In ilasm/tests:
[mcs.git] / class / PEAPI / Metadata.cs
blob5515cc8c669214e3f5d9ba36d8d1df0135e45dad
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Text;
6 namespace PEAPI {
8 #region Enums
10 /// <summary>
11 /// flags for the assembly (.corflags)
12 /// </summary>
13 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
14 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
16 /// <summary>
17 /// subsystem for the assembly (.subsystem)
18 /// </summary>
19 public enum SubSystem { Native = 1, Windows_GUI = 2,
20 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
21 Windows_CE_GUI = 9}
23 /// <summary>
24 /// Hash algorithms for the assembly
25 /// </summary>
26 public enum HashAlgorithm { None, SHA1 }
28 /// <summary>
29 /// Attributes for this assembly
30 /// </summary>
31 public enum AssemAttr { EnableJITCompileTracking = 0x8000,
32 DisableJITCompileOptimizer = 0x4000}
34 /// <summary>
35 /// Method call conventions
36 /// </summary>
37 [Flags]
38 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
39 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
41 /// <summary>
42 /// Type custom modifier
43 /// </summary>
44 public enum CustomModifier { modreq = 0x1F, modopt };
46 /// <summary>
47 /// Attibutes for a class
48 /// </summary>
49 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
50 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
51 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
52 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
53 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
54 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
55 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
56 VisibilityMask = 0x07 }
58 /// <summary>
59 /// Attributes for a field
60 /// </summary>
61 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
62 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
63 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
64 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
66 /// <summary>
67 /// Attributes for a method
68 /// </summary>
69 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
70 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
71 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
72 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
73 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
74 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
75 HasSecurity = 0x4000, RequireSecObject = 0x8000}
77 /// <summary>
78 /// Attributes for .pinvokeimpl method declarations
79 /// </summary>
80 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
81 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
82 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
84 /// <summary>
85 /// Implementation attributes for a method
86 /// </summary>
87 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
88 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
89 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
91 /// <summary>
92 /// Modes for a parameter
93 /// </summary>
94 public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
96 /// <summary>
97 /// CIL instructions
98 /// </summary>
99 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
100 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
101 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
102 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
103 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
104 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
105 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
106 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
107 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
108 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
109 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
110 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
111 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
112 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
113 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
114 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
115 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
116 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
117 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
118 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
119 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
120 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
122 /// <summary>
123 /// CIL instructions requiring an integer parameter
124 /// </summary>
125 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
126 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
127 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
129 /// <summary>
130 /// CIL instructions requiring a field parameter
131 /// </summary>
132 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
133 stsfld, ldtoken = 0xD0 }
135 /// <summary>
136 /// CIL instructions requiring a method parameter
137 /// </summary>
138 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
139 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
141 /// <summary>
142 /// CIL instructions requiring a type parameter
143 /// </summary>
144 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
145 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
146 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
147 ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
148 ldelem = 0xA3, stelem = 0xA4, unbox_any }
150 /// <summary>
151 /// CIL branch instructions
152 /// </summary>
153 public enum BranchOp {
154 // short branches
155 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
156 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
157 // long branches
158 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
159 bne_un, bge_un, bgt_un, ble_un, blt_un,
161 leave = 0xDD, leave_s }
163 /// <summary>
164 /// Index for all the tables in the meta data
165 /// </summary>
166 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
167 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
168 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
169 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
170 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
171 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
172 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
173 GenericParam, MethodSpec, GenericParamConstraint }
175 public enum SafeArrayType { int16 = 2, int32, float32, float64,
176 currency, date, bstr, dispatch, error, boolean, variant, unknown,
177 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
179 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
180 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
181 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
182 TypeOrMethodDef, MaxCIx }
184 internal enum MapType { eventMap, propertyMap, nestedClass }
186 public enum ValueClass { ValueType, Enum }
188 public enum GenParamType : byte {
189 Var = 0x13, MVar = 0x1E
192 /* Taken from Mono.Cecil */
193 public enum SecurityAction : short {
194 Request = 1,
195 Demand = 2,
196 Assert = 3,
197 Deny = 4,
198 PermitOnly = 5,
199 LinkDemand = 6,
200 InheritDemand = 7,
201 RequestMinimum = 8,
202 RequestOptional = 9,
203 RequestRefuse = 10,
204 PreJitGrant = 11,
205 PreJitDeny = 12,
206 NonCasDemand = 13,
207 NonCasLinkDemand = 14,
208 NonCasInheritance = 15,
209 LinkDemandChoice = 16,
210 InheritDemandChoice = 17,
211 DemandChoice = 18
214 #endregion
216 /**************************************************************************/
217 /// <summary>
218 /// Base class for all Meta Data table elements
219 /// </summary>
221 public abstract class MetaDataElement: IComparable {
222 protected ArrayList customAttributes;
223 private uint row = 0;
224 protected bool done = false;
225 protected MDTable tabIx;
226 protected bool sortTable = false;
228 internal MetaDataElement() { }
230 public uint Row {
231 get {
232 return row;
234 set {
235 if (row == 0) row = value;
239 internal virtual uint GetCodedIx(CIx code) { return 0; }
241 /// <summary>
242 /// Add a custom attribute to this item
243 /// </summary>
244 /// <param name="ctorMeth">the constructor method for this attribute</param>
245 /// <param name="val">the byte value of the parameters</param>
246 public void AddCustomAttribute(Method ctorMeth, byte[] val)
248 if (customAttributes == null) {
249 customAttributes = new ArrayList();
251 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
254 /// <summary>
255 /// Add a custom attribute to this item
256 /// </summary>
257 /// <param name="ctorMeth">the constructor method for this attribute</param>
258 /// <param name="val">the constant values of the parameters</param>
259 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals)
261 if (customAttributes == null) {
262 customAttributes = new ArrayList();
264 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
267 internal uint Token()
269 return (((uint)tabIx << 24) | row);
272 internal virtual void BuildTables(MetaData md)
274 done = true;
277 internal virtual uint Size(MetaData md)
279 return 0;
282 internal virtual void Write(FileImage output) { }
284 internal virtual uint SortKey()
286 throw new PEFileException("Trying to sort table of " + this);
287 //return 0;
290 internal virtual uint SortKey2()
292 return 0;
295 public int CompareTo(object obj)
297 uint otherKey = ((MetaDataElement)obj).SortKey();
298 uint thisKey = SortKey();
300 if (thisKey == otherKey) {
302 otherKey = ((MetaDataElement)obj).SortKey2();
303 thisKey = SortKey2();
304 if (thisKey == otherKey)
305 return 0;
306 if (thisKey < otherKey)
307 return -1;
308 return 1;
310 if (thisKey < otherKey) return -1;
312 return 1;
317 /**************************************************************************/
318 /// <summary>
319 /// Layout information for a class (.class [sequential | explicit])
320 /// </summary>
321 internal class ClassLayout : MetaDataElement {
323 ClassDef parent;
324 ushort packSize = 0;
325 uint classSize = 0;
327 internal ClassLayout(int pack, int cSize, ClassDef par)
329 packSize = (ushort)pack;
330 classSize = (uint)cSize;
331 parent = par;
332 tabIx = MDTable.ClassLayout;
335 internal sealed override uint Size(MetaData md)
337 return 6 + md.TableIndexSize(MDTable.TypeDef);
340 internal sealed override void Write(FileImage output)
342 output.Write(packSize);
343 output.Write(classSize);
344 output.WriteIndex(MDTable.TypeDef,parent.Row);
349 /**************************************************************************/
350 /// <summary>
351 /// Summary description for ConstantElem.
352 /// </summary>
353 internal class ConstantElem : MetaDataElement {
355 MetaDataElement parent;
356 Constant cValue;
357 uint valIx = 0;
359 internal ConstantElem(MetaDataElement parent, Constant val)
361 this.parent = parent;
362 cValue = val;
363 tabIx = MDTable.Constant;
364 sortTable = true;
367 internal override uint SortKey()
369 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
370 | parent.GetCodedIx(CIx.HasConst);
373 internal sealed override void BuildTables(MetaData md)
375 if (done) return;
376 valIx = cValue.GetBlobIndex(md);
377 done = true;
380 internal void AddToBlob(BinaryWriter bw)
382 cValue.Write(bw);
385 internal sealed override uint Size(MetaData md)
387 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
390 internal sealed override void Write(FileImage output)
392 output.Write(cValue.GetTypeIndex());
393 output.Write((byte)0);
394 output.WriteCodedIndex(CIx.HasConst,parent);
395 output.BlobIndex(valIx);
399 /**************************************************************************/
400 /// <summary>
401 /// Descriptor for a Custom Attribute (.custom)
402 /// </summary>
404 public class CustomAttribute : MetaDataElement {
406 private static readonly ushort prolog = 0x0001;
407 MetaDataElement parent;
408 Method type;
409 uint valIx;
410 Constant cVal;
411 byte[] byteVal;
412 ushort numNamed = 0;
413 ArrayList names, vals;
415 internal CustomAttribute(MetaDataElement paren, Method constrType,
416 Constant val) {
417 parent = paren;
418 type = constrType;
419 cVal = val;
420 tabIx = MDTable.CustomAttribute;
423 internal CustomAttribute(MetaDataElement paren, Method constrType,
424 byte[] val) {
425 parent = paren;
426 type = constrType;
427 tabIx = MDTable.CustomAttribute;
428 byteVal = val;
431 internal override uint SortKey()
433 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
434 | parent.GetCodedIx(CIx.HasCustomAttr);
437 public void AddFieldOrProp(string name, Constant val)
439 if (numNamed == 0) {
440 names = new ArrayList();
441 vals = new ArrayList();
443 names.Add(name);
444 vals.Add(val);
447 internal sealed override void BuildTables(MetaData md)
449 BinaryWriter bw = new BinaryWriter(new MemoryStream());
450 bw.Write(byteVal);
451 md.AddToTable(MDTable.CustomAttribute, this);
452 MemoryStream str = (MemoryStream)bw.BaseStream;
453 valIx = md.AddToBlobHeap(str.ToArray());
456 internal sealed override uint Size(MetaData md)
458 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
461 internal sealed override void Write(FileImage output)
463 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
464 output.WriteCodedIndex(CIx.CustomAttributeType,type);
465 output.BlobIndex(valIx);
470 /**************************************************************************/
471 /// <summary>
472 /// Descriptor for security permissions for a class or a method
473 /// </summary>
475 public class DeclSecurity : MetaDataElement {
477 ushort action;
478 MetaDataElement parent;
479 uint permissionIx;
480 byte [] byteVal;
482 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
484 parent = paren;
485 action = act;
486 tabIx = MDTable.DeclSecurity;
487 byteVal = val;
490 internal override uint SortKey()
492 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
493 | parent.GetCodedIx(CIx.HasDeclSecurity);
496 internal sealed override uint Size(MetaData md)
498 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
501 internal sealed override void BuildTables(MetaData md)
503 if (done) return;
504 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
505 bw.Write (byteVal);
506 md.AddToTable (MDTable.DeclSecurity, this);
507 MemoryStream str = (MemoryStream)bw.BaseStream;
508 permissionIx = md.AddToBlobHeap(str.ToArray());
510 done = true;
513 internal sealed override void Write(FileImage output)
515 output.Write(action);
516 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
517 output.BlobIndex(permissionIx);
522 /**************************************************************************/
523 /// <summary>
524 /// Descriptor for layout information for a field
525 /// </summary>
527 public class FieldLayout : MetaDataElement {
529 Field field;
530 uint offset;
532 internal FieldLayout(Field field, uint offset)
534 this.field = field;
535 this.offset = offset;
536 tabIx = MDTable.FieldLayout;
539 internal sealed override uint Size(MetaData md)
541 return 4 + md.TableIndexSize(MDTable.Field);
544 internal sealed override void Write(FileImage output)
546 output.Write(offset);
547 output.WriteIndex(MDTable.Field,field.Row);
552 /*****************************************************************************/
553 /// <summary>
554 /// Marshalling information for a field or param
555 /// </summary>
556 public class FieldMarshal : MetaDataElement {
558 MetaDataElement field;
559 NativeType nt;
560 uint ntIx;
562 internal FieldMarshal(MetaDataElement field, NativeType nType)
564 this.field = field;
565 this.nt = nType;
566 tabIx = MDTable.FieldMarshal;
569 internal override uint SortKey()
571 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
572 | field.GetCodedIx(CIx.HasFieldMarshal);
575 internal sealed override void BuildTables(MetaData md)
577 if (done) return;
578 ntIx = md.AddToBlobHeap(nt.ToBlob());
579 done = true;
582 internal sealed override uint Size(MetaData md)
584 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
587 internal sealed override void Write(FileImage output)
589 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
590 output.BlobIndex(ntIx);
595 /**************************************************************************/
596 /// <summary>
597 /// Descriptor for the address of a field's value in the PE file
598 /// </summary>
599 public class FieldRVA : MetaDataElement {
601 Field field;
602 DataConstant data;
604 internal FieldRVA(Field field, DataConstant data)
606 this.field = field;
607 this.data = data;
608 tabIx = MDTable.FieldRVA;
611 internal sealed override void BuildTables(MetaData md)
613 if (done) return;
614 md.AddData(data);
615 done = true;
618 internal sealed override uint Size(MetaData md)
620 return 4 + md.TableIndexSize(MDTable.Field);
623 internal sealed override void Write(FileImage output)
625 output.WriteDataRVA(data.DataOffset);
626 output.WriteIndex(MDTable.Field,field.Row);
631 /**************************************************************************/
632 /// <summary>
633 /// Descriptor for a file referenced in THIS assembly/module (.file)
634 /// </summary>
635 public class FileRef : MetaDataElement {
637 private static readonly uint NoMetaData = 0x1;
638 uint nameIx = 0, hashIx = 0;
639 uint flags = 0;
640 protected string name;
642 internal FileRef(string name, byte[] hashBytes, bool metaData,
643 bool entryPoint, MetaData md) {
644 if (!metaData) flags = NoMetaData;
645 if (entryPoint) md.SetEntryPoint(this);
646 this.name = name;
647 nameIx = md.AddToStringsHeap(name);
648 hashIx = md.AddToBlobHeap(hashBytes);
649 tabIx = MDTable.File;
652 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
653 bool entryPoint, MetaData md) {
654 if (!metaData) flags = NoMetaData;
655 if (entryPoint) md.SetEntryPoint(this);
656 this.nameIx = nameIx;
657 hashIx = md.AddToBlobHeap(hashBytes);
658 tabIx = MDTable.File;
661 internal sealed override uint Size(MetaData md)
663 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
666 internal sealed override void BuildTables(MetaData md)
668 md.AddToTable(MDTable.File,this);
671 internal sealed override void Write(FileImage output)
673 output.Write(flags);
674 output.StringsIndex(nameIx);
675 output.BlobIndex(hashIx);
678 internal sealed override uint GetCodedIx(CIx code)
680 switch (code) {
681 case (CIx.HasCustomAttr) : return 16;
682 case (CIx.Implementation) : return 0;
684 return 0;
688 /**************************************************************************/
689 /// <summary>
690 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
691 /// </summary>
692 public class ImplMap : MetaDataElement {
694 private static readonly ushort NoMangle = 0x01;
695 ushort flags;
696 Method meth;
697 string importName;
698 uint iNameIx;
699 ModuleRef importScope;
701 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
703 flags = flag;
704 meth = implMeth;
705 importName = iName;
706 importScope = mScope;
707 tabIx = MDTable.ImplMap;
708 if (iName == null) flags |= NoMangle;
709 //throw(new NotYetImplementedException("PInvoke "));
712 internal override uint SortKey()
714 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
715 | meth.GetCodedIx(CIx.MemberForwarded);
718 internal sealed override void BuildTables(MetaData md)
720 if (done) return;
721 iNameIx = md.AddToStringsHeap(importName);
722 done = true;
725 internal sealed override uint Size(MetaData md)
727 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
728 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
731 internal sealed override void Write(FileImage output)
733 output.Write(flags);
734 output.WriteCodedIndex(CIx.MemberForwarded,meth);
735 output.StringsIndex(iNameIx);
736 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
741 /**************************************************************************/
743 public class GenericParameter : MetaDataElement {
745 MetaDataElement owner;
746 MetaData metadata;
747 string name;
748 uint nameIx;
749 short index;
751 internal GenericParameter (ClassDef owner, MetaData metadata,
752 short index, string name) : this (owner, metadata, index, name, true)
756 internal GenericParameter (MethodDef owner, MetaData metadata,
757 short index, string name) : this (owner, metadata, index, name, true)
761 private GenericParameter (MetaDataElement owner, MetaData metadata,
762 short index, string name, bool nadda) {
763 this.owner = owner;
764 this.metadata = metadata;
765 this.index = index;
766 tabIx = MDTable.GenericParam;
767 this.name = name;
770 internal override uint SortKey()
772 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
773 | owner.GetCodedIx(CIx.TypeOrMethodDef);
776 internal override uint SortKey2 ()
778 return (uint) index;
781 public void AddConstraint (Type constraint)
783 metadata.AddToTable (MDTable.GenericParamConstraint,
784 new GenericParamConstraint (this, constraint));
787 internal sealed override uint Size(MetaData md)
789 return (uint) (4 +
790 md.CodedIndexSize(CIx.TypeOrMethodDef) +
791 md.StringsIndexSize ());
794 internal sealed override void BuildTables(MetaData md)
796 if (done) return;
797 nameIx = md.AddToStringsHeap(name);
798 done = true;
801 internal sealed override void Write(FileImage output)
803 output.Write ((short) index);
804 output.Write ((short) 0);
805 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
806 output.StringsIndex (nameIx);
812 internal class GenericParamConstraint : MetaDataElement {
814 GenericParameter param;
815 Type type;
817 public GenericParamConstraint (GenericParameter param, Type type)
819 this.param = param;
820 this.type = type;
821 tabIx = MDTable.GenericParamConstraint;
824 internal sealed override uint Size(MetaData md)
826 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
827 md.CodedIndexSize(CIx.TypeDefOrRef));
830 internal sealed override void Write(FileImage output)
832 output.WriteIndex(MDTable.GenericParam, param.Row);
833 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
838 internal class MethodSpec : Method {
840 Method meth;
841 GenericMethodSig g_sig;
842 uint sidx;
844 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
846 this.meth = meth;
847 this.g_sig = g_sig;
848 tabIx = MDTable.MethodSpec;
851 internal override uint GetSigIx (MetaData md)
853 throw new Exception ("Should not be used.");
856 public override void AddCallConv (CallConv cconv)
858 throw new Exception ("Should not be used.");
861 internal sealed override void BuildTables (MetaData md)
863 if (done) return;
864 sidx = g_sig.GetSigIx (md);
865 done = true;
868 internal sealed override uint Size (MetaData md)
870 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
871 md.BlobIndexSize ());
874 internal sealed override void Write (FileImage output)
876 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
877 output.BlobIndex (sidx);
880 internal sealed override void TypeSig (MemoryStream sig)
882 throw new Exception ("Should not be used.");
886 /**************************************************************************/
887 /// <summary>
888 /// Descriptor for interface implemented by a class
889 /// </summary>
890 public class InterfaceImpl: MetaDataElement {
892 ClassDef theClass;
893 Class theInterface;
895 internal InterfaceImpl(ClassDef theClass, Class theInterface)
897 this.theClass = theClass;
898 this.theInterface = theInterface;
899 tabIx = MDTable.InterfaceImpl;
902 internal sealed override uint Size(MetaData md)
904 return md.TableIndexSize(MDTable.TypeDef) +
905 md.CodedIndexSize(CIx.TypeDefOrRef);
908 internal sealed override void Write(FileImage output)
910 output.WriteIndex(MDTable.TypeDef,theClass.Row);
911 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
914 internal sealed override uint GetCodedIx(CIx code) { return 5; }
916 internal override uint SortKey ()
918 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
919 | theClass.GetCodedIx (CIx.TypeDefOrRef);
924 /**************************************************************************/
925 /// <summary>
926 /// Descriptor for resources used in this PE file
927 /// </summary>
929 public class ManifestResource : MetaDataElement {
931 public static readonly uint PublicResource = 0x1;
932 public static readonly uint PrivateResource = 0x2;
934 string mrName;
935 MetaDataElement rRef;
936 uint fileOffset;
937 uint nameIx = 0;
938 uint flags = 0;
939 byte [] resourceBytes;
941 public ManifestResource (string name, byte[] resBytes, uint flags)
943 InitResource (name, flags);
944 this.resourceBytes = resBytes;
947 public ManifestResource(string name, uint flags, FileRef fileRef)
949 InitResource (name, flags);
950 rRef = fileRef;
953 public ManifestResource(string name, uint flags, FileRef fileRef,
954 uint fileIx) {
955 InitResource (name, flags);
956 rRef = fileRef;
957 fileOffset = fileIx;
960 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
962 InitResource (name, flags);
963 rRef = assemRef;
966 internal ManifestResource (ManifestResource mres)
968 mrName = mres.mrName;
969 flags = mres.flags;
970 rRef = mres.rRef;
971 fileOffset = mres.fileOffset;
972 resourceBytes = mres.resourceBytes;
975 private void InitResource (string name, uint flags)
977 mrName = name;
978 this.flags = flags;
979 tabIx = MDTable.ManifestResource;
982 internal sealed override void BuildTables(MetaData md)
984 if (done) return;
985 md.AddToTable (MDTable.ManifestResource, this);
986 nameIx = md.AddToStringsHeap(mrName);
987 if (resourceBytes != null) {
988 if (rRef != null)
989 throw new Exception("ERROR: Manifest Resource has byte value and file reference");
990 fileOffset = md.AddResource(resourceBytes);
991 } else {
992 if (rRef == null)
993 throw new Exception("ERROR: Manifest Resource has no implementation or value");
994 rRef.BuildTables (md);
997 done = true;
1000 internal sealed override uint Size(MetaData md)
1002 return 8 + md.StringsIndexSize() +
1003 md.CodedIndexSize(CIx.Implementation);
1006 internal sealed override void Write(FileImage output)
1008 output.Write(fileOffset);
1009 output.Write(flags);
1010 output.StringsIndex(nameIx);
1011 output.WriteCodedIndex(CIx.Implementation,rRef);
1014 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1016 public string Name {
1017 get { return mrName; }
1018 set { mrName = value; }
1022 /**************************************************************************/
1023 /// <summary>
1024 /// Base class for elements in the PropertyMap, EventMap and
1025 /// NestedClass MetaData tables
1026 /// </summary>
1027 public class MapElem : MetaDataElement {
1029 ClassDef parent;
1030 uint elemIx;
1031 MDTable elemTable;
1033 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1035 parent = par;
1036 elemIx = elIx;
1037 elemTable = elemTab;
1040 internal sealed override uint Size(MetaData md)
1042 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1045 internal sealed override void Write(FileImage output)
1047 output.WriteIndex(MDTable.TypeDef,parent.Row);
1048 output.WriteIndex(elemTable,elemIx);
1052 /**************************************************************************/
1053 /// <summary>
1054 /// Descriptor for an overriding method (.override)
1055 /// </summary>
1056 public class MethodImpl : MetaDataElement {
1058 ClassDef parent;
1059 Method header, body;
1061 internal MethodImpl(ClassDef par, Method decl, Method bod)
1063 parent = par;
1064 header = decl;
1065 body = bod;
1066 tabIx = MDTable.MethodImpl;
1069 internal sealed override uint Size(MetaData md)
1071 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1074 internal sealed override void Write(FileImage output)
1076 output.WriteIndex(MDTable.TypeDef,parent.Row);
1077 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1078 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1083 /**************************************************************************/
1084 /// <summary>
1085 /// Descriptor for Property and Event methods
1086 /// </summary>
1087 public class MethodSemantics : MetaDataElement {
1089 Feature.MethodType type;
1090 MethodDef meth;
1091 Feature eventOrProp;
1093 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1095 type = mType;
1096 meth = method;
1097 eventOrProp = feature;
1098 tabIx = MDTable.MethodSemantics;
1101 internal override uint SortKey()
1103 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1104 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1107 internal sealed override uint Size(MetaData md)
1109 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1112 internal sealed override void Write(FileImage output)
1114 output.Write((ushort)type);
1115 output.WriteIndex(MDTable.Method,meth.Row);
1116 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1121 /**************************************************************************/
1122 /// <summary>
1123 /// Descriptor for a parameter of a method defined in this assembly/module
1124 /// </summary>
1125 public class Param : MetaDataElement {
1128 Type pType;
1129 string pName;
1130 internal ushort seqNo = 0;
1131 ushort parMode;
1132 ConstantElem defaultVal;
1133 uint nameIx = 0;
1134 FieldMarshal marshalInfo;
1136 /// <summary>
1137 /// Create a new parameter for a method
1138 /// </summary>
1139 /// <param name="mode">param mode (in, out, opt)</param>
1140 /// <param name="parName">parameter name</param>
1141 /// <param name="parType">parameter type</param>
1142 public Param(ParamAttr mode, string parName, Type parType)
1144 pName = parName;
1145 pType = parType;
1146 parMode = (ushort)mode;
1147 tabIx = MDTable.Param;
1150 /// <summary>
1151 /// Add a default value to this parameter
1152 /// </summary>
1153 /// <param name="c">the default value for the parameter</param>
1154 public void AddDefaultValue(Constant cVal)
1156 defaultVal = new ConstantElem(this,cVal);
1157 parMode |= (ushort) ParamAttr.HasDefault;
1160 /// <summary>
1161 /// Add marshalling information about this parameter
1162 /// </summary>
1163 public void AddMarshallInfo(NativeType marshallType)
1165 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1166 marshalInfo = new FieldMarshal(this,marshallType);
1169 internal Type GetParType() { return pType; }
1171 internal sealed override void BuildTables(MetaData md)
1173 if (done) return;
1174 nameIx = md.AddToStringsHeap(pName);
1175 if (defaultVal != null) {
1176 md.AddToTable(MDTable.Constant,defaultVal);
1177 defaultVal.BuildTables(md);
1179 if (marshalInfo != null) {
1180 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1181 marshalInfo.BuildTables(md);
1183 done = true;
1186 internal void TypeSig(MemoryStream str)
1188 pType.TypeSig(str);
1191 internal sealed override uint Size(MetaData md)
1193 return 4 + md.StringsIndexSize();
1196 internal sealed override void Write(FileImage output)
1198 output.Write(parMode);
1199 output.Write(seqNo);
1200 output.StringsIndex(nameIx);
1203 internal sealed override uint GetCodedIx(CIx code)
1205 switch (code) {
1206 case (CIx.HasCustomAttr) : return 4;
1207 case (CIx.HasConst) : return 1;
1208 case (CIx.HasFieldMarshal) : return 1;
1210 return 0;
1215 /**************************************************************************/
1216 public abstract class Signature : MetaDataElement {
1218 protected uint sigIx;
1220 internal Signature()
1222 tabIx = MDTable.StandAloneSig;
1225 internal sealed override uint Size(MetaData md)
1227 return md.BlobIndexSize();
1230 internal sealed override void Write(FileImage output)
1232 output.BlobIndex(sigIx);
1235 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1239 /**************************************************************************/
1240 public class TypeSpec : MetaDataElement {
1241 uint sigIx = 0;
1243 internal TypeSpec(Type aType, MetaData md)
1245 MemoryStream sig = new MemoryStream();
1246 aType.TypeSig(sig);
1247 sigIx = md.AddToBlobHeap(sig.ToArray());
1248 tabIx = MDTable.TypeSpec;
1251 internal sealed override uint GetCodedIx(CIx code)
1253 switch (code) {
1254 case (CIx.TypeDefOrRef) : return 2;
1255 case (CIx.HasCustomAttr) : return 13;
1256 case (CIx.MemberRefParent) : return 4;
1258 return 0;
1261 internal override uint Size(MetaData md)
1263 return md.BlobIndexSize();
1266 internal sealed override void Write(FileImage output)
1268 //Console.WriteLine("Writing the blob index for a TypeSpec");
1269 output.BlobIndex(sigIx);
1274 /**************************************************************************/
1275 /// <summary>
1276 /// Base class for all IL types
1277 /// </summary>
1278 public abstract class Type : MetaDataElement {
1279 protected byte typeIndex;
1280 protected TypeSpec typeSpec;
1282 internal Type(byte tyIx) { typeIndex = tyIx; }
1284 internal byte GetTypeIndex() { return typeIndex; }
1285 internal void SetTypeIndex (byte b) { typeIndex = b; }
1287 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1289 if (typeSpec == null) {
1290 typeSpec = new TypeSpec(this,md);
1291 md.AddToTable(MDTable.TypeSpec,typeSpec);
1293 return typeSpec;
1296 internal virtual void TypeSig(MemoryStream str)
1298 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1299 " doesn't have a type signature!!"));
1303 public class ClassRefInst : Type {
1305 private Type type;
1306 private bool is_value;
1308 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1310 this.type = type;
1311 this.is_value = is_value;
1312 if (is_value)
1313 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1314 tabIx = MDTable.TypeSpec;
1317 internal sealed override void TypeSig(MemoryStream str)
1319 type.TypeSig (str);
1323 /**************************************************************************/
1324 /// <summary>
1325 /// The base descriptor for a class
1326 /// </summary>
1327 public abstract class Class : Type {
1329 protected int row = 0;
1330 public string name, nameSpace;
1331 protected uint nameIx, nameSpaceIx;
1332 protected MetaData _metaData;
1333 internal Class(string nameSpaceName, string className, MetaData md)
1334 : base(PrimitiveType.Class.GetTypeIndex ())
1336 nameSpace = nameSpaceName;
1337 name = className;
1338 nameIx = md.AddToStringsHeap(name);
1339 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1340 _metaData = md;
1343 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1345 nameSpaceIx = nsIx;
1346 nameIx = nIx;
1349 internal Class (byte typeIndex) : base (typeIndex)
1351 nameSpace = "Should not be used";
1352 name = "Should not be used";
1355 internal virtual uint TypeDefOrRefToken() { return 0; }
1357 internal virtual void MakeValueClass(ValueClass vClass)
1359 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1362 internal virtual string TypeName()
1364 return (nameSpace + "." + name);
1367 internal override MetaDataElement GetTypeSpec(MetaData md)
1369 return this;
1373 /**************************************************************************/
1374 // This Class produces entries in the TypeDef table of the MetaData
1375 // in the PE meta data.
1377 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1378 // which is the parent for functions and variables declared a module level
1380 /// <summary>
1381 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1382 /// </summary>
1383 ///
1384 public class ClassDef : Class {
1386 private static readonly byte ElementType_Class = 0x12;
1388 Class superType;
1389 ArrayList fields = new ArrayList();
1390 ArrayList methods = new ArrayList();
1391 ArrayList events;
1392 ArrayList properties;
1393 bool typeIndexChecked = true;
1394 uint fieldIx = 0, methodIx = 0;
1395 byte[] securityActions;
1396 uint flags;
1397 ClassLayout layout;
1398 ClassDef parentClass;
1399 MetaData metaData;
1401 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1402 MetaData md) : base(nsName, name, md)
1404 metaData = md;
1405 if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1406 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1408 flags = (uint)attrSet;
1409 tabIx = MDTable.TypeDef;
1412 internal void SetSuper(Class sClass)
1414 superType = sClass;
1415 if (! (sClass is GenericTypeInst))
1416 typeIndexChecked = false;
1419 internal override void MakeValueClass(ValueClass vClass)
1421 if (vClass == ValueClass.Enum)
1422 superType = metaData.mscorlib.EnumType();
1423 else
1424 superType = metaData.mscorlib.ValueType();
1426 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1429 public void SpecialNoSuper()
1431 superType = null;
1434 /// <summary>
1435 /// Add an attribute to this class
1436 /// </summary>
1437 /// <param name="ta">the attribute to be added</param>
1438 public void AddAttribute(TypeAttr ta)
1440 flags |= (uint)ta;
1443 /// <summary>
1444 /// Add an interface that is implemented by this class
1445 /// </summary>
1446 /// <param name="iFace">the interface that is implemented</param>
1447 public void AddImplementedInterface(Class iFace)
1449 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1452 /// <summary>
1453 /// Add a named generic type parameter
1454 /// </summary>
1455 public GenericParameter AddGenericParameter (short index, string name)
1457 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1458 metaData.AddToTable (MDTable.GenericParam, gp);
1459 return gp;
1462 /// <summary>
1463 /// Add a field to this class
1464 /// </summary>
1465 /// <param name="name">field name</param>
1466 /// <param name="fType">field type</param>
1467 /// <returns>a descriptor for this new field</returns>
1468 public FieldDef AddField(string name, Type fType)
1470 FieldDef field = new FieldDef(name,fType);
1471 fields.Add(field);
1472 return field;
1475 /// <summary>
1476 /// Add a field to this class
1477 /// </summary>
1478 /// <param name="fAtts">attributes for this field</param>
1479 /// <param name="name">field name</param>
1480 /// <param name="fType">field type</param>
1481 /// <returns>a descriptor for this new field</returns>
1482 public FieldDef AddField(FieldAttr fAtts, string name, Type fType)
1484 FieldDef field = new FieldDef(fAtts,name,fType);
1485 fields.Add(field);
1486 return field;
1489 public void SetFieldOrder (ArrayList fields)
1491 this.fields = fields;
1494 /// <summary>
1495 /// Add a method to this class
1496 /// </summary>
1497 /// <param name="name">method name</param>
1498 /// <param name="retType">return type</param>
1499 /// <param name="pars">parameters</param>
1500 /// <returns>a descriptor for this new method</returns>
1501 public MethodDef AddMethod(string name, Type retType, Param[] pars)
1503 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1504 MethodDef meth = new MethodDef(metaData,name,retType, pars);
1505 methods.Add(meth);
1506 return meth;
1509 /// <summary>
1510 /// Add a method to this class
1511 /// </summary>
1512 /// <param name="mAtts">attributes for this method</param>
1513 /// <param name="iAtts">implementation attributes for this method</param>
1514 /// <param name="name">method name</param>
1515 /// <param name="retType">return type</param>
1516 /// <param name="pars">parameters</param>
1517 /// <returns>a descriptor for this new method</returns>
1518 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1519 Type retType, Param[] pars) {
1520 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1521 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
1522 methods.Add(meth);
1523 return meth;
1526 /// <summary>
1527 /// Add an event to this class
1528 /// </summary>
1529 /// <param name="name">event name</param>
1530 /// <param name="eType">event type</param>
1531 /// <returns>a descriptor for this new event</returns>
1532 public Event AddEvent(string name, Type eType)
1534 Event e = new Event(name,eType,this);
1535 if (events == null) events = new ArrayList();
1536 events.Add(e);
1537 return e;
1540 /// <summary>
1541 /// Add a property to this class
1542 /// </summary>
1543 /// <param name="name">property name</param>
1544 /// <param name="propType">property type</param>
1545 /// <returns>a descriptor for this new property</returns>
1546 public Property AddProperty(string name, Type retType, Type[] pars)
1548 Property p = new Property(name, retType, pars, this);
1549 if (properties == null) properties = new ArrayList();
1550 properties.Add(p);
1551 return p;
1554 /// <summary>
1555 /// Add a nested class to this class
1556 /// </summary>
1557 /// <param name="attrSet">attributes for this nested class</param>
1558 /// <param name="nsName">nested name space name</param>
1559 /// <param name="name">nested class name</param>
1560 /// <returns>a descriptor for this new nested class</returns>
1561 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1562 string name) {
1563 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1564 metaData.AddToTable(MDTable.TypeDef,nClass);
1565 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1566 nClass.parentClass = this;
1567 return (nClass);
1570 public static bool IsValueType (Class type)
1572 return IsValueType (type.nameSpace, type.name);
1575 public static bool IsEnum (Class type)
1577 return IsEnum (type.nameSpace, type.name);
1580 public static bool IsValueType (string nsName, string name)
1582 return (nsName == "System" && name == "ValueType");
1585 public static bool IsEnum (string nsName, string name)
1587 return (nsName == "System" && name == "Enum");
1590 /// <summary>
1591 /// Add a nested class to this class
1592 /// </summary>
1593 /// <param name="attrSet">attributes for this nested class</param>
1594 /// <param name="nsName">nested name space name</param>
1595 /// <param name="name">nested class name</param>
1596 /// <param name="sType">super type of this nested class</param>
1597 /// <returns>a descriptor for this new nested class</returns>
1598 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1599 string name, Class sType) {
1600 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1601 nClass.SetSuper(sType);
1602 if (ClassDef.IsValueType (sType))
1603 nClass.MakeValueClass (ValueClass.ValueType);
1604 else
1605 if (ClassDef.IsEnum (sType))
1606 nClass.MakeValueClass (ValueClass.Enum);
1608 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1609 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1611 nClass.typeIndexChecked = true;
1612 return (nClass);
1615 /// <summary>
1616 /// Add layout information for this class. This class must have the
1617 /// sequential or explicit attribute.
1618 /// </summary>
1619 /// <param name="packSize">packing size (.pack)</param>
1620 /// <param name="classSize">class size (.size)</param>
1621 public void AddLayoutInfo (int packSize, int classSize)
1623 layout = new ClassLayout(packSize,classSize,this);
1626 /// <summary>
1627 /// Use a method as the implementation for another method (.override)
1628 /// </summary>
1629 /// <param name="decl">the method to be overridden</param>
1630 /// <param name="body">the implementation to be used</param>
1631 public void AddMethodOverride(Method decl, Method body)
1633 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1636 /// <summary>
1637 /// Add security to this class NOT YET IMPLEMENTED
1638 /// </summary>
1639 /// <param name="permissionSet"></param>
1640 public void AddSecurity(byte[] permissionSet)
1642 throw(new NotYetImplementedException("Class security "));
1643 //flags |= HasSecurity;
1644 // securityActions = permissionSet;
1647 //public void AddLineInfo(int row, int col) { }
1649 internal void CheckTypeIndex()
1651 if (typeIndexChecked) return;
1652 if (superType is ClassDef)
1653 ((ClassDef)superType).CheckTypeIndex();
1654 typeIndex = superType.GetTypeIndex();
1655 typeIndexChecked = true;
1658 internal sealed override void BuildTables(MetaData md)
1660 if (done) return;
1661 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1662 // Console.WriteLine("Building tables for " + name);
1663 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1664 // Console.WriteLine("adding methods " + methods.Count);
1665 methodIx = md.TableIndex(MDTable.Method);
1666 for (int i=0; i < methods.Count; i++) {
1667 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1668 ((MethodDef)methods[i]).BuildTables(md);
1670 // Console.WriteLine("adding fields");
1671 fieldIx = md.TableIndex(MDTable.Field);
1672 for (int i=0; i < fields.Count; i++) {
1673 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1674 ((FieldDef)fields[i]).BuildTables(md);
1676 // Console.WriteLine("adding events and properties");
1677 if (events != null) {
1678 for (int i=0; i < events.Count; i++) {
1679 md.AddToTable(MDTable.Event,(Event)events[i]);
1680 ((Event)events[i]).BuildTables(md);
1682 md.AddToTable(MDTable.EventMap,
1683 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1685 if (properties != null) {
1686 for (int i=0; i < properties.Count; i++) {
1687 md.AddToTable(MDTable.Property,(Property)properties[i]);
1688 ((Property)properties[i]).BuildTables(md);
1690 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1691 ((Property)properties[0]).Row,MDTable.Property));
1693 // Console.WriteLine("End of building tables");
1694 done = true;
1697 internal sealed override uint Size(MetaData md)
1699 return 4 + 2 * md.StringsIndexSize() +
1700 md.CodedIndexSize(CIx.TypeDefOrRef) +
1701 md.TableIndexSize(MDTable.Field) +
1702 md.TableIndexSize(MDTable.Method);
1705 internal sealed override void Write(FileImage output)
1707 output.Write(flags);
1708 output.StringsIndex(nameIx);
1709 output.StringsIndex(nameSpaceIx);
1710 //if (superType != null)
1711 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1712 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1713 output.WriteIndex(MDTable.Field,fieldIx);
1714 output.WriteIndex(MDTable.Method,methodIx);
1717 internal sealed override uint TypeDefOrRefToken()
1719 uint cIx = Row;
1720 cIx = cIx << 2;
1721 return cIx;
1724 internal sealed override void TypeSig(MemoryStream sig)
1726 if (!typeIndexChecked) CheckTypeIndex();
1727 sig.WriteByte(GetTypeIndex());
1728 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1731 internal sealed override uint GetCodedIx(CIx code)
1733 switch (code) {
1734 case (CIx.TypeDefOrRef) : return 0;
1735 case (CIx.HasCustomAttr) : return 3;
1736 case (CIx.HasDeclSecurity) : return 0;
1737 case (CIx.TypeOrMethodDef) : return 0;
1739 return 0;
1744 /**************************************************************************/
1745 /// <summary>
1746 /// Descriptor for a class/interface declared in another module of THIS
1747 /// assembly, or in another assembly.
1748 /// </summary>
1749 public class ClassRef : Class, IExternRef, IResolutionScope {
1751 protected IResolutionScope parent;
1752 ExternClass externClass;
1753 protected MetaData metaData;
1755 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
1757 metaData = md;
1758 tabIx = MDTable.TypeRef;
1761 /// <summary>
1762 /// Add a method to this class
1763 /// </summary>
1764 /// <param name="name">method name</param>
1765 /// <param name="retType">return type</param>
1766 /// <param name="pars">parameter types</param>
1767 /// <returns>a descriptor for this method</returns>
1768 public MethodRef AddMethod(string name, Type retType, Type[] pars)
1770 return AddMethod (name, retType, pars, 0);
1773 /// <summary>
1774 /// Add a method to this class
1775 /// </summary>
1776 /// <param name="name">method name</param>
1777 /// <param name="retType">return type</param>
1778 /// <param name="pars">parameter types</param>
1779 /// <param name="gen_param_count">num of generic parameters</param>
1780 /// <returns>a descriptor for this method</returns>
1781 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
1783 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
1784 metaData.AddToTable(MDTable.MemberRef,meth);
1785 return meth;
1788 /// <summary>
1789 /// Add a method to this class
1790 /// </summary>
1791 /// <param name="name">method name</param>
1792 /// <param name="retType">return type</param>
1793 /// <param name="pars">parameter types</param>
1794 /// <returns>a descriptor for this method</returns>
1795 public MethodRef AddVarArgMethod(string name, Type retType,
1796 Type[] pars, Type[] optPars)
1798 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
1799 metaData.AddToTable(MDTable.MemberRef,meth);
1800 return meth;
1803 /// <summary>
1804 /// Add a field to this class
1805 /// </summary>
1806 /// <param name="name">field name</param>
1807 /// <param name="fType">field type</param>
1808 /// <returns>a descriptor for this field</returns>
1809 public FieldRef AddField(string name, Type fType)
1811 FieldRef field = new FieldRef(this,name,fType);
1812 metaData.AddToTable(MDTable.MemberRef,field);
1813 return field;
1816 public ClassRef AddClass (string nsName, string name)
1818 ClassRef aClass = new ClassRef(nsName,name,metaData);
1819 metaData.AddToTable(MDTable.TypeRef,aClass);
1820 aClass.SetParent(this);
1821 return aClass;
1824 public ClassRef AddValueClass (string nsName, string name)
1826 ClassRef aClass = AddClass (nsName, name);
1827 aClass.MakeValueClass (ValueClass.ValueType);
1828 return aClass;
1831 internal void SetParent(IResolutionScope par)
1833 parent = par;
1836 internal override string TypeName()
1838 if ((parent != null) && (parent is AssemblyRef))
1839 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
1840 else
1841 return (nameSpace + name);
1844 internal sealed override uint Size(MetaData md)
1846 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
1847 md.StringsIndexSize();
1850 internal sealed override void Write(FileImage output)
1852 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
1853 output.StringsIndex(nameIx);
1854 output.StringsIndex(nameSpaceIx);
1857 internal override sealed uint TypeDefOrRefToken()
1859 uint cIx = Row;
1860 cIx = (cIx << 2) | 0x1;
1861 return cIx;
1864 internal override void TypeSig(MemoryStream sig)
1866 sig.WriteByte(GetTypeIndex());
1867 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1870 internal sealed override uint GetCodedIx(CIx code)
1872 switch (code) {
1873 case (CIx.TypeDefOrRef) : return 1;
1874 case (CIx.HasCustomAttr) : return 2;
1875 case (CIx.MemberRefParent) : return 1;
1876 case (CIx.ResolutionScope) : return 3;
1878 return 0;
1883 /**************************************************************************/
1884 public class ExternClassRef : ClassRef {
1886 ExternClass externClass;
1888 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
1889 FileRef declFile, MetaData md) : base(nsName,name,md)
1891 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
1892 metaData.AddToTable(MDTable.ExportedType,externClass);
1895 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
1899 public ClassRef AddNestedClass(TypeAttr attrs, string name)
1901 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
1902 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
1903 metaData.AddToTable(MDTable.ExportedType,externClass);
1904 return nestedClass;
1909 /**************************************************************************/
1910 /// <summary>
1911 /// Descriptor for a class defined in another module of THIS assembly
1912 /// and exported (.class extern)
1913 /// </summary>
1915 internal class ExternClass : Class {
1917 MetaDataElement parent;
1918 uint flags;
1920 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
1921 MetaDataElement paren) : base(nsIx,nIx)
1923 flags = (uint)attr;
1924 parent = paren;
1925 tabIx = MDTable.ExportedType;
1928 internal sealed override uint Size(MetaData md)
1930 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
1933 internal sealed override void Write(FileImage output)
1935 output.Write(flags);
1936 output.Write(0);
1937 output.StringsIndex(nameIx);
1938 output.StringsIndex(nameSpaceIx);
1939 output.WriteCodedIndex(CIx.Implementation,parent);
1942 internal sealed override uint GetCodedIx(CIx code)
1944 switch (code) {
1945 case (CIx.HasCustomAttr) : return 17;
1946 case (CIx.Implementation) : return 2;
1948 return 0;
1953 public class GenParam : Type {
1955 private int index;
1956 private string name;
1958 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
1960 this.index = index;
1961 this.name = name;
1962 tabIx = MDTable.TypeSpec;
1965 public int Index {
1966 get { return index; }
1967 set { index = value; }
1970 public string Name {
1971 get { return name; }
1972 set { name = value; }
1975 public GenParamType Type {
1976 get { return (GenParamType) GetTypeIndex (); }
1978 internal sealed override void TypeSig(MemoryStream str)
1980 if (index < 0)
1981 throw new Exception (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), name));
1982 str.WriteByte(typeIndex);
1983 MetaData.CompressNum ((uint) index, str);
1987 public class GenericTypeInst : Class {
1989 private Type gen_type;
1990 private Type[] gen_param;
1991 bool done = false;
1992 bool inTable = false;
1993 uint sigIx = 0;
1995 public GenericTypeInst (Type gen_type, Type[] gen_param)
1996 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
1998 this.gen_type = gen_type;
1999 this.gen_param = gen_param;
2000 tabIx = MDTable.TypeSpec;
2003 internal override MetaDataElement GetTypeSpec (MetaData md)
2005 if (!inTable) {
2006 md.AddToTable (MDTable.TypeSpec, this);
2007 inTable = true;
2010 return this;
2013 internal sealed override void TypeSig(MemoryStream str)
2015 str.WriteByte(typeIndex);
2016 gen_type.TypeSig (str);
2017 MetaData.CompressNum ((uint) gen_param.Length, str);
2018 foreach (Type param in gen_param)
2019 param.TypeSig (str);
2022 internal sealed override void BuildTables (MetaData md)
2024 if (done)
2025 return;
2026 MemoryStream str = new MemoryStream ();
2027 TypeSig (str);
2028 sigIx = md.AddToBlobHeap (str.ToArray ());
2030 done = true;
2033 internal sealed override uint Size (MetaData md)
2035 return md.BlobIndexSize ();
2038 internal sealed override void Write (FileImage output)
2040 output.BlobIndex (sigIx);
2043 internal sealed override uint GetCodedIx (CIx code)
2045 switch (code) {
2046 case (CIx.TypeDefOrRef): return 2;
2047 case (CIx.MemberRefParent): return 4;
2048 case (CIx.HasCustomAttr): return 13;
2050 return 0;
2054 public class GenericMethodSig {
2056 private Type[] gen_param;
2058 public GenericMethodSig (Type[] gen_param)
2060 this.gen_param = gen_param;
2063 internal void TypeSig (MemoryStream str)
2065 str.WriteByte (0x0A); /* GENERIC_INST */
2066 MetaData.CompressNum ((uint) gen_param.Length, str);
2067 foreach (Type param in gen_param)
2068 param.TypeSig (str);
2071 internal uint GetSigIx (MetaData md)
2073 MemoryStream sig = new MemoryStream();
2074 TypeSig (sig);
2075 return md.AddToBlobHeap (sig.ToArray());
2079 public class Sentinel : Type {
2081 public Sentinel () : base (0x41) { }
2083 internal sealed override void TypeSig(MemoryStream str)
2085 str.WriteByte(typeIndex);
2089 /**************************************************************************/
2090 /// <summary>
2091 /// Descriptor for a FunctionPointer type
2092 /// </summary>
2093 ///
2094 public class MethPtrType : Type {
2096 bool varArgMeth;
2097 Type retType;
2098 Type [] parList;
2099 Type [] optParList;
2100 CallConv callConv;
2101 uint numPars;
2102 uint numOptPars;
2103 uint sigIx = 0;
2105 /// <summary>
2106 /// Create a new function pointer type
2107 /// </summary>
2108 /// <param name="meth">the function to be referenced</param>
2109 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2110 bool varArgMeth, Type[] optPars) : base(0x1B)
2112 this.retType = retType;
2113 callConv = callconv;
2114 parList = pars;
2115 this.varArgMeth = varArgMeth;
2116 if (parList != null) numPars = (uint)parList.Length;
2117 if (varArgMeth) {
2118 optParList = optPars;
2119 if (optParList != null) numOptPars = (uint)optParList.Length;
2120 callConv |= CallConv.Vararg;
2122 tabIx = MDTable.TypeSpec;
2125 internal sealed override void TypeSig(MemoryStream sig)
2127 sig.WriteByte(typeIndex);
2128 // Bootlegged from method ref
2129 sig.WriteByte((byte)callConv);
2130 MetaData.CompressNum (numPars + numOptPars, sig);
2131 retType.TypeSig (sig);
2132 for (int i=0; i < numPars; i++) {
2133 parList[i].TypeSig (sig);
2135 if (varArgMeth) {
2136 sig.WriteByte (0x41); // Write the sentinel
2137 for (int i=0; i < numOptPars; i++) {
2138 optParList[i].TypeSig (sig);
2143 internal sealed override void BuildTables(MetaData md)
2145 if (done) return;
2146 MemoryStream sig = new MemoryStream();
2147 TypeSig(sig);
2148 sigIx = md.AddToBlobHeap(sig.ToArray());
2149 done = true;
2152 internal sealed override uint Size(MetaData md)
2154 return md.BlobIndexSize();
2157 internal sealed override void Write(FileImage output)
2159 output.BlobIndex(sigIx);
2162 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2166 #region Array Types
2167 /* Classes for Arrays */
2169 /// <summary>
2170 /// The IL Array type
2171 /// </summary>
2172 public abstract class Array : Type {
2174 protected Type elemType;
2175 protected MetaData metaData;
2176 protected string cnameSpace, cname;
2178 internal Array(Type eType, byte TypeId) : base(TypeId)
2180 elemType = eType;
2181 tabIx = MDTable.TypeSpec;
2185 /// <summary>
2186 /// Single dimensional array with zero lower bound
2187 /// </summary>
2188 public class ZeroBasedArray : Array {
2190 /// <summary>
2191 /// Create a new array - elementType[]
2192 /// </summary>
2193 /// <param name="elementType">the type of the array elements</param>
2194 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2196 internal sealed override void TypeSig(MemoryStream str)
2198 str.WriteByte(typeIndex);
2199 elemType.TypeSig(str);
2204 /// <summary>
2205 /// Multi dimensional array with explicit bounds
2206 /// </summary>
2207 public class BoundArray : Array {
2208 int[] lowerBounds;
2209 int[] sizes;
2210 uint numDims;
2212 /// <summary>
2213 /// Create a new multi dimensional array type
2214 /// eg. elemType[1..5,3..10,5,,] would be
2215 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2216 /// </summary>
2217 /// <param name="elementType">the type of the elements</param>
2218 /// <param name="dimensions">the number of dimensions</param>
2219 /// <param name="loBounds">lower bounds of dimensions</param>
2220 /// <param name="upBounds">upper bounds of dimensions</param>
2221 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2222 int[] upBounds) : base (elementType,0x14)
2224 numDims = dimensions;
2225 lowerBounds = loBounds;
2226 if (upBounds == null)
2227 return;
2228 sizes = new int[loBounds.Length];
2229 for (int i=0; i < loBounds.Length; i++) {
2230 sizes[i] = upBounds[i] - loBounds[i] + 1;
2234 /// <summary>
2235 /// Create a new multi dimensional array type
2236 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2237 /// </summary>
2238 /// <param name="elementType">the type of the elements</param>
2239 /// <param name="dimensions">the number of dimensions</param>
2240 /// <param name="size">the sizes of the dimensions</param>
2241 public BoundArray(Type elementType, uint dimensions, int[] size)
2242 : base (elementType,0x14)
2244 numDims = dimensions;
2245 sizes = size;
2248 /// <summary>
2249 /// Create a new multi dimensional array type
2250 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2251 /// </summary>
2252 /// <param name="elementType">the type of the elements</param>
2253 /// <param name="dimensions">the number of dimensions</param>
2254 public BoundArray(Type elementType, uint dimensions)
2255 : base (elementType,0x14)
2257 numDims = dimensions;
2260 internal sealed override void TypeSig(MemoryStream str)
2262 str.WriteByte(typeIndex);
2263 elemType.TypeSig(str);
2264 MetaData.CompressNum(numDims,str);
2265 if ((sizes != null) && (sizes.Length > 0)) {
2267 MetaData.CompressNum((uint)sizes.Length,str);
2268 for (int i=0; i < sizes.Length; i++) {
2269 MetaData.CompressNum((uint)sizes[i],str);
2271 } else str.WriteByte(0);
2272 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2273 MetaData.CompressNum((uint)lowerBounds.Length,str);
2274 for (int i=0; i < lowerBounds.Length; i++) {
2275 MetaData.CompressNum((uint)lowerBounds[i],str);
2277 } else str.WriteByte(0);
2282 #endregion
2285 /* Empty interface for grouping TypeRef's possible ResolutionScope
2286 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2287 public interface IResolutionScope {
2290 /**************************************************************************/
2291 /// <summary>
2292 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2293 /// </summary>
2294 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2296 protected uint nameIx = 0;
2297 protected MetaData metaData;
2298 protected string name;
2300 internal ResolutionScope(string name, MetaData md)
2302 metaData = md;
2303 this.name = name;
2304 nameIx = md.AddToStringsHeap(name);
2307 internal string GetName() { return name; }
2311 /**************************************************************************/
2312 /// <summary>
2313 /// Descriptor for THIS assembly (.assembly)
2314 /// </summary>
2315 public class Assembly : ResolutionScope {
2317 ushort majorVer, minorVer, buildNo, revisionNo;
2318 uint flags;
2319 uint hashAlgId;
2320 uint keyIx = 0, cultIx = 0;
2321 bool hasPublicKey = false;
2323 internal Assembly(string name, MetaData md) : base(name,md)
2325 tabIx = MDTable.Assembly;
2328 /// <summary>
2329 /// Add details about THIS assembly
2330 /// </summary>
2331 /// <param name="majVer">Major Version</param>
2332 /// <param name="minVer">Minor Version</param>
2333 /// <param name="bldNo">Build Number</param>
2334 /// <param name="revNo">Revision Number</param>
2335 /// <param name="key">Hash Key</param>
2336 /// <param name="hash">Hash Algorithm</param>
2337 /// <param name="cult">Culture</param>
2338 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2339 byte[] key, uint hash, string cult)
2341 majorVer = (ushort)majVer;
2342 minorVer = (ushort)minVer;
2343 buildNo = (ushort)bldNo;
2344 revisionNo = (ushort)revNo;
2345 hashAlgId = hash;
2346 hasPublicKey = (key != null);
2347 keyIx = metaData.AddToBlobHeap(key);
2348 cultIx = metaData.AddToStringsHeap(cult);
2351 /// <summary>
2352 /// Add an attribute to THIS assembly
2353 /// </summary>
2354 /// <param name="aa">assembly attribute</param>
2355 public void AddAssemblyAttr(AssemAttr aa)
2357 flags |= (uint)aa;
2360 internal sealed override uint Size(MetaData md)
2362 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2365 internal sealed override void Write(FileImage output)
2367 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2368 output.Write((uint)hashAlgId);
2369 output.Write(majorVer);
2370 output.Write(minorVer);
2371 output.Write(buildNo);
2372 output.Write(revisionNo);
2373 output.Write(flags);
2374 output.BlobIndex(keyIx);
2375 output.StringsIndex(nameIx);
2376 output.StringsIndex(cultIx);
2379 internal sealed override uint GetCodedIx(CIx code)
2381 switch (code) {
2382 case (CIx.HasCustomAttr) : return 14;
2383 case (CIx.HasDeclSecurity) : return 2;
2385 return 0;
2388 internal bool HasPublicKey {
2389 get { return hasPublicKey; }
2393 /**************************************************************************/
2394 /// <summary>
2395 /// Descriptor for THIS module
2396 /// </summary>
2397 public class Module : ResolutionScope {
2399 Guid mvid;
2400 uint mvidIx = 0;
2402 internal Module(string name, MetaData md) : base(name,md)
2404 mvid = Guid.NewGuid();
2405 mvidIx = md.AddToGUIDHeap(mvid);
2406 tabIx = MDTable.Module;
2409 public Guid Guid {
2410 get { return mvid; }
2413 internal sealed override uint Size(MetaData md)
2415 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2418 internal sealed override void Write(FileImage output)
2420 output.Write((short)0);
2421 output.StringsIndex(nameIx);
2422 output.GUIDIndex(mvidIx);
2423 output.GUIDIndex(0);
2424 output.GUIDIndex(0);
2427 internal sealed override uint GetCodedIx(CIx code)
2429 switch (code) {
2430 case (CIx.HasCustomAttr) : return 7;
2431 case (CIx.ResolutionScope) : return 0;
2433 return 0;
2436 /**************************************************************************/
2437 /// <summary>
2438 /// Descriptor for another module in THIS assembly
2439 /// </summary>
2440 public class ModuleRef : ResolutionScope, IExternRef {
2442 internal ModuleRef(MetaData md, string name) : base(name,md)
2444 tabIx = MDTable.ModuleRef;
2447 /// <summary>
2448 /// Add a class to this external module. This is a class declared in
2449 /// another module of THIS assembly.
2450 /// </summary>
2451 /// <param name="nsName">name space name</param>
2452 /// <param name="name">class name</param>
2453 /// <returns>a descriptor for this class in another module</returns>
2454 public ClassRef AddClass(string nsName, string name)
2456 ClassRef aClass = new ClassRef(nsName,name,metaData);
2457 metaData.AddToTable(MDTable.TypeRef,aClass);
2458 aClass.SetParent(this);
2459 return aClass;
2462 /// <summary>
2463 /// Make a file descriptor to correspond to this module. The file
2464 /// descriptor will have the same name as the module descriptor
2465 /// </summary>
2466 /// <param name="hashBytes">the hash of the file</param>
2467 /// <param name="hasMetaData">the file contains metadata</param>
2468 /// <param name="entryPoint">the program entry point is in this file</param>
2469 /// <returns>a descriptor for the file which contains this module</returns>
2470 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2472 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2473 metaData.AddToTable(MDTable.File,file);
2474 return file;
2477 /// <summary>
2478 /// Add a value class to this module. This is a class declared in
2479 /// another module of THIS assembly.
2480 /// </summary>
2481 /// <param name="nsName">name space name</param>
2482 /// <param name="name">class name</param>
2483 /// <returns></returns>
2484 public ClassRef AddValueClass(string nsName, string name)
2486 ClassRef aClass = new ClassRef(nsName,name,metaData);
2487 metaData.AddToTable(MDTable.TypeRef,aClass);
2488 aClass.SetParent(this);
2489 aClass.MakeValueClass(ValueClass.ValueType);
2490 return aClass;
2493 /// <summary>
2494 /// Add a class which is declared public in this external module of
2495 /// THIS assembly. This class will be exported from this assembly.
2496 /// The ilasm syntax for this is .extern class
2497 /// </summary>
2498 /// <param name="attrSet">attributes of the class to be exported</param>
2499 /// <param name="nsName">name space name</param>
2500 /// <param name="name">external class name</param>
2501 /// <param name="declFile">the file where the class is declared</param>
2502 /// <param name="isValueClass">is this class a value type?</param>
2503 /// <returns>a descriptor for this external class</returns>
2504 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2505 string name, FileRef declFile,
2506 bool isValueClass) {
2507 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2508 metaData.AddToTable(MDTable.TypeRef,cRef);
2509 cRef.SetParent(this);
2510 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2511 return cRef;
2514 /// <summary>
2515 /// Add a "global" method in another module
2516 /// </summary>
2517 /// <param name="name">method name</param>
2518 /// <param name="retType">return type</param>
2519 /// <param name="pars">method parameter types</param>
2520 /// <returns>a descriptor for this method in anther module</returns>
2521 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2523 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2524 metaData.AddToTable(MDTable.MemberRef,meth);
2525 return meth;
2528 /// <summary>
2529 /// Add a vararg method to this class
2530 /// </summary>
2531 /// <param name="name">method name</param>
2532 /// <param name="retType">return type</param>
2533 /// <param name="pars">parameter types</param>
2534 /// <param name="optPars">optional param types for this vararg method</param>
2535 /// <returns>a descriptor for this method</returns>
2536 public MethodRef AddVarArgMethod(string name, Type retType,
2537 Type[] pars, Type[] optPars) {
2538 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2539 metaData.AddToTable(MDTable.MemberRef,meth);
2540 return meth;
2543 /// <summary>
2544 /// Add a field in another module
2545 /// </summary>
2546 /// <param name="name">field name</param>
2547 /// <param name="fType">field type</param>
2548 /// <returns>a descriptor for this field in another module</returns>
2549 public FieldRef AddField(string name, Type fType)
2551 FieldRef field = new FieldRef(this,name,fType);
2552 metaData.AddToTable(MDTable.MemberRef,field);
2553 return field;
2556 internal sealed override uint Size(MetaData md)
2558 return md.StringsIndexSize();
2561 internal sealed override void Write(FileImage output)
2563 output.StringsIndex(nameIx);
2566 internal sealed override uint GetCodedIx(CIx code)
2568 switch (code) {
2569 case (CIx.HasCustomAttr) : return 12;
2570 case (CIx.MemberRefParent) : return 2;
2571 case (CIx.ResolutionScope) : return 1;
2573 return 0;
2578 #region Classes for Constants
2579 /// <summary>
2580 /// Descriptor for a constant value
2581 /// </summary>
2582 public abstract class Constant {
2583 protected uint size = 0;
2584 protected Type type;
2585 protected uint blobIndex;
2586 protected bool addedToBlobHeap = false;
2588 internal Constant() { }
2590 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2592 internal uint GetSize() { return size; }
2594 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2596 internal virtual void Write(BinaryWriter bw) { }
2599 /// <summary>
2600 /// Descriptor for a constant value
2601 /// </summary>
2602 public abstract class DataConstant : Constant {
2603 private uint dataOffset = 0;
2605 internal DataConstant() { }
2607 public uint DataOffset {
2608 get { return dataOffset; }
2609 set { dataOffset = value; }
2614 /// <summary>
2615 /// Boolean constant
2616 /// </summary>
2617 public class BoolConst : Constant {
2618 bool val;
2620 /// <summary>
2621 /// Create a new boolean constant with the value "val"
2622 /// </summary>
2623 /// <param name="val">value of this boolean constant</param>
2624 public BoolConst(bool val)
2626 this.val = val;
2627 size = 1;
2628 type = PrimitiveType.Boolean;
2631 internal sealed override uint GetBlobIndex(MetaData md)
2633 if (!addedToBlobHeap) {
2634 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2635 else blobIndex = md.AddToBlobHeap((sbyte)0);
2636 addedToBlobHeap = true;
2638 return blobIndex;
2641 internal sealed override void Write(BinaryWriter bw)
2643 if (val) bw.Write((sbyte)1);
2644 else bw.Write((sbyte)0);
2649 public class ByteArrConst : DataConstant {
2650 byte[] val;
2652 public ByteArrConst(byte[] val)
2654 type = PrimitiveType.String;
2655 this.val = val;
2656 size = (uint)val.Length;
2659 public Type Type {
2660 get { return type; }
2661 set { type = value; }
2664 internal sealed override uint GetBlobIndex(MetaData md)
2666 if (!addedToBlobHeap) {
2667 blobIndex = md.AddToBlobHeap(val);
2668 addedToBlobHeap = true;
2670 return blobIndex;
2673 internal sealed override void Write(BinaryWriter bw)
2675 bw.Write(val);
2680 public class CharConst : Constant {
2681 char val;
2683 public CharConst(char val)
2685 this.val = val;
2686 size = 2;
2687 type = PrimitiveType.Char;
2690 internal sealed override uint GetBlobIndex(MetaData md)
2692 if (!addedToBlobHeap) {
2693 blobIndex = md.AddToBlobHeap(val);
2694 addedToBlobHeap = true;
2696 return blobIndex;
2699 internal sealed override void Write(BinaryWriter bw)
2701 bw.Write(val);
2706 public class FloatConst : DataConstant {
2707 float val;
2709 public FloatConst(float val)
2711 this.val = val;
2712 size = 4;
2713 type = PrimitiveType.Float32;
2716 internal sealed override uint GetBlobIndex(MetaData md)
2718 if (!addedToBlobHeap) {
2719 blobIndex = md.AddToBlobHeap(val);
2720 addedToBlobHeap = true;
2722 return blobIndex;
2725 internal sealed override void Write(BinaryWriter bw)
2727 bw.Write(val);
2732 public class DoubleConst : DataConstant {
2733 double val;
2735 public DoubleConst(double val)
2737 this.val = val;
2738 size = 8;
2739 type = PrimitiveType.Float64;
2742 internal sealed override uint GetBlobIndex(MetaData md)
2744 if (!addedToBlobHeap) {
2745 blobIndex = md.AddToBlobHeap(val);
2746 addedToBlobHeap = true;
2748 return blobIndex;
2751 internal sealed override void Write(BinaryWriter bw)
2753 bw.Write(val);
2758 public class IntConst : DataConstant {
2759 long val;
2761 public IntConst(sbyte val)
2763 this.val = val;
2764 size = 1;
2765 type = PrimitiveType.Int8;
2768 public IntConst(short val)
2770 this.val = val;
2771 size = 2;
2772 type = PrimitiveType.Int16;
2775 public IntConst(int val)
2777 this.val = val;
2778 size = 4;
2779 type = PrimitiveType.Int32;
2782 public IntConst(long val)
2784 this.val = val;
2785 size = 8;
2786 type = PrimitiveType.Int64;
2789 internal sealed override uint GetBlobIndex(MetaData md)
2791 if (!addedToBlobHeap) {
2792 switch (size) {
2793 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
2794 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
2795 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
2796 default : blobIndex = md.AddToBlobHeap(val); break;
2798 addedToBlobHeap = true;
2800 return blobIndex;
2803 internal sealed override void Write(BinaryWriter bw)
2805 switch (size) {
2806 case (1) : bw.Write((sbyte)val); break;
2807 case (2) : bw.Write((short)val); break;
2808 case (4) : bw.Write((int)val); break;
2809 default : bw.Write(val); break;
2815 public class UIntConst : Constant {
2816 ulong val;
2818 public UIntConst(byte val)
2820 this.val = val;
2821 size = 1;
2822 type = PrimitiveType.UInt8;
2824 public UIntConst(ushort val)
2826 this.val = val;
2827 size = 2;
2828 type = PrimitiveType.UInt16;
2830 public UIntConst(uint val)
2832 this.val = val;
2833 size = 4;
2834 type = PrimitiveType.UInt32;
2836 public UIntConst(ulong val)
2838 this.val = val;
2839 size = 8;
2840 type = PrimitiveType.UInt64;
2843 internal sealed override uint GetBlobIndex(MetaData md)
2845 if (!addedToBlobHeap) {
2846 switch (size) {
2847 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
2848 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
2849 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
2850 default : blobIndex = md.AddToBlobHeap(val); break;
2852 addedToBlobHeap = true;
2854 return blobIndex;
2857 internal sealed override void Write(BinaryWriter bw)
2859 switch (size) {
2860 case (1) : bw.Write((byte)val); break;
2861 case (2) : bw.Write((ushort)val); break;
2862 case (4) : bw.Write((uint)val); break;
2863 default : bw.Write(val); break;
2869 public class StringConst : DataConstant {
2870 string val;
2872 public StringConst(string val)
2874 this.val = val;
2875 size = (uint)val.Length; // need to add null ??
2876 type = PrimitiveType.String;
2879 internal sealed override uint GetBlobIndex(MetaData md)
2881 if (!addedToBlobHeap) {
2882 byte [] b = Encoding.Unicode.GetBytes (val);
2883 blobIndex = md.AddToBlobHeap(b);
2884 addedToBlobHeap = true;
2886 return blobIndex;
2889 internal sealed override void Write(BinaryWriter bw)
2891 bw.Write(val);
2896 public class NullConst : Constant {
2898 public NullConst()
2900 size = 4;
2901 type = PrimitiveType.Class;
2904 internal sealed override uint GetBlobIndex(MetaData md)
2906 if (!addedToBlobHeap) {
2907 blobIndex = md.AddToBlobHeap((int)0);
2908 addedToBlobHeap = true;
2910 return blobIndex;
2913 internal sealed override void Write(BinaryWriter bw)
2915 bw.Write((int)0);
2920 public class AddressConstant : DataConstant {
2921 DataConstant data;
2923 public AddressConstant(DataConstant dConst)
2925 data = dConst;
2926 size = 4;
2927 type = PrimitiveType.TypedRef;
2930 internal sealed override void Write(BinaryWriter bw)
2932 ((FileImage)bw).WriteDataRVA(data.DataOffset);
2937 public class RepeatedConstant : DataConstant {
2938 DataConstant data;
2939 uint repCount;
2941 public RepeatedConstant(DataConstant dConst, int repeatCount)
2943 data = dConst;
2944 repCount = (uint)repeatCount;
2945 int[] sizes = new int[1];
2946 sizes[0] = repeatCount;
2947 type = new BoundArray(type,1,sizes);
2948 size = data.GetSize() * repCount;
2951 internal sealed override void Write(BinaryWriter bw)
2953 for (int i=0; i < repCount; i++) {
2954 data.Write(bw);
2960 public class ArrayConstant : DataConstant {
2961 DataConstant[] dataVals;
2963 public ArrayConstant(DataConstant[] dVals)
2965 dataVals = dVals;
2966 for (int i=0; i < dataVals.Length; i++) {
2967 size += dataVals[i].GetSize();
2971 internal sealed override void Write(BinaryWriter bw)
2973 for (int i=0; i < dataVals.Length; i++) {
2974 dataVals[i].Write(bw);
2980 public class ClassType : Constant {
2981 string name;
2982 Class desc;
2984 public ClassType(string className)
2986 name = className;
2987 type = PrimitiveType.ClassType;
2990 public ClassType(Class classDesc)
2992 desc = classDesc;
2993 type = PrimitiveType.ClassType;
2996 internal override void Write(BinaryWriter bw)
2998 if (name == null) name = desc.TypeName();
2999 bw.Write(name);
3004 #endregion
3006 /**************************************************************************/
3007 /// <summary>
3008 /// Descriptor for a custom modifier of a type (modopt or modreq)
3009 /// </summary>
3011 public class CustomModifiedType : Type {
3013 Type type;
3014 Class cmodType;
3016 /// <summary>
3017 /// Create a new custom modifier for a type
3018 /// </summary>
3019 /// <param name="type">the type to be modified</param>
3020 /// <param name="cmod">the modifier</param>
3021 /// <param name="cmodType">the type reference to be associated with the type</param>
3022 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3023 : base((byte)cmod)
3025 this.type = type;
3026 this.cmodType = cmodType;
3029 internal sealed override void TypeSig(MemoryStream str)
3031 str.WriteByte(typeIndex);
3032 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3033 type.TypeSig(str);
3038 /**************************************************************************/
3039 /// <summary>
3040 /// Base class for Event and Property descriptors
3041 /// </summary>
3043 public class Feature : MetaDataElement {
3045 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3046 RemoveOn = 0x10, Fire = 0x20 }
3048 private static readonly int INITSIZE = 5;
3049 private static readonly ushort specialName = 0x200;
3050 private static readonly ushort rtSpecialName = 0x400;
3052 protected ClassDef parent;
3053 protected ushort flags = 0;
3054 protected string name;
3055 protected int tide = 0;
3056 protected uint nameIx;
3057 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3059 internal Feature(string name, ClassDef par)
3061 parent = par;
3062 this.name = name;
3065 internal void AddMethod(MethodDef meth, MethodType mType)
3067 if (tide >= methods.Length) {
3068 int len = methods.Length;
3069 MethodSemantics[] mTmp = methods;
3070 methods = new MethodSemantics[len * 2];
3071 for (int i=0; i < len; i++) {
3072 methods[i] = mTmp[i];
3075 methods[tide++] = new MethodSemantics(mType,meth,this);
3078 /// <summary>
3079 /// Set the specialName attribute for this Event or Property
3080 /// </summary>
3081 public void SetSpecialName()
3083 flags |= specialName;
3086 /// <summary>
3087 /// Set the RTSpecialName attribute for this Event or Property
3088 /// </summary>
3089 public void SetRTSpecialName()
3091 flags |= rtSpecialName;
3096 /**************************************************************************/
3097 /// <summary>
3098 /// Descriptor for an event
3099 /// </summary>
3100 public class Event : Feature {
3102 Type eventType;
3104 internal Event(string name, Type eType, ClassDef parent)
3105 : base(name, parent)
3107 eventType = eType;
3108 tabIx = MDTable.Event;
3111 /// <summary>
3112 /// Add the addon method to this event
3113 /// </summary>
3114 /// <param name="addon">the addon method</param>
3115 public void AddAddon(MethodDef addon)
3117 AddMethod(addon,MethodType.AddOn);
3120 /// <summary>
3121 /// Add the removeon method to this event
3122 /// </summary>
3123 /// <param name="removeOn">the removeon method</param>
3124 public void AddRemoveOn(MethodDef removeOn)
3126 AddMethod(removeOn,MethodType.RemoveOn);
3129 /// <summary>
3130 /// Add the fire method to this event
3131 /// </summary>
3132 /// <param name="fire">the fire method</param>
3133 public void AddFire(MethodDef fire)
3135 AddMethod(fire,MethodType.Fire);
3138 /// <summary>
3139 /// Add another method to this event
3140 /// </summary>
3141 /// <param name="other">the method to be added</param>
3142 public void AddOther(MethodDef other)
3144 AddMethod(other,MethodType.Other);
3147 internal sealed override void BuildTables(MetaData md)
3149 if (done) return;
3150 nameIx = md.AddToStringsHeap(name);
3151 for (int i=0; i < tide; i++) {
3152 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3154 done = true;
3157 internal sealed override uint Size(MetaData md)
3159 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3162 internal sealed override void Write(FileImage output)
3164 output.Write(flags);
3165 output.StringsIndex(nameIx);
3166 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3169 internal sealed override uint GetCodedIx(CIx code)
3171 switch (code) {
3172 case (CIx.HasCustomAttr) : return 10;
3173 case (CIx.HasSemantics) : return 0;
3175 return 0;
3180 /**************************************************************************/
3181 /// <summary>
3182 /// Descriptor for the Property of a class
3183 /// </summary>
3184 public class Property : Feature {
3186 private static readonly byte PropertyTag = 0x8;
3187 private bool instance;
3188 MethodDef getterMeth;
3189 ConstantElem constVal;
3190 uint typeBlobIx = 0;
3191 Type[] parList;
3192 Type returnType;
3193 uint numPars = 0;
3195 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3197 returnType = retType;
3198 parList = pars;
3199 if (pars != null) numPars = (uint)pars.Length;
3200 tabIx = MDTable.Property;
3203 /// <summary>
3204 /// Add a set method to this property
3205 /// </summary>
3206 /// <param name="setter">the set method</param>
3207 public void AddSetter(MethodDef setter)
3209 AddMethod(setter,MethodType.Setter);
3212 /// <summary>
3213 /// Add a get method to this property
3214 /// </summary>
3215 /// <param name="getter">the get method</param>
3216 public void AddGetter(MethodDef getter)
3218 AddMethod(getter,MethodType.Getter);
3219 getterMeth = getter;
3222 /// <summary>
3223 /// Add another method to this property
3224 /// </summary>
3225 /// <param name="other">the method</param>
3226 public void AddOther(MethodDef other)
3228 AddMethod(other,MethodType.Other);
3231 /// <summary>
3232 /// Add an initial value for this property
3233 /// </summary>
3234 /// <param name="constVal">the initial value for this property</param>
3235 public void AddInitValue(Constant constVal)
3237 this.constVal = new ConstantElem(this,constVal);
3240 public void SetInstance (bool isInstance)
3242 this.instance = isInstance;
3245 internal sealed override void BuildTables(MetaData md)
3247 if (done) return;
3248 nameIx = md.AddToStringsHeap(name);
3249 MemoryStream sig = new MemoryStream();
3250 byte tag = PropertyTag;
3251 if (instance)
3252 tag |= 0x20;
3253 sig.WriteByte(tag);
3254 MetaData.CompressNum(numPars,sig);
3255 returnType.TypeSig(sig);
3256 for (int i=0; i < numPars; i++) {
3257 parList[i].TypeSig(sig);
3259 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3260 for (int i=0; i < tide; i++) {
3261 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3263 if (constVal != null) {
3264 md.AddToTable(MDTable.Constant,constVal);
3265 constVal.BuildTables(md);
3267 done = true;
3270 internal sealed override uint Size(MetaData md)
3272 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3275 internal sealed override void Write(FileImage output)
3277 output.Write(flags);
3278 output.StringsIndex(nameIx);
3279 output.BlobIndex(typeBlobIx);
3282 internal sealed override uint GetCodedIx(CIx code)
3284 switch (code) {
3285 case (CIx.HasCustomAttr) : return 9;
3286 case (CIx.HasConst) : return 2;
3287 case (CIx.HasSemantics) : return 1;
3289 return 0;
3294 /**************************************************************************/
3295 /// <summary>
3296 /// Base class for field/methods (member of a class)
3297 /// </summary>
3298 public abstract class Member : MetaDataElement {
3300 protected string name;
3301 protected uint nameIx = 0, sigIx = 0;
3303 internal Member(string memName)
3305 name = memName;
3306 tabIx = MDTable.MemberRef;
3311 /*****************************************************************************/
3312 /// <summary>
3313 /// Descriptor for a field of a class
3314 /// </summary>
3316 public abstract class Field : Member {
3318 protected static readonly byte FieldSig = 0x6;
3320 protected Type type;
3322 internal Field(string pfName, Type pfType) : base(pfName)
3324 type = pfType;
3328 /**************************************************************************/
3329 /// <summary>
3330 /// Descriptor for a field defined in a class of THIS assembly/module
3331 /// </summary>
3332 public class FieldDef : Field {
3334 //private static readonly uint PInvokeImpl = 0x2000;
3335 private static readonly ushort HasFieldRVA = 0x100;
3336 private static readonly ushort HasDefault = 0x8000;
3338 FieldRVA rva;
3339 ConstantElem constVal;
3340 FieldLayout layout;
3341 FieldMarshal marshalInfo;
3342 ushort flags;
3344 internal FieldDef(string name, Type fType) : base(name,fType)
3346 tabIx = MDTable.Field;
3349 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3351 flags = (ushort)attrSet;
3352 tabIx = MDTable.Field;
3355 /// <summary>
3356 /// Add an attribute(s) to this field
3357 /// </summary>
3358 /// <param name="fa">the attribute(s) to be added</param>
3359 public void AddFieldAttr(FieldAttr fa)
3361 flags |= (ushort)fa;
3364 /// <summary>
3365 /// Add a value for this field
3366 /// </summary>
3367 /// <param name="val">the value for the field</param>
3368 public void AddValue(Constant val)
3370 constVal = new ConstantElem(this,val);
3371 flags |= HasDefault;
3374 /// <summary>
3375 /// Add an initial value for this field (at dataLabel) (.data)
3376 /// </summary>
3377 /// <param name="val">the value for the field</param>
3378 /// <param name="repeatVal">the number of repetitions of this value</param>
3379 public void AddDataValue(DataConstant val)
3381 flags |= HasFieldRVA;
3382 rva = new FieldRVA(this,val);
3385 /// <summary>
3386 /// Set the offset of the field. Used for sequential or explicit classes.
3387 /// (.field [offs])
3388 /// </summary>
3389 /// <param name="offs">field offset</param>
3390 public void SetOffset(uint offs)
3392 layout = new FieldLayout(this,offs);
3395 /// <summary>
3396 /// Set the marshalling info for a field
3397 /// </summary>
3398 /// <param name="mInf"></param>
3399 public void SetMarshalInfo(NativeType marshallType)
3401 flags |= (ushort) FieldAttr.HasFieldMarshal;
3402 marshalInfo = new FieldMarshal(this,marshallType);
3405 internal sealed override void BuildTables(MetaData md)
3407 if (done) return;
3408 nameIx = md.AddToStringsHeap(name);
3409 MemoryStream sig = new MemoryStream();
3410 sig.WriteByte(FieldSig);
3411 type.TypeSig(sig);
3412 sigIx = md.AddToBlobHeap(sig.ToArray());
3413 if (rva != null) {
3414 md.AddToTable(MDTable.FieldRVA,rva);
3415 rva.BuildTables(md);
3416 } else if (constVal != null) {
3417 md.AddToTable(MDTable.Constant,constVal);
3418 constVal.BuildTables(md);
3420 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3421 if (marshalInfo != null) {
3422 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3423 marshalInfo.BuildTables(md);
3425 done = true;
3428 internal sealed override uint Size(MetaData md)
3430 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3433 internal sealed override void Write(FileImage output)
3435 output.Write(flags);
3436 output.StringsIndex(nameIx);
3437 output.BlobIndex(sigIx);
3440 internal sealed override uint GetCodedIx(CIx code)
3442 switch (code) {
3443 case (CIx.HasConst) : return 0;
3444 case (CIx.HasCustomAttr) : return 1;
3445 case (CIx.HasFieldMarshal) : return 0;
3446 case (CIx.MemberForwarded) : return 0;
3448 return 0;
3453 /**************************************************************************/
3454 /// <summary>
3455 /// Descriptor for a field of a class defined in another assembly/module
3456 /// </summary>
3457 public class FieldRef : Field {
3459 MetaDataElement parent;
3461 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3463 parent = paren;
3466 internal sealed override void BuildTables(MetaData md)
3468 if (done) return;
3469 nameIx = md.AddToStringsHeap(name);
3470 MemoryStream sig = new MemoryStream();
3471 sig.WriteByte(FieldSig);
3472 type.TypeSig(sig);
3473 sigIx = md.AddToBlobHeap(sig.ToArray());
3474 done = true;
3477 internal sealed override uint Size(MetaData md)
3479 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3482 internal sealed override void Write(FileImage output)
3484 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3485 output.StringsIndex(nameIx);
3486 output.BlobIndex(sigIx);
3489 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3493 /**************************************************************************/
3494 /// <summary>
3495 /// Base class for Method Descriptors
3496 /// </summary>
3498 public abstract class Method : Member {
3500 internal Method (string methName) : base (methName)
3503 public abstract void AddCallConv(CallConv cconv);
3504 internal abstract void TypeSig(MemoryStream sig);
3505 internal abstract uint GetSigIx(MetaData md);
3508 /**************************************************************************/
3509 /// <summary>
3510 /// Descriptor for a method defined in THIS assembly/module
3511 /// IL .method
3512 /// </summary>
3514 public class MethodDef : Method {
3516 private static readonly ushort PInvokeImpl = 0x2000;
3517 //private static readonly uint UnmanagedExport = 0x0008;
3518 // private static readonly byte LocalSigByte = 0x7;
3519 uint parIx = 0, textOffset = 0;
3520 private CallConv callConv = CallConv.Default;
3521 private Type retType;
3522 private int gen_param_count;
3524 MetaData metaData;
3525 CILInstructions code;
3526 ArrayList securityActions = new ArrayList();
3527 Param[] parList;
3528 Local[] locals;
3529 bool initLocals;
3530 ushort methFlags = 0, implFlags = 0;
3531 int maxStack = 0, numPars = 0;
3532 bool entryPoint = false;
3533 LocalSig localSig;
3534 ArrayList varArgSigList;
3535 ImplMap pinvokeImpl;
3536 Param ret_param;
3539 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base (name)
3541 this.retType = retType;
3542 metaData = md;
3543 parList = pars;
3544 if (parList != null) numPars = parList.Length;
3545 tabIx = MDTable.Method;
3548 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3549 Type retType, Param [] pars) : this (md, name, retType, pars)
3551 methFlags = (ushort)mAttrSet;
3552 implFlags = (ushort)iAttrSet;
3555 internal Param[] GetPars()
3557 return parList;
3560 internal override uint GetSigIx(MetaData md)
3562 MemoryStream sig = new MemoryStream();
3563 TypeSig(sig);
3564 return md.AddToBlobHeap(sig.ToArray());
3567 public override void AddCallConv(CallConv cconv)
3569 callConv |= cconv;
3572 /// <summary>
3573 /// Add some attributes to this method descriptor
3574 /// </summary>
3575 /// <param name="ma">the attributes to be added</param>
3576 public void AddMethAttribute(MethAttr ma)
3578 methFlags |= (ushort)ma;
3581 /// <summary>
3582 /// Add some implementation attributes to this method descriptor
3583 /// </summary>
3584 /// <param name="ia">the attributes to be added</param>
3585 public void AddImplAttribute(ImplAttr ia)
3587 implFlags |= (ushort)ia;
3590 public void AddPInvokeInfo(ModuleRef scope, string methName,
3591 PInvokeAttr callAttr) {
3592 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3593 methFlags |= PInvokeImpl;
3596 /// <summary>
3597 /// Add a named generic type parameter
3598 /// </summary>
3599 public GenericParameter AddGenericParameter (short index, string name)
3601 GenericParameter gp = new GenericParameter (this, metaData, index, name);
3602 metaData.AddToTable (MDTable.GenericParam, gp);
3603 gen_param_count ++;
3604 return gp;
3607 /// <summary>
3608 /// Set the maximum stack height for this method
3609 /// </summary>
3610 /// <param name="maxStack">the maximum height of the stack</param>
3611 public void SetMaxStack(int maxStack)
3613 this.maxStack = maxStack;
3616 /// <summary>
3617 /// Add local variables to this method
3618 /// </summary>
3619 /// <param name="locals">the locals to be added</param>
3620 /// <param name="initLocals">are locals initialised to default values</param>
3621 public void AddLocals(Local[] locals, bool initLocals)
3623 this.locals = locals;
3624 this.initLocals = initLocals;
3627 /* Add Marshal info for return type */
3628 public void AddRetTypeMarshallInfo (NativeType marshallType)
3630 ret_param = new Param (ParamAttr.HasFieldMarshal, "", retType);
3631 ret_param.AddMarshallInfo (marshallType);
3634 /// <summary>
3635 /// Mark this method as having an entry point
3636 /// </summary>
3637 public void DeclareEntryPoint()
3639 entryPoint = true;
3642 /// <summary>
3643 /// Create a code buffer for this method to add the IL instructions to
3644 /// </summary>
3645 /// <returns>a buffer for this method's IL instructions</returns>
3646 public CILInstructions CreateCodeBuffer()
3648 code = new CILInstructions(metaData);
3649 return code;
3652 /// <summary>
3653 /// Make a method reference descriptor for this method to be used
3654 /// as a callsite signature for this vararg method
3655 /// </summary>
3656 /// <param name="optPars">the optional pars for the vararg method call</param>
3657 /// <returns></returns>
3658 public MethodRef MakeVarArgSignature(Type[] optPars)
3660 Type[] pars = new Type[numPars];
3661 MethodRef varArgSig;
3662 for (int i=0; i < numPars; i++) {
3663 pars[i] = parList[i].GetParType();
3665 varArgSig = new MethodRef(this,name,retType,pars,true,optPars, 0);
3667 if (varArgSigList == null)
3668 varArgSigList = new ArrayList ();
3669 varArgSigList.Add (varArgSig);
3670 return varArgSig;
3673 internal sealed override void TypeSig(MemoryStream sig)
3675 sig.WriteByte((byte)callConv);
3676 if ((callConv & CallConv.Generic) == CallConv.Generic)
3677 MetaData.CompressNum ((uint) gen_param_count, sig);
3678 MetaData.CompressNum((uint)numPars,sig);
3679 if (ret_param != null)
3680 ret_param.seqNo = 0;
3681 retType.TypeSig(sig);
3682 for (ushort i=0; i < numPars; i++) {
3683 parList[i].seqNo = (ushort)(i+1);
3684 parList[i].TypeSig(sig);
3688 internal sealed override void BuildTables(MetaData md)
3690 if (done) return;
3691 if (pinvokeImpl != null) {
3692 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
3693 pinvokeImpl.BuildTables(md);
3695 if (entryPoint) md.SetEntryPoint(this);
3696 uint locToken = 0;
3697 if (locals != null) {
3698 localSig = new LocalSig(locals);
3699 md.AddToTable(MDTable.StandAloneSig,localSig);
3700 localSig.BuildTables(md);
3701 locToken = localSig.Token();
3703 if (code != null) {
3704 code.CheckCode(locToken,initLocals,maxStack);
3705 textOffset = md.AddCode(code);
3707 nameIx = md.AddToStringsHeap(name);
3708 sigIx = GetSigIx(md);
3709 parIx = md.TableIndex(MDTable.Param);
3710 if (ret_param != null) {
3711 md.AddToTable(MDTable.Param, ret_param);
3712 ret_param.BuildTables(md);
3714 for (int i=0; i < numPars; i++) {
3715 md.AddToTable(MDTable.Param,parList[i]);
3716 parList[i].BuildTables(md);
3718 if (varArgSigList != null) {
3719 foreach (MethodRef varArgSig in varArgSigList) {
3720 md.AddToTable(MDTable.MemberRef,varArgSig);
3721 varArgSig.BuildTables(md);
3724 // Console.WriteLine("method has " + numPars + " parameters");
3725 done = true;
3728 internal sealed override uint Size(MetaData md)
3730 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
3733 internal sealed override void Write(FileImage output)
3735 if (ZeroRva ()) output.Write(0);
3736 else output.WriteCodeRVA(textOffset);
3737 output.Write(implFlags);
3738 output.Write(methFlags);
3739 output.StringsIndex(nameIx);
3740 output.BlobIndex(sigIx);
3741 output.WriteIndex(MDTable.Param,parIx);
3744 internal bool ZeroRva ()
3746 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
3747 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
3748 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
3749 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
3752 internal sealed override uint GetCodedIx(CIx code)
3754 switch (code) {
3755 case (CIx.HasCustomAttr) : return 0;
3756 case (CIx.HasDeclSecurity) : return 1;
3757 case (CIx.MemberRefParent) : return 3;
3758 case (CIx.MethodDefOrRef) : return 0;
3759 case (CIx.MemberForwarded) : return 1;
3760 case (CIx.CustomAttributeType) : return 2;
3761 case (CIx.TypeOrMethodDef) : return 1;
3763 return 0;
3767 /**************************************************************************/
3768 /// <summary>
3769 /// Descriptor for a method defined in another assembly/module
3770 /// </summary>
3771 public class MethodRef : Method {
3773 private static readonly byte Sentinel = 0x41;
3774 Type[] parList, optParList;
3775 MetaDataElement parent;
3776 uint numPars = 0, numOptPars = 0;
3777 CallConv callConv = CallConv.Default;
3778 Type retType;
3779 int gen_param_count;
3781 internal MethodRef(MetaDataElement paren, string name, Type retType,
3782 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
3784 parent = paren;
3785 parList = pars;
3786 this.retType = retType;
3787 if (parList != null) numPars = (uint)parList.Length;
3788 if (varArgMeth) {
3789 optParList = optPars;
3790 if (optParList != null) numOptPars = (uint)optParList.Length;
3791 callConv = CallConv.Vararg;
3793 this.gen_param_count = gen_param_count;
3796 internal override uint GetSigIx(MetaData md)
3798 MemoryStream sig = new MemoryStream();
3799 TypeSig(sig);
3800 return md.AddToBlobHeap(sig.ToArray());
3803 public override void AddCallConv(CallConv cconv)
3805 callConv |= cconv;
3808 internal sealed override void TypeSig(MemoryStream sig)
3810 sig.WriteByte((byte)callConv);
3811 if ((callConv & CallConv.Generic) == CallConv.Generic)
3812 MetaData.CompressNum ((uint) gen_param_count, sig);
3813 MetaData.CompressNum(numPars+numOptPars,sig);
3814 retType.TypeSig(sig);
3815 for (int i=0; i < numPars; i++) {
3816 parList[i].TypeSig(sig);
3818 if (numOptPars > 0) {
3819 sig.WriteByte(Sentinel);
3820 for (int i=0; i < numOptPars; i++) {
3821 optParList[i].TypeSig(sig);
3826 internal sealed override void BuildTables(MetaData md)
3828 if (done) return;
3829 nameIx = md.AddToStringsHeap(name);
3830 sigIx = GetSigIx(md);
3831 done = true;
3834 internal sealed override uint Size(MetaData md)
3836 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3839 internal sealed override void Write(FileImage output)
3841 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3842 output.StringsIndex(nameIx);
3843 output.BlobIndex(sigIx);
3846 internal sealed override uint GetCodedIx(CIx code)
3848 switch (code) {
3849 case (CIx.HasCustomAttr) : return 6;
3850 case (CIx.MethodDefOrRef) : return 1;
3851 case (CIx.CustomAttributeType) : return 3;
3853 return 0;
3859 /**************************************************************************/
3860 /// <summary>
3861 /// Descriptors for native types used for marshalling
3862 /// </summary>
3863 public class NativeType {
3864 public static readonly NativeType Void = new NativeType(0x01);
3865 public static readonly NativeType Boolean = new NativeType(0x02);
3866 public static readonly NativeType Int8 = new NativeType(0x03);
3867 public static readonly NativeType UInt8 = new NativeType(0x04);
3868 public static readonly NativeType Int16 = new NativeType(0x05);
3869 public static readonly NativeType UInt16 = new NativeType(0x06);
3870 public static readonly NativeType Int32 = new NativeType(0x07);
3871 public static readonly NativeType UInt32 = new NativeType(0x08);
3872 public static readonly NativeType Int64 = new NativeType(0x09);
3873 public static readonly NativeType UInt64 = new NativeType(0x0A);
3874 public static readonly NativeType Float32 = new NativeType(0x0B);
3875 public static readonly NativeType Float64 = new NativeType(0x0C);
3876 public static readonly NativeType Currency = new NativeType(0x0F);
3877 public static readonly NativeType BStr = new NativeType(0x13);
3878 public static readonly NativeType LPStr = new NativeType(0x14);
3879 public static readonly NativeType LPWStr = new NativeType(0x15);
3880 public static readonly NativeType LPTStr = new NativeType(0x16);
3881 public static readonly NativeType FixedSysString = new NativeType(0x17);
3882 public static readonly NativeType IUnknown = new NativeType(0x19);
3883 public static readonly NativeType IDispatch = new NativeType(0x1A);
3884 public static readonly NativeType Struct = new NativeType(0x1B);
3885 public static readonly NativeType Interface = new NativeType(0x1C);
3886 public static readonly NativeType Int = new NativeType(0x1F);
3887 public static readonly NativeType UInt = new NativeType(0x20);
3888 public static readonly NativeType ByValStr = new NativeType(0x22);
3889 public static readonly NativeType AnsiBStr = new NativeType(0x23);
3890 public static readonly NativeType TBstr = new NativeType(0x24);
3891 public static readonly NativeType VariantBool = new NativeType(0x25);
3892 public static readonly NativeType FuncPtr = new NativeType(0x26);
3893 public static readonly NativeType AsAny = new NativeType(0x28);
3895 protected byte typeIndex;
3897 internal NativeType(byte tyIx) { typeIndex = tyIx; }
3898 internal byte GetTypeIndex() { return typeIndex; }
3900 internal virtual byte[] ToBlob()
3902 byte[] bytes = new byte[1];
3903 bytes[0] = GetTypeIndex();
3904 return bytes;
3909 public class FixedSysString : NativeType {
3911 uint size;
3913 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
3915 this.size = size;
3918 internal override byte [] ToBlob ()
3920 MemoryStream str = new MemoryStream ();
3921 str.WriteByte (GetTypeIndex ());
3922 MetaData.CompressNum (size, str);
3923 return str.ToArray ();
3928 public class NativeArray : NativeType {
3930 NativeType elemType;
3931 int numElem = -1, parNum = -1, elemMult = -1;
3933 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
3935 this.elemType = elemType;
3938 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
3939 this.elemType = elemType;
3940 this.len = len;
3944 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
3946 this.elemType = elemType;
3947 this.numElem = numElem;
3948 parNum = parNumForLen;
3949 this.elemMult = elemMult;
3952 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
3953 : this (elemType, numElem, parNumForLen, -1)
3957 internal override byte[] ToBlob()
3959 MemoryStream str = new MemoryStream();
3960 str.WriteByte(GetTypeIndex());
3961 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
3962 else str.WriteByte(elemType.GetTypeIndex());
3964 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
3965 * LAMESPEC: Older spec versions say elemMult comes before
3966 * len. Newer spec versions don't talk about elemMult at
3967 * all, but csc still emits it, and it is used to distinguish
3968 * between parNum being 0, and parNum being omitted.
3971 if (parNum == -1)
3972 // <native_type> []
3973 return str.ToArray ();
3975 MetaData.CompressNum((uint) parNum,str);
3976 if (numElem != -1) {
3977 MetaData.CompressNum ((uint) numElem, str);
3978 if (elemMult != -1)
3979 // <native_type> [ int32 ]
3980 MetaData.CompressNum((uint) elemMult,str);
3981 //else <native_type> [ int32 + int32 ]
3982 } else if (elemMult != -1) {
3983 // When can this occur ?
3984 MetaData.CompressNum (0, str);
3985 MetaData.CompressNum((uint) elemMult,str);
3987 //else <native_type> [ + int32 ]
3989 return str.ToArray();
3994 public class SafeArray : NativeType {
3996 SafeArrayType elemType;
3997 bool hasElemType;
3999 public SafeArray() : base(0x1D)
4003 public SafeArray(SafeArrayType elemType) : base(0x1D)
4005 this.elemType = elemType;
4006 hasElemType = true;
4009 internal override byte[] ToBlob()
4011 byte[] bytes = new byte[hasElemType ? 2 : 1];
4012 bytes[0] = GetTypeIndex();
4013 if (hasElemType)
4014 bytes[1] = (byte)elemType;
4015 return bytes;
4020 public class FixedArray : NativeType {
4022 NativeType elemType;
4023 uint numElem;
4025 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4026 public FixedArray(int numElems) : base(0x1E)
4028 //this.elemType = elemType;
4029 numElem = (uint)numElems;
4032 internal override byte[] ToBlob()
4034 MemoryStream str = new MemoryStream();
4035 str.WriteByte(GetTypeIndex());
4036 MetaData.CompressNum(numElem,str);
4037 /* FIXME:
4038 fixed array [5] lpstr [2]
4039 This format is not supported by ilasm 1.1.4322.2032,
4040 but is supported by 2.0.5125..
4041 ilasm 1.1 only supports "fixed array [5]"
4042 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4043 else str.WriteByte(elemType.GetTypeIndex());*/
4045 return str.ToArray();
4050 public class CustomMarshaller : NativeType {
4052 string typeName;
4053 string marshallerName;
4054 string cookie;
4056 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4057 string optCookie) : base(0x2C)
4059 typeName = typeNameOrGUID;
4060 this.marshallerName = marshallerName;
4061 cookie = optCookie;
4064 public CustomMarshaller(string marshallerName, string optCookie)
4065 :this (null, marshallerName, optCookie)
4069 internal override byte[] ToBlob()
4071 MemoryStream str = new MemoryStream();
4072 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4073 bw.Write(GetTypeIndex());
4074 //Native type name & unmanaged type - unused
4075 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4076 bw.Write ((byte) 0); // Native Type name, unused
4077 bw.Write ((byte) 0); // Unmanaged type, unused
4078 if (marshallerName != null) {
4079 MetaData.CompressNum ((uint)marshallerName.Length, str);
4080 bw.Write(marshallerName.ToCharArray());
4081 } else {
4082 bw.Write ((byte) 0);
4084 if (cookie != null) {
4085 MetaData.CompressNum ((uint)cookie.Length, str);
4086 bw.Write(cookie.ToCharArray());
4087 } else {
4088 bw.Write ((byte) 0);
4090 bw.Flush();
4091 return str.ToArray();
4095 /**************************************************************************/
4096 /// <summary>
4097 /// Descriptor for the Primitive types defined in IL
4098 /// </summary>
4099 public class PrimitiveType : Type {
4101 private string name;
4102 private int systemTypeIndex;
4103 public static int NumSystemTypes = 18;
4105 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4106 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4107 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4108 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4109 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4110 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4111 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4112 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4113 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4114 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4115 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4116 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4117 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4118 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4119 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4120 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4121 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4122 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4123 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4124 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4125 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4126 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4127 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4128 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4129 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4130 public static readonly PrimitiveType NativeInt = IntPtr;
4131 public static readonly PrimitiveType NativeUInt = UIntPtr;
4133 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4135 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4137 this.name = name;
4138 this.systemTypeIndex = STIx;
4141 internal string GetName() { return name; }
4143 internal int GetSystemTypeIx() { return systemTypeIndex; }
4145 internal sealed override void TypeSig(MemoryStream str)
4147 str.WriteByte(typeIndex);
4150 internal override MetaDataElement GetTypeSpec(MetaData md)
4152 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4153 if (tS == null) {
4154 tS = new TypeSpec(this,md);
4155 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4156 md.AddToTable(MDTable.TypeSpec,tS);
4158 return tS;
4163 /**************************************************************************/
4164 /// <summary>
4165 /// Descriptor for an pointer (type * or type &)
4166 /// </summary>
4167 public abstract class PtrType : Type {
4169 Type baseType;
4171 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4173 baseType = bType;
4174 tabIx = MDTable.TypeSpec;
4177 internal sealed override void TypeSig(MemoryStream str)
4179 str.WriteByte(typeIndex);
4180 baseType.TypeSig(str);
4184 /**************************************************************************/
4185 /// <summary>
4186 /// Descriptor for a managed pointer (type & or byref)
4187 /// </summary>
4189 public class ManagedPointer : PtrType {
4191 /// <summary>
4192 /// Create new managed pointer to baseType
4193 /// </summary>
4194 /// <param name="bType">the base type of the pointer</param>
4195 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4198 /**************************************************************************/
4199 /// <summary>
4200 /// Descriptor for an unmanaged pointer (type *)
4201 /// </summary>
4202 public class UnmanagedPointer : PtrType {
4204 /// <summary>
4205 /// Create a new unmanaged pointer to baseType
4206 /// </summary>
4207 /// <param name="baseType">the base type of the pointer</param>
4208 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4212 /**************************************************************************/
4214 public interface IExternRef {
4215 ClassRef AddClass(string nsName, string name);
4216 ClassRef AddValueClass(string nsName, string name);
4219 /// <summary>
4220 /// A reference to an external assembly (.assembly extern)
4221 /// </summary>
4222 public class AssemblyRef : ResolutionScope, IExternRef {
4224 private ushort major, minor, build, revision;
4225 uint flags, keyIx, hashIx, cultIx;
4226 bool hasVersion = false, isKeyToken = false;
4227 byte[] keyBytes;
4228 string culture;
4230 internal AssemblyRef(MetaData md, string name) : base(name,md)
4232 tabIx = MDTable.AssemblyRef;
4235 /// <summary>
4236 /// Add version information about this external assembly
4237 /// </summary>
4238 /// <param name="majVer">Major Version</param>
4239 /// <param name="minVer">Minor Version</param>
4240 /// <param name="bldNo">Build Number</param>
4241 /// <param name="revNo">Revision Number</param>
4242 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4244 major = (ushort)majVer;
4245 minor = (ushort)minVer;
4246 build = (ushort)bldNo;
4247 revision = (ushort)revNo;
4248 hasVersion = true;
4251 /// <summary>
4252 /// Add the hash value for this external assembly
4253 /// </summary>
4254 /// <param name="hash">bytes of the hash value</param>
4255 public void AddHash(byte[] hash)
4257 hashIx = metaData.AddToBlobHeap(hash);
4260 /// <summary>
4261 /// Set the culture for this external assembly
4262 /// </summary>
4263 /// <param name="cult">the culture string</param>
4264 public void AddCulture(string cult)
4266 cultIx = metaData.AddToStringsHeap(cult);
4267 culture = cult;
4270 /// <summary>
4271 /// Add the full public key for this external assembly
4272 /// </summary>
4273 /// <param name="key">bytes of the public key</param>
4274 public void AddKey(byte[] key)
4276 flags |= 0x0001; // full public key
4277 keyBytes = key;
4278 keyIx = metaData.AddToBlobHeap(key);
4281 /// <summary>
4282 /// Add the public key token (low 8 bytes of the public key)
4283 /// </summary>
4284 /// <param name="key">low 8 bytes of public key</param>
4285 public void AddKeyToken(byte[] key)
4287 keyIx = metaData.AddToBlobHeap(key);
4288 keyBytes = key;
4289 isKeyToken = true;
4292 /// <summary>
4293 /// Add a class to this external assembly
4294 /// </summary>
4295 /// <param name="nsName">name space name</param>
4296 /// <param name="name">class name</param>
4297 /// <returns></returns>
4298 public virtual ClassRef AddClass(string nsName, string name)
4300 ClassRef aClass = new ClassRef(nsName,name,metaData);
4301 metaData.AddToTable(MDTable.TypeRef,aClass);
4302 aClass.SetParent(this);
4303 return aClass;
4306 /// <summary>
4307 /// Add a value class to this external assembly
4308 /// </summary>
4309 /// <param name="nsName">name space name</param>
4310 /// <param name="name">class name</param>
4311 /// <returns></returns>
4312 public virtual ClassRef AddValueClass(string nsName, string name)
4314 ClassRef aClass = new ClassRef(nsName,name,metaData);
4315 metaData.AddToTable(MDTable.TypeRef,aClass);
4316 aClass.SetParent(this);
4317 aClass.MakeValueClass(ValueClass.ValueType);
4318 return aClass;
4321 internal string TypeName()
4323 string result = name;
4324 if (hasVersion)
4325 result = result + ", Version=" + major + "." + minor + "." +
4326 build + "." + revision;
4327 if (keyBytes != null) {
4328 string tokenStr = "=";
4329 if (isKeyToken) tokenStr = "Token=";
4330 result = result + ", PublicKey" + tokenStr;
4331 for (int i=0; i < keyBytes.Length; i++) {
4332 result = result + Hex.Byte(keyBytes[i]);
4335 if (culture != null)
4336 result = result + ", Culture=" + culture;
4337 return result;
4340 internal sealed override uint Size(MetaData md)
4342 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4345 internal sealed override void Write(FileImage output)
4347 output.Write(major);
4348 output.Write(minor);
4349 output.Write(build);
4350 output.Write(revision);
4351 output.Write(flags);
4352 output.BlobIndex(keyIx);
4353 output.StringsIndex(nameIx);
4354 output.StringsIndex(cultIx);
4355 output.BlobIndex(hashIx);
4358 internal sealed override uint GetCodedIx(CIx code)
4360 switch (code) {
4361 case (CIx.ResolutionScope) : return 2;
4362 case (CIx.HasCustomAttr) : return 15;
4363 case (CIx.Implementation) : return 1;
4365 return 0;
4370 /**************************************************************************/
4371 /// <summary>
4372 /// Descriptor for a class defined in System (mscorlib)
4373 /// </summary>
4374 internal class SystemClass : ClassRef {
4376 PrimitiveType elemType;
4378 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4379 : base("System",eType.GetName(),md) {
4380 elemType = eType;
4381 parent = paren;
4384 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4386 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4387 return typeSpec;
4391 internal sealed override void TypeSig(MemoryStream str)
4393 str.WriteByte(elemType.GetTypeIndex());
4398 /**************************************************************************/
4399 /// <summary>
4400 /// The assembly for mscorlib.
4401 /// </summary>
4402 public sealed class MSCorLib : AssemblyRef {
4404 private static readonly int valueTypeIx = 18;
4405 private readonly string systemName = "System";
4406 private Class[] systemClasses = new Class[valueTypeIx+2];
4407 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4408 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
4409 private static int[] specialNames = {
4410 PrimitiveType.Void.GetName().GetHashCode(),
4411 PrimitiveType.Boolean.GetName().GetHashCode(),
4412 PrimitiveType.Char.GetName().GetHashCode(),
4413 PrimitiveType.Int8.GetName().GetHashCode(),
4414 PrimitiveType.UInt8.GetName().GetHashCode(),
4415 PrimitiveType.Int16.GetName().GetHashCode(),
4416 PrimitiveType.UInt16.GetName().GetHashCode(),
4417 PrimitiveType.Int32.GetName().GetHashCode(),
4418 PrimitiveType.UInt32.GetName().GetHashCode(),
4419 PrimitiveType.Int64.GetName().GetHashCode(),
4420 PrimitiveType.UInt64.GetName().GetHashCode(),
4421 PrimitiveType.Float32.GetName().GetHashCode(),
4422 PrimitiveType.Float64.GetName().GetHashCode(),
4423 PrimitiveType.String.GetName().GetHashCode(),
4424 PrimitiveType.TypedRef.GetName().GetHashCode(),
4425 PrimitiveType.IntPtr.GetName().GetHashCode(),
4426 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4427 PrimitiveType.Object.GetName().GetHashCode(),
4428 PrimitiveType.ValueType.GetName ().GetHashCode(),
4429 "Enum".GetHashCode()
4432 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4434 if (!PEFile.IsMSCorlib)
4435 md.AddToTable(MDTable.AssemblyRef,this);
4436 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4437 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4438 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4439 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4440 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4441 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4442 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4443 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4444 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4445 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4446 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4447 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4448 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4449 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4450 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4451 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4452 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4453 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4456 /// <summary>
4457 /// Add a class to the mscorlib assembly
4458 /// </summary>
4459 /// <param name="nsName">name space name</param>
4460 /// <param name="name">class name</param>
4461 /// <returns></returns>
4462 public override ClassRef AddClass(string nsName, string name)
4464 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4465 it should be returning ClassRef ..*/
4466 Class aClass = GetSpecialClass(nsName,name);
4467 if (aClass == null) {
4468 aClass = new ClassRef(nsName,name,metaData);
4469 metaData.AddToTable(MDTable.TypeRef,aClass);
4470 if (aClass is ClassRef)
4471 ((ClassRef) aClass).SetParent(this);
4473 //FIXME: Check for !ClassRef here?
4474 return (ClassRef) aClass;
4477 private Class GetSpecialClass(string nsName,string name)
4479 if (nsName.CompareTo(systemName) != 0) return null;
4480 int hash = name.GetHashCode();
4481 for (int i=0; i < specialNames.Length; i++) {
4482 if (hash != specialNames[i])
4483 continue;
4484 if (systemClasses[i] == null) {
4485 if (i < valueTypeIx) {
4486 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4487 if ((systemTypes[i] != PrimitiveType.Object) &&
4488 (systemTypes[i] != PrimitiveType.String)) {
4489 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4491 } else {
4492 systemClasses[i] = new ClassRef(nsName,name,metaData);
4493 ((ClassRef) systemClasses[i]).SetParent(this);
4494 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4495 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4497 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4499 return systemClasses[i];
4501 return null;
4504 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4506 if (nsName != systemName) return;
4507 int hash = name.GetHashCode ();
4508 for (int i = 0; i < specialNames.Length; i++) {
4509 if (hash != specialNames [i])
4510 continue;
4511 if (systemClasses [i] == null) {
4512 systemClasses [i] = aClass;
4517 internal Class GetSpecialSystemClass(PrimitiveType pType)
4519 int ix = pType.GetSystemTypeIx();
4520 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4521 systemClasses[ix] = new SystemClass(pType,this,metaData);
4522 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4524 return systemClasses[ix];
4527 private ClassRef GetValueClass(string name, int hash)
4529 /* Called by MSCorLib.AddValueClass, which is called by
4530 !mscorlib, for adding ref to value class INTO mscorlib,
4531 so this should be classref */
4532 int ix = valueTypeIx;
4533 if (hash != specialNames[valueTypeIx]) ix++;
4534 if (systemClasses[ix] == null) {
4535 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4536 ((ClassRef) systemClasses[ix]).SetParent(this);
4537 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4538 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4540 return (ClassRef) systemClasses[ix];
4543 internal Class ValueType()
4545 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4546 ClassRef valType = new ClassRef("System","ValueType",metaData);
4547 valType.SetParent(this);
4548 valType.MakeValueClass(ValueClass.ValueType);
4549 metaData.AddToTable(MDTable.TypeRef,valType);
4550 systemClasses[valueTypeIx] = valType;
4552 return systemClasses[valueTypeIx];
4555 internal Class EnumType()
4557 /* Called by both mscorlib & !mscorlib, so can be
4558 either ClassRef or ClassDef */
4559 //systemClasses [ valueTypeIx + 1] -> System.Enum
4560 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4561 ClassRef valType = new ClassRef("System","Enum",metaData);
4562 valType.SetParent(this);
4563 valType.MakeValueClass(ValueClass.Enum);
4564 metaData.AddToTable(MDTable.TypeRef,valType);
4565 systemClasses[valueTypeIx + 1] = valType;
4567 return systemClasses[valueTypeIx + 1];
4570 /// <summary>
4571 /// Add a value class to this external assembly
4572 /// </summary>
4573 /// <param name="nsName">name space name</param>
4574 /// <param name="name">class name</param>
4575 /// <returns></returns>
4576 public override ClassRef AddValueClass(string nsName, string name)
4578 if (nsName.CompareTo(systemName) == 0) {
4579 int hash = name.GetHashCode();
4580 if ((hash == specialNames[valueTypeIx]) ||
4581 (hash == specialNames[valueTypeIx+1])) {
4582 return GetValueClass(name,hash);
4585 ClassRef aClass = new ClassRef(nsName,name,metaData);
4586 metaData.AddToTable(MDTable.TypeRef,aClass);
4587 aClass.SetParent(this);
4588 aClass.MakeValueClass(ValueClass.ValueType);
4589 return aClass;
4594 /**************************************************************************/
4595 /// <summary>
4596 /// MetaData
4597 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4598 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4599 /// Streams
4600 /// #~ (always present - holds metadata tables)
4601 /// #Strings (always present - holds identifier strings)
4602 /// #US (Userstring heap)
4603 /// #Blob (signature blobs)
4604 /// #GUID (guids for assemblies or Modules)
4605 /// </summary>
4606 public class MetaData {
4608 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4609 private static readonly byte StringsHeapMask = 0x1;
4610 private static readonly byte GUIDHeapMask = 0x2;
4611 private static readonly byte BlobHeapMask = 0x4;
4612 private static readonly uint MetaDataSignature = 0x424A5342;
4613 private static readonly uint maxSmlIxSize = 0xFFFF;
4614 private static readonly uint max1BitSmlIx = 0x7FFF;
4615 private static readonly uint max2BitSmlIx = 0x3FFF;
4616 private static readonly uint max3BitSmlIx = 0x1FFF;
4617 private static readonly uint max5BitSmlIx = 0x7FF;
4618 // NOTE: version and stream name strings MUST always be quad padded
4619 #if NET_2_0 || BOOTSTRAP_NET_2_0
4620 private static readonly string version = "v2.0.50727\0\0";
4621 #else
4622 private static readonly string version = "v1.1.4322\0\0\0";
4623 #endif
4624 private static readonly char[] tildeName = {'#','~','\0','\0'};
4625 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4626 private static readonly char[] usName = {'#','U','S','\0'};
4627 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4628 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4629 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4630 private static readonly uint TildeHeaderSize = 24;
4631 private static readonly uint StreamHeaderSize = 8;
4632 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4633 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
4635 MetaDataStream strings, us, guid, blob;
4637 MetaDataStream[] streams = new MetaDataStream[5];
4638 uint numStreams = 5;
4639 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4640 uint numTables = 0, resourcesSize = 0;
4641 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4642 ArrayList byteCodes = new ArrayList();
4643 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4644 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4645 bool[] largeIx = new bool[numMetaDataTables];
4646 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4647 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4648 private FileImage file;
4649 private byte heapSizes = 0;
4650 MetaDataElement entryPoint;
4651 BinaryWriter output;
4652 public MSCorLib mscorlib;
4653 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4654 long mdStart;
4655 private ArrayList cattr_list;
4656 private ArrayList declsec_list;
4657 ArrayList resources;
4659 internal MetaData(FileImage file)
4661 // tilde = new MetaDataStream(tildeName,false,0);
4662 this.file = file;
4663 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4664 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4665 guid = new MetaDataStream(guidName,false);
4666 blob = new MetaDataStream(blobName,true);
4667 streams[1] = strings;
4668 streams[2] = us;
4669 streams[3] = guid;
4670 streams[4] = blob;
4671 for (int i=0; i < numMetaDataTables; i++) {
4672 largeIx[i] = false;
4674 for (int i=0; i < lgeCIx.Length; i++) {
4675 lgeCIx[i] = false;
4677 mscorlib = new MSCorLib(this);
4680 internal TypeSpec GetPrimitiveTypeSpec(int ix)
4682 return systemTypeSpecs[ix];
4685 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
4687 systemTypeSpecs[ix] = typeSpec;
4690 internal uint Size()
4692 return metaDataSize;
4695 private void CalcHeapSizes ()
4697 if (strings.LargeIx()) {
4698 largeStrings = true;
4699 heapSizes |= StringsHeapMask;
4701 if (guid.LargeIx()) {
4702 largeGUID = true;
4703 heapSizes |= GUIDHeapMask;
4705 if (blob.LargeIx()) {
4706 largeBlob = true;
4707 heapSizes |= BlobHeapMask;
4710 largeUS = us.LargeIx();
4713 internal void StreamSize(byte mask)
4715 heapSizes |= mask;
4718 internal uint AddToUSHeap(string str)
4720 if (str == null) return 0;
4721 return us.Add(str,true);
4724 internal uint AddToUSHeap(byte[] str)
4726 if (str == null) return 0;
4727 return us.Add (str, true);
4730 internal uint AddToStringsHeap(string str)
4732 if ((str == null) || (str.CompareTo("") == 0)) return 0;
4733 return strings.Add(str,false);
4736 internal uint AddToGUIDHeap(Guid guidNum)
4738 return guid.Add(guidNum, false);
4741 internal uint AddToBlobHeap(byte[] blobBytes)
4743 if (blobBytes == null) return 0;
4744 return blob.Add(blobBytes, true);
4747 internal uint AddToBlobHeap(byte val)
4749 return blob.Add(val, true);
4752 internal uint AddToBlobHeap(sbyte val)
4754 return blob.Add(val, true);
4757 internal uint AddToBlobHeap(ushort val)
4759 return blob.Add(val, true);
4762 internal uint AddToBlobHeap(short val)
4764 return blob.Add(val, true);
4767 internal uint AddToBlobHeap(uint val)
4769 return blob.Add(val, true);
4772 internal uint AddToBlobHeap(int val)
4774 return blob.Add(val, true);
4777 internal uint AddToBlobHeap(ulong val)
4779 return blob.Add(val, true);
4782 internal uint AddToBlobHeap(long val)
4784 return blob.Add(val, true);
4787 internal uint AddToBlobHeap(float val)
4789 return blob.Add(val, true);
4792 internal uint AddToBlobHeap(double val)
4794 return blob.Add(val, true);
4797 internal uint AddToBlobHeap(string val)
4799 return blob.Add(val,true);
4802 internal void AddCustomAttribute (CustomAttribute cattr)
4804 if (cattr_list == null)
4805 cattr_list = new ArrayList ();
4806 cattr_list.Add (cattr);
4809 internal void AddDeclSecurity (DeclSecurity decl_sec)
4811 if (declsec_list == null)
4812 declsec_list = new ArrayList ();
4813 declsec_list.Add (decl_sec);
4816 private ArrayList GetTable(MDTable tableIx)
4818 int tabIx = (int)tableIx;
4819 if (metaDataTables[tabIx] == null) {
4820 metaDataTables[tabIx] = new ArrayList();
4821 valid |= ((ulong)0x1 << tabIx);
4822 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
4823 numTables++;
4825 return metaDataTables[tabIx];
4828 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
4830 if (elem.Row > 0) {
4831 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
4832 return;
4834 // updates Row field of the element
4835 // Console.WriteLine("Adding element to table " + (uint)tableIx);
4836 ArrayList table = GetTable(tableIx);
4837 elem.Row = (uint)table.Count + 1;
4838 table.Add(elem);
4841 internal uint TableIndex(MDTable tableIx)
4843 if (metaDataTables[(int)tableIx] == null) return 1;
4844 return (uint)metaDataTables[(int)tableIx].Count+1;
4847 internal uint AddCode(CILInstructions byteCode)
4849 byteCodes.Add(byteCode);
4850 uint offset = codeSize + codeStart;
4851 codeSize += byteCode.GetCodeSize();
4852 return offset;
4855 internal void SetEntryPoint(MetaDataElement ep)
4857 entryPoint = ep;
4860 internal uint AddResource(byte[] resBytes)
4862 if (resources == null) resources = new ArrayList ();
4863 resources.Add (resBytes);
4864 uint offset = resourcesSize;
4865 resourcesSize += (uint)resBytes.Length + 4;
4866 return offset;
4869 internal void AddData(DataConstant cVal)
4871 file.AddInitData(cVal);
4874 internal static void CompressNum(uint val, MemoryStream sig)
4876 if (val < 0x7F) {
4877 sig.WriteByte((byte)val);
4878 } else if (val < 0x3FFF) {
4879 byte b1 = (byte)((val >> 8) | 0x80);
4880 byte b2 = (byte)(val & FileImage.iByteMask[0]);
4881 sig.WriteByte(b1);
4882 sig.WriteByte(b2);
4883 } else {
4884 byte b1 = (byte)((val >> 24) | 0xC0);
4885 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
4886 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
4887 byte b4 = (byte)(val & FileImage.iByteMask[0]);
4888 sig.WriteByte(b1);
4889 sig.WriteByte(b2);
4890 sig.WriteByte(b3);
4891 sig.WriteByte(b4);
4895 internal uint CodeSize()
4897 return codeSize + byteCodePadding;
4900 internal uint GetResourcesSize()
4902 return resourcesSize;
4905 internal uint StringsIndexSize()
4907 if (largeStrings) return 4;
4908 return 2;
4911 internal uint GUIDIndexSize()
4913 if (largeGUID) return 4;
4914 return 2;
4917 internal uint USIndexSize()
4919 if (largeUS) return 4;
4920 return 2;
4923 internal uint BlobIndexSize()
4925 if (largeBlob) return 4;
4926 return 2;
4929 internal uint CodedIndexSize(CIx code)
4931 if (lgeCIx[(uint)code]) return 4;
4932 return 2;
4935 internal uint TableIndexSize(MDTable tabIx)
4937 if (largeIx[(uint)tabIx]) return 4;
4938 return 2;
4941 private void SetIndexSizes()
4943 for (int i=0; i < numMetaDataTables; i++) {
4944 if (metaDataTables[i] == null)
4945 continue;
4947 uint count = (uint)metaDataTables[i].Count;
4948 if (count > maxSmlIxSize)
4949 largeIx[i] = true;
4951 MDTable tabIx = (MDTable)i;
4952 if (count > max5BitSmlIx) {
4953 lgeCIx[(int)CIx.HasCustomAttr] = true;
4955 if (count > max3BitSmlIx) {
4956 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
4957 lgeCIx[(int)CIx.CustomAttributeType] = true;
4958 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
4959 lgeCIx[(int)CIx.MemberRefParent] = true;
4961 if (count > max2BitSmlIx) {
4962 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
4963 lgeCIx[(int)CIx.HasConst] = true;
4964 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
4965 lgeCIx[(int)CIx.TypeDefOrRef] = true;
4966 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
4967 lgeCIx[(int)CIx.HasDeclSecurity] = true;
4968 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
4969 lgeCIx[(int)CIx.Implementation] = true;
4970 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
4971 lgeCIx[(int)CIx.ResolutionScope] = true;
4973 if (count > max1BitSmlIx) {
4974 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
4975 lgeCIx[(int)CIx.HasFieldMarshal] = true;
4976 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
4977 lgeCIx[(int)CIx.HasSemantics] = true;
4978 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
4979 lgeCIx[(int)CIx.MethodDefOrRef] = true;
4980 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
4981 lgeCIx[(int)CIx.MemberForwarded] = true;
4982 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
4983 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
4988 private void SetStreamOffsets()
4990 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
4991 for (int i=1; i < numStreams; i++) {
4992 sizeOfHeaders += streams[i].headerSize();
4994 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
4995 tildeStart = metaDataSize;
4996 metaDataSize += tildeTide + tildePadding;
4997 for (int i=1; i < numStreams; i++) {
4998 streams[i].Start = metaDataSize;
4999 metaDataSize += streams[i].Size();
5000 streams[i].WriteDetails();
5004 internal void CalcTildeStreamSize()
5006 CalcHeapSizes ();
5007 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5008 tildeTide = TildeHeaderSize;
5009 tildeTide += 4 * numTables;
5010 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5011 for (int i=0; i < numMetaDataTables; i++) {
5012 if (metaDataTables[i] != null) {
5013 ArrayList table = metaDataTables[i];
5014 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5015 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5016 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5017 // Console.WriteLine("tildeTide = " + tildeTide);
5020 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5021 //Console.WriteLine("tildePadding = " + tildePadding);
5024 internal void WriteTildeStream(FileImage output)
5026 long startTilde = output.Seek(0,SeekOrigin.Current);
5027 output.Write((uint)0); // Reserved
5028 #if NET_2_0 || BOOTSTRAP_NET_2_0
5029 output.Write((byte)2); // MajorVersion
5030 output.Write((byte)0); // MinorVersion
5031 #else
5032 output.Write((byte)1); // MajorVersion
5033 output.Write((byte)0); // MinorVersion
5034 #endif
5035 output.Write(heapSizes);
5036 output.Write((byte)1); // Reserved
5037 output.Write(valid);
5038 output.Write(sorted);
5039 for (int i=0; i < numMetaDataTables; i++) {
5040 if (metaDataTables[i] != null) {
5041 uint count = (uint)metaDataTables[i].Count;
5042 output.Write(count);
5045 long tabStart = output.Seek(0,SeekOrigin.Current);
5046 // Console.WriteLine("Starting metaData tables at " + tabStart);
5047 for (int i=0; i < numMetaDataTables; i++) {
5048 if (metaDataTables[i] != null) {
5049 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5050 ArrayList table = metaDataTables[i];
5051 for (int j=0; j < table.Count; j++) {
5052 ((MetaDataElement)table[j]).Write(output);
5056 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5057 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5060 private void BuildTable(ArrayList table)
5062 if (table == null) return;
5063 for (int j=0; j < table.Count; j++) {
5064 ((MetaDataElement)table[j]).BuildTables(this);
5068 private void SortTable (ArrayList mTable)
5070 if (mTable == null) return;
5071 mTable.Sort();
5072 for (int i=0; i < mTable.Count; i++) {
5073 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5077 internal void BuildMetaData(uint codeStartOffset)
5079 codeStart = codeStartOffset;
5080 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5081 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5082 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5083 #if NET_2_0 || BOOTSTRAP_NET_2_0
5084 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5085 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5086 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5087 #endif
5088 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5090 if (cattr_list != null) {
5091 foreach (CustomAttribute cattr in cattr_list)
5092 cattr.BuildTables (this);
5095 if (declsec_list != null) {
5096 foreach (DeclSecurity decl_sec in declsec_list)
5097 decl_sec.BuildTables (this);
5100 /* for (int i=0; i < metaDataTables.Length; i++) {
5101 ArrayList table = metaDataTables[i];
5102 if (table != null) {
5103 for (int j=0; j < table.Count; j++) {
5104 ((MetaDataElement)table[j]).BuildTables(this);
5110 SetIndexSizes();
5111 for (int i=1; i < numStreams; i++) {
5112 streams[i].EndStream();
5114 CalcTildeStreamSize();
5115 SetStreamOffsets();
5116 byteCodePadding = NumToAlign(codeSize,4);
5117 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5119 // Check ordering of specific tables
5120 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5121 // ImplMap, GenericParam
5122 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5123 // The tables:
5124 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5125 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5127 SortTable(metaDataTables[(int)MDTable.Constant]);
5128 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5129 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5130 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5131 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5132 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5133 #if NET_2_0 || BOOTSTRAP_NET_2_0
5134 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5135 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5136 // Now add GenericParamConstraints
5137 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5138 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5141 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5142 #endif
5143 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5147 internal void WriteByteCodes(FileImage output)
5149 for (int i=0; i < byteCodes.Count; i++) {
5150 ((CILInstructions)byteCodes[i]).Write(output);
5152 for (int i=0; i < byteCodePadding; i++) {
5153 output.Write((byte)0);
5157 internal void WriteResources (FileImage output)
5159 if (resources == null) return;
5160 for (int i = 0; i < resources.Count; i ++) {
5161 byte [] resBytes = (byte []) resources [i];
5162 output.Write ((uint) resBytes.Length);
5163 output.Write (resBytes);
5167 internal void WriteMetaData(FileImage output)
5169 this.output = output;
5170 mdStart = output.Seek(0,SeekOrigin.Current);
5171 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5172 output.Write(MetaDataSignature);
5173 output.Write((short)1); // Major Version
5174 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5175 output.Write(0); // Reserved
5176 output.Write(version.Length);
5177 output.Write(version.ToCharArray()); // version string is already zero padded
5178 output.Write((short)0);
5179 output.Write((ushort)numStreams);
5180 // write tilde header
5181 output.Write(tildeStart);
5182 output.Write(tildeTide + tildePadding);
5183 output.Write(tildeName);
5184 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5185 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5186 WriteTildeStream(output);
5187 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5188 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5191 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5192 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5193 internal bool LargeUSIndex() { return us.LargeIx(); }
5194 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5196 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5199 private uint NumToAlign(uint val, uint alignVal)
5201 if ((val % alignVal) == 0) return 0;
5202 return alignVal - (val % alignVal);
5205 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5207 uint ix = 0;
5208 if (elem != null) {
5209 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5210 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5211 //} else {
5212 // Console.WriteLine("elem for coded index is null");
5214 if (lgeCIx[(uint)code])
5215 output.Write(ix);
5216 else
5217 output.Write((ushort)ix);
5222 /**************************************************************************/
5223 /// <summary>
5224 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5225 /// </summary>
5227 internal class MetaDataStream : BinaryWriter {
5229 private static readonly uint StreamHeaderSize = 8;
5230 private static uint maxSmlIxSize = 0xFFFF;
5232 private uint start = 0;
5233 uint size = 0, tide = 1;
5234 bool largeIx = false;
5235 uint sizeOfHeader;
5236 char[] name;
5237 Hashtable htable = new Hashtable();
5238 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5240 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5242 if (addInitByte) { Write((byte)0); size = 1; }
5243 this.name = name;
5244 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5247 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5249 if (addInitByte) { Write((byte)0); size = 1; }
5250 this.name = name;
5251 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5254 public uint Start {
5255 get { return start; }
5256 set { start = value; }
5259 internal uint headerSize()
5261 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5262 return sizeOfHeader;
5265 internal void SetSize(uint siz)
5267 size = siz;
5270 internal uint Size()
5272 return size;
5275 internal bool LargeIx()
5277 return largeIx;
5280 internal void WriteDetails()
5282 // Console.WriteLine(name + " - size = " + size);
5285 internal uint Add(string str, bool prependSize)
5287 Object val = htable[str];
5288 uint index = 0;
5289 if (val == null) {
5290 index = size;
5291 htable[str] = index;
5292 char[] arr = str.ToCharArray();
5293 if (prependSize) CompressNum((uint)arr.Length*2+1);
5294 Write(arr);
5295 Write((byte)0);
5296 size = (uint)Seek(0,SeekOrigin.Current);
5297 } else {
5298 index = (uint)val;
5300 return index;
5302 internal uint Add (byte[] str, bool prependSize)
5304 Object val = btable [str];
5305 uint index = 0;
5306 if (val == null) {
5307 index = size;
5308 btable [str] = index;
5309 if (prependSize) CompressNum ((uint) str.Length);
5310 Write (str);
5311 size = (uint) Seek (0, SeekOrigin.Current);
5312 } else {
5313 index = (uint) val;
5315 return index;
5319 internal uint Add(Guid guid, bool prependSize)
5321 byte [] b = guid.ToByteArray ();
5322 if (prependSize) CompressNum ((uint) b.Length);
5323 Write(guid.ToByteArray());
5324 size =(uint)Seek(0,SeekOrigin.Current);
5325 return tide++;
5328 internal uint Add(byte[] blob)
5330 uint ix = size;
5331 CompressNum((uint)blob.Length);
5332 Write(blob);
5333 size = (uint)Seek(0,SeekOrigin.Current);
5334 return ix;
5337 internal uint Add(byte val, bool prependSize)
5339 uint ix = size;
5340 if (prependSize) CompressNum (1);
5341 Write(val);
5342 size = (uint)Seek(0,SeekOrigin.Current);
5343 return ix;
5346 internal uint Add(sbyte val, bool prependSize)
5348 uint ix = size;
5349 if (prependSize) CompressNum (1);
5350 Write(val);
5351 size = (uint)Seek(0,SeekOrigin.Current);
5352 return ix;
5355 internal uint Add(ushort val, bool prependSize)
5357 uint ix = size;
5358 if (prependSize) CompressNum (2);
5359 Write(val);
5360 size = (uint)Seek(0,SeekOrigin.Current);
5361 return ix;
5364 internal uint Add(short val, bool prependSize)
5366 uint ix = size;
5367 if (prependSize) CompressNum (2);
5368 Write(val);
5369 size = (uint)Seek(0,SeekOrigin.Current);
5370 return ix;
5373 internal uint Add(uint val, bool prependSize)
5375 uint ix = size;
5376 if (prependSize) CompressNum (4);
5377 Write(val);
5378 size = (uint)Seek(0,SeekOrigin.Current);
5379 return ix;
5382 internal uint Add(int val, bool prependSize)
5384 uint ix = size;
5385 if (prependSize) CompressNum (4);
5386 Write (val);
5387 size = (uint)Seek(0,SeekOrigin.Current);
5388 return ix;
5391 internal uint Add(ulong val, bool prependSize)
5393 uint ix = size;
5394 if (prependSize) CompressNum (8);
5395 Write(val);
5396 size = (uint)Seek(0,SeekOrigin.Current);
5397 return ix;
5400 internal uint Add(long val, bool prependSize)
5402 uint ix = size;
5403 if (prependSize) CompressNum (8);
5404 Write(val);
5405 size = (uint)Seek(0,SeekOrigin.Current);
5406 return ix;
5409 internal uint Add(float val, bool prependSize)
5411 uint ix = size;
5412 if (prependSize) CompressNum (4);
5413 Write(val);
5414 size = (uint)Seek(0,SeekOrigin.Current);
5415 return ix;
5418 internal uint Add(double val, bool prependSize)
5420 uint ix = size;
5421 if (prependSize) CompressNum (8);
5422 Write(val);
5423 size = (uint)Seek(0,SeekOrigin.Current);
5424 return ix;
5427 private void CompressNum(uint val)
5429 if (val < 0x7F) {
5430 Write((byte)val);
5431 } else if (val < 0x3FFF) {
5432 byte b1 = (byte)((val >> 8) | 0x80);
5433 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5434 Write(b1);
5435 Write(b2);
5436 } else {
5437 byte b1 = (byte)((val >> 24) | 0xC0);
5438 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5439 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5440 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5441 Write(b1);
5442 Write(b2);
5443 Write(b3);
5444 Write(b4);
5448 private void QuadAlign()
5450 if ((size % 4) != 0) {
5451 uint pad = 4 - (size % 4);
5452 size += pad;
5453 for (int i=0; i < pad; i++) {
5454 Write((byte)0);
5459 internal void EndStream()
5461 QuadAlign();
5462 if (size > maxSmlIxSize) {
5463 largeIx = true;
5467 internal void WriteHeader(BinaryWriter output)
5469 output.Write(start);
5470 output.Write(size);
5471 output.Write(name);
5474 internal virtual void Write(BinaryWriter output)
5476 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5477 MemoryStream str = (MemoryStream)BaseStream;
5478 output.Write(str.ToArray());
5483 /**************************************************************************/
5484 class ByteArrayComparer : IComparer {
5486 public int Compare (object x, object y)
5488 byte [] a = (byte []) x;
5489 byte [] b = (byte []) y;
5490 int len = a.Length;
5492 if (b.Length != len)
5493 return 1;
5495 for (int i = 0; i < len; ++i)
5496 if (a [i] != b [i])
5497 return 1;
5498 return 0;
5502 class ByteArrayHashCodeProvider : IHashCodeProvider {
5504 public int GetHashCode (Object key)
5506 byte [] arr = (byte []) key;
5507 int len = arr.Length;
5508 int h = 0;
5510 for (int i = 0; i < len; ++i)
5511 h = (h << 5) - h + arr [i];
5513 return h;