In some collection case, xsi:type is explicitly written. Try to copy that behavior.
[mono.git] / mcs / class / PEAPI / Metadata.cs
index a402d332227355fa29085f2de4f6cc7e4f3331e5..e67f2966d2b307cdb5e6b33f20a174cc3128705d 100644 (file)
@@ -2,6 +2,7 @@ using System;
 using System.IO;
 using System.Collections;
 using System.Text;
+using System.Reflection;
 
 namespace PEAPI {
 
@@ -28,7 +29,7 @@ namespace PEAPI {
        /// <summary>
        /// Attributes for this assembly
        /// </summary>
-       public enum AssemAttr { EnableJITCompileTracking = 0x8000, 
+       public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000, 
                DisableJITCompileOptimizer = 0x4000}
 
        /// <summary>
@@ -46,13 +47,15 @@ namespace PEAPI {
        /// <summary>
        /// Attibutes for a class
        /// </summary>
+       [Flags]
        public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate, 
                NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem, 
                SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20, 
                Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100, 
                PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800, 
                Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
-               AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000 }
+               AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
+               VisibilityMask = 0x07 }
 
        /// <summary>
        /// Attributes for a field
@@ -69,7 +72,7 @@ namespace PEAPI {
                Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16, 
                Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040, 
                PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080, 
-               NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
+               NewSlot = 0x0100, Strict = 0x200, Abstract = 0x0400, SpecialName = 0x0800,
                RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800, 
                HasSecurity = 0x4000, RequireSecObject = 0x8000}
 
@@ -77,8 +80,11 @@ namespace PEAPI {
        /// Attributes for .pinvokeimpl method declarations
        /// </summary>
        public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
+               bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
                lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
-               stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
+               stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
+               charmaperror_on = 0x1000, charmaperror_off = 0x2000
+       }
 
        /// <summary>
        /// Implementation attributes for a method
@@ -116,7 +122,7 @@ namespace PEAPI {
                add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally, 
                stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, 
                localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_, 
-               cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
+               cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
 
        /// <summary>
        /// CIL instructions requiring an integer parameter
@@ -143,8 +149,8 @@ namespace PEAPI {
        public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst, 
                unbox = 0x79, stobj = 0x81, box = 0x8C, newarr, 
                ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6, 
-               ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
-               ldelem = 0xA3, stelem = 0xA4, unbox_any }
+               ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16, 
+               sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
 
        /// <summary>
        /// CIL branch instructions
@@ -188,6 +194,19 @@ namespace PEAPI {
                Var = 0x13, MVar = 0x1E 
        }
 
+       [Flags]
+       public enum GenericParamAttributes : ushort {
+               VarianceMask  = 0x0003,
+               NonVariant    = 0x0000,
+               Covariant     = 0x0001,
+               Contravariant = 0x0002,
+
+               SpecialConstraintMask = 0x001c,
+               ReferenceTypeConstraint = 0x0004,
+               NotNullableValueTypeConstraint = 0x0008,
+               DefaultConstructorConstrait = 0x0010
+       }
+
        /* Taken from Mono.Cecil */
        public enum SecurityAction : short {
                Request = 1,
@@ -223,6 +242,8 @@ namespace PEAPI {
                protected bool done = false;
                protected MDTable tabIx;
                protected bool sortTable = false;
+               //Temporary hack.. 
+               private bool has_custom_attrs = false;
 
                internal MetaDataElement() { }
 
@@ -231,10 +252,15 @@ namespace PEAPI {
                                return row;
                        }
                        set {
-                               if (row == 0) row = value;
+                               row = value;
                        }
                }
 
+               public bool HasCustomAttr {
+                       get { return has_custom_attrs; }
+                       set { has_custom_attrs = value; }
+               }
+
                internal virtual uint GetCodedIx(CIx code) { return 0; }
 
                /// <summary>
@@ -445,9 +471,14 @@ namespace PEAPI {
 
                internal sealed override void BuildTables(MetaData md) 
                {
+                       md.AddToTable(MDTable.CustomAttribute, this);
+                       if (byteVal == null) {
+                               valIx = 0;
+                               return;
+                       }
+
                        BinaryWriter bw = new BinaryWriter(new MemoryStream());
                        bw.Write(byteVal);
-                       md.AddToTable(MDTable.CustomAttribute, this);
                        MemoryStream str = (MemoryStream)bw.BaseStream;
                        valIx = md.AddToBlobHeap(str.ToArray());
                }
@@ -471,19 +502,17 @@ namespace PEAPI {
        /// Descriptor for security permissions for a class or a method
        /// </summary>
 
-       public class DeclSecurity : MetaDataElement {
+       public abstract class BaseDeclSecurity : MetaDataElement {
 
                ushort action;
                MetaDataElement parent;
                uint permissionIx;
-               byte [] byteVal;
 
-               internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)        
+               internal BaseDeclSecurity(MetaDataElement paren, ushort act)
                {
                        parent = paren;
                        action = act;
                        tabIx = MDTable.DeclSecurity;
-                       byteVal = val;
                }
 
                internal override uint SortKey() 
@@ -500,15 +529,18 @@ namespace PEAPI {
                internal sealed override void BuildTables(MetaData md) 
                {
                        if (done) return;
+
                        BinaryWriter bw = new BinaryWriter (new MemoryStream ());
-                       bw.Write (byteVal);
                        md.AddToTable (MDTable.DeclSecurity, this);
                        MemoryStream str = (MemoryStream)bw.BaseStream;
+                       WriteSig (bw);
                        permissionIx = md.AddToBlobHeap(str.ToArray());
 
                        done = true;
                }
 
+               internal abstract void WriteSig (BinaryWriter bw);
+
                internal sealed override void Write(FileImage output) 
                {
                        output.Write(action);
@@ -518,6 +550,154 @@ namespace PEAPI {
 
        }
 
+       public class DeclSecurity : BaseDeclSecurity {
+
+               byte [] byteVal;
+
+               internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)        
+                       : base (paren, act)
+               {
+                       byteVal = val;
+               }
+
+               internal override void WriteSig (BinaryWriter bw)
+               {
+                       bw.Write (byteVal);
+               }
+
+       }
+
+       public class DeclSecurity_20 : BaseDeclSecurity {
+
+               PermissionSet ps;
+
+               internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
+                       : base (paren, act)
+               {
+                        this.ps = ps;
+               }
+
+               internal override void WriteSig (BinaryWriter bw)
+               {
+                       ps.Write (bw);
+               }
+       }
+
+       public class PermissionMember {
+
+               MemberTypes member_type;
+               PEAPI.Type type;
+               string name;
+               object value;
+
+               public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
+               {
+                       this.member_type = member_type;
+                       this.type = type;
+                       this.name = name;
+                       this.value = value;
+               }
+
+               public void Write (BinaryWriter bw)
+               {
+                       byte [] b;
+
+                       if (member_type == MemberTypes.Field)
+                               bw.Write ((byte) 0x53);
+                       else
+                               //Property
+                               bw.Write ((byte) 0x54);
+
+                       if (type is PrimitiveType) {
+                               bw.Write (type.GetTypeIndex ());
+                       } else {
+                               //must be enum
+                               bw.Write ((byte) 0x55); //ENUM
+
+                               b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
+                               MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
+                               bw.Write (b);
+                       }
+                       
+                       b = Encoding.UTF8.GetBytes (name);
+                       MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
+                       bw.Write (b);
+
+                       ((Constant) value).Write (bw);
+               }
+
+       }
+
+       public class Permission
+       {
+               PEAPI.Type type;
+
+               //PermissionMembers
+               ArrayList members;
+               string name;
+
+               public Permission (PEAPI.Type type, string name)
+               {
+                       this.type = type;
+                       this.name = name;
+               }
+
+               public void AddMember (PEAPI.PermissionMember member)
+               {
+                       if (members == null)
+                               members = new ArrayList ();
+
+                       members.Add (member);
+               }
+
+               public void Write (BinaryWriter bw)
+               {
+                       byte [] b = Encoding.UTF8.GetBytes (name);
+                       MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
+                       bw.Write (b);
+
+                       BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
+                       MemoryStream str = (MemoryStream) perm_writer.BaseStream;
+
+                       MetaData.CompressNum ((uint) members.Count, str);//number of params
+                       foreach (PermissionMember member in members)
+                               member.Write (perm_writer);
+
+                       bw.Write ((byte) str.Length); //(optional) parameters length
+                       bw.Write (str.ToArray ());
+               }
+       }
+
+       public class PermissionSet 
+       {
+               PEAPI.SecurityAction sec_action;
+               ArrayList permissions;
+               PEAPI.PermissionSet ps;
+
+               public PermissionSet (PEAPI.SecurityAction sec_action)
+               {
+                       this.sec_action = sec_action;
+               }
+
+               public void AddPermission (PEAPI.Permission perm)
+               {
+                       if (permissions == null)
+                               permissions = new ArrayList ();
+
+                       permissions.Add (perm);
+               }
+
+               public void Write (BinaryWriter bw)
+               {
+                       bw.Write ((byte) 0x2e);
+                       MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
+
+                       foreach (Permission perm in permissions)
+                               perm.Write (bw);
+               }
+
+       }
+
        /**************************************************************************/  
        /// <summary>
        /// Descriptor for layout information for a field
@@ -743,27 +923,29 @@ namespace PEAPI {
 
                MetaDataElement owner;
                MetaData metadata;
-               string name;
+               public string name;
                uint nameIx;
                short index;
+               GenericParamAttributes attr;
 
                internal GenericParameter (ClassDef owner, MetaData metadata,
-                               short index, string name) : this (owner, metadata, index, name, true)
+                               short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
                {
                }
 
                internal GenericParameter (MethodDef owner, MetaData metadata,
-                               short index, string name) : this (owner, metadata, index, name, true)
+                               short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
                {
                }
 
                private GenericParameter (MetaDataElement owner, MetaData metadata,
-                               short index, string name, bool nadda) {
+                               short index, string name, GenericParamAttributes attr, bool nadda) {
                        this.owner = owner;
                        this.metadata = metadata;
                        this.index = index;
                        tabIx = MDTable.GenericParam;
                        this.name = name;
+                       this.attr = attr;
                }
 
                internal override uint SortKey() 
@@ -800,11 +982,18 @@ namespace PEAPI {
                internal sealed override void Write(FileImage output) 
                {
                        output.Write ((short) index);
-                       output.Write ((short) 0);
+                       output.Write ((short) attr);
                        output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
                        output.StringsIndex (nameIx);
                }
 
+               internal sealed override uint GetCodedIx(CIx code) 
+               {
+                       switch (code) {
+                               case (CIx.HasCustomAttr) : return 19; 
+                       }
+                       return 0;
+               }
 
        }
 
@@ -820,6 +1009,11 @@ namespace PEAPI {
                        tabIx = MDTable.GenericParamConstraint;
                }
 
+               internal override uint SortKey() 
+               {
+                       return param.Row;
+               }
+
                internal sealed override uint Size(MetaData md) 
                {
                        return (uint) (md.TableIndexSize(MDTable.GenericParam) +
@@ -834,19 +1028,29 @@ namespace PEAPI {
 
        }
 
-       internal class MethodSpec : MetaDataElement {
+       internal class MethodSpec : Method {
 
                Method meth;
                GenericMethodSig g_sig;
                uint sidx;
 
-               internal MethodSpec (Method meth, GenericMethodSig g_sig) 
+               internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
                {
                        this.meth = meth;
                        this.g_sig = g_sig;
                        tabIx = MDTable.MethodSpec;
                }
 
+               internal override uint GetSigIx (MetaData md)
+               {
+                       throw new Exception ("Should not be used.");
+               }
+
+               public override void AddCallConv (CallConv cconv)
+               {
+                       throw new Exception ("Should not be used.");
+               }
+               
                internal sealed override void BuildTables (MetaData md) 
                {
                        if (done) return;
@@ -865,6 +1069,11 @@ namespace PEAPI {
                        output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
                        output.BlobIndex (sidx);
                }
+
+               internal sealed override void TypeSig (MemoryStream sig)
+               {
+                       throw new Exception ("Should not be used.");
+               }
        }
 
        /**************************************************************************/
@@ -970,11 +1179,11 @@ namespace PEAPI {
                        nameIx = md.AddToStringsHeap(mrName);
                        if (resourceBytes != null) {
                                if (rRef != null)
-                                       throw new Exception("ERROR:  Manifest Resource has byte value and file reference");
+                                       throw new PEFileException ("Manifest Resource has byte value and file reference");
                                fileOffset = md.AddResource(resourceBytes);
                        } else {
                                if (rRef == null)
-                                       throw new Exception("ERROR:  Manifest Resource has no implementation or value");
+                                       throw new PEFileException ("Manifest Resource has no implementation or value");
                                rRef.BuildTables (md);
                        }
 
@@ -1131,6 +1340,10 @@ namespace PEAPI {
                        tabIx = MDTable.Param;
                }
 
+               public bool HasMarshalInfo {
+                       get { return marshalInfo != null; }
+               }
+
                /// <summary>
                /// Add a default value to this parameter
                /// </summary>
@@ -1330,6 +1543,12 @@ namespace PEAPI {
                        nameIx = nIx;
                }
 
+               internal Class (byte typeIndex) : base (typeIndex)
+               {
+                       nameSpace = "Should not be used";
+                       name = "Should not be used";
+               }
+
                internal virtual uint TypeDefOrRefToken() { return 0; }
 
                internal virtual void MakeValueClass(ValueClass vClass) 
@@ -1390,9 +1609,7 @@ namespace PEAPI {
                internal void SetSuper(Class sClass) 
                {
                        superType = sClass;
-                       if (sClass is ClassRef)
-                               typeIndex = superType.GetTypeIndex();
-                       else
+                       if (! (sClass is GenericTypeInst))
                                typeIndexChecked = false;
                }
 
@@ -1434,7 +1651,15 @@ namespace PEAPI {
                /// </summary>
                public GenericParameter AddGenericParameter (short index, string name) 
                {
-                       GenericParameter gp = new GenericParameter (this, metaData, index, name);
+                       return AddGenericParameter (index, name, 0);
+               }
+
+               /// <summary>
+               ///  Add a named generic type parameter with attributes
+               /// </summary>
+               public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
+               {
+                       GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
                        metaData.AddToTable (MDTable.GenericParam, gp);
                        return gp;
                }
@@ -1479,9 +1704,14 @@ namespace PEAPI {
                /// <param name="pars">parameters</param>
                /// <returns>a descriptor for this new method</returns>
                public MethodDef AddMethod(string name, Type retType, Param[] pars) 
+               {
+                       return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
+               }
+
+               public MethodDef AddMethod (string name, Param ret_param, Param [] pars) 
                {
                        // Console.WriteLine("Adding method " + name + " to class " + this.name);
-                       MethodDef meth = new MethodDef(metaData,name,retType, pars);
+                       MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
                        methods.Add(meth);
                        return meth;
                }
@@ -1496,9 +1726,9 @@ namespace PEAPI {
                /// <param name="pars">parameters</param>
                /// <returns>a descriptor for this new method</returns>
                public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, 
-                               Type retType, Param[] pars) {
+                               Param ret_param, Param [] pars) {
                        // Console.WriteLine("Adding method " + name + " to class " + this.name);
-                       MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
+                       MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
                        methods.Add(meth);
                        return meth;
                }
@@ -1629,7 +1859,7 @@ namespace PEAPI {
                internal void CheckTypeIndex() 
                {
                        if (typeIndexChecked) return;
-                       if (!(superType is ClassRef)
+                       if (superType is ClassDef
                                ((ClassDef)superType).CheckTypeIndex();
                        typeIndex = superType.GetTypeIndex();
                        typeIndexChecked = true;
@@ -1747,7 +1977,20 @@ namespace PEAPI {
                /// <returns>a descriptor for this method</returns>
                public MethodRef AddMethod(string name, Type retType, Type[] pars) 
                {
-                       MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
+                       return AddMethod (name, retType, pars, 0);
+               }
+               
+               /// <summary>
+               /// Add a method to this class
+               /// </summary>
+               /// <param name="name">method name</param>
+               /// <param name="retType">return type</param>
+               /// <param name="pars">parameter types</param>
+               /// <param name="gen_param_count">num of generic parameters</param>
+               /// <returns>a descriptor for this method</returns>
+               public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count) 
+               {
+                       MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
                        metaData.AddToTable(MDTable.MemberRef,meth);
                        return meth;
                }
@@ -1762,7 +2005,7 @@ namespace PEAPI {
                public MethodRef AddVarArgMethod(string name, Type retType, 
                                Type[] pars, Type[] optPars) 
                {
-                       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
+                       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
                        metaData.AddToTable(MDTable.MemberRef,meth);
                        return meth;
                }
@@ -1917,15 +2160,16 @@ namespace PEAPI {
 
        }
 
-       public class GenParam : Type {
+       public class GenParam : Class {
 
                private int index;
-               private string name;
+               private string param_name;
+               private uint sigIx = 0;
 
                public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype) 
                {
                        this.index = index;
-                       this.name = name;
+                       this.param_name = name;
                        tabIx = MDTable.TypeSpec;
                }
 
@@ -1935,26 +2179,60 @@ namespace PEAPI {
                }
 
                public string Name {
-                       get { return name; }
-                       set { name = value; }
+                       get { return param_name; }
+                       set { param_name = value; }
                }
 
                public GenParamType Type {
                        get { return (GenParamType) GetTypeIndex (); }
                }
+               
+               internal sealed override void BuildTables (MetaData md)
+               {
+                       if (done)
+                               return;
+                       MemoryStream str = new MemoryStream ();
+                       TypeSig (str);
+                       sigIx = md.AddToBlobHeap (str.ToArray ());
+
+                       done = true;
+               }
+
                internal sealed override void TypeSig(MemoryStream str) 
                {
                        if (index < 0)
-                               throw new Exception (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), name));
+                               throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
                        str.WriteByte(typeIndex);
                        MetaData.CompressNum ((uint) index, str);
                }
+               
+               internal override uint Size(MetaData md) 
+               {
+                       return md.BlobIndexSize();
+               }
+
+               internal sealed override void Write (FileImage output)
+               {
+                       output.BlobIndex (sigIx);       
+               }
+
+               internal sealed override uint GetCodedIx(CIx code) 
+               {
+                       switch (code) {
+                               case (CIx.TypeDefOrRef) : return 2; 
+                               case (CIx.HasCustomAttr) : return 13; 
+                               case (CIx.MemberRefParent) : return 4; 
+                       }
+                       return 0;
+               }
        }
 
-       public class GenericTypeInst : Type {
+       public class GenericTypeInst : Class {
 
                private Type gen_type;
                private Type[] gen_param;
+               bool inTable = false;
+               uint sigIx = 0;
 
                public GenericTypeInst (Type gen_type, Type[] gen_param) 
                        : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
@@ -1964,6 +2242,16 @@ namespace PEAPI {
                        tabIx = MDTable.TypeSpec;
                }
 
+               internal override MetaDataElement GetTypeSpec (MetaData md)
+               {
+                       if (!inTable) {
+                               md.AddToTable (MDTable.TypeSpec, this);
+                               inTable = true;
+                       }
+
+                       return this;
+               }
+
                internal sealed override void TypeSig(MemoryStream str) 
                {
                        str.WriteByte(typeIndex);
@@ -1972,15 +2260,49 @@ namespace PEAPI {
                        foreach (Type param in gen_param)
                                param.TypeSig (str);
                }
+
+               internal sealed override void BuildTables (MetaData md)
+               {
+                       if (done)
+                               return;
+                       MemoryStream str = new MemoryStream ();
+                       TypeSig (str);
+                       sigIx = md.AddToBlobHeap (str.ToArray ());
+
+                       done = true;
+               }
+
+               internal sealed override uint Size (MetaData md)
+               {
+                       return md.BlobIndexSize ();
+               }
+
+               internal sealed override void Write (FileImage output)
+               {
+                       output.BlobIndex (sigIx);       
+               }
+
+               internal sealed override uint GetCodedIx (CIx code)
+               {
+                       switch (code) {
+                               case (CIx.TypeDefOrRef): return 2;
+                               case (CIx.MemberRefParent): return 4;
+                               case (CIx.HasCustomAttr): return 13;
+                       }
+                       return 0;
+               }
        }
 
        public class GenericMethodSig {
 
                private Type[] gen_param;
+               private bool done;
+               private uint sigIx = 0;
 
                public GenericMethodSig (Type[] gen_param)
                {
                        this.gen_param = gen_param;
+                       done = false;
                }
 
                internal void TypeSig (MemoryStream str)
@@ -1993,9 +2315,14 @@ namespace PEAPI {
 
                internal uint GetSigIx (MetaData md)
                {
+                       if (done)
+                               return sigIx;
+
                        MemoryStream sig = new MemoryStream();
                        TypeSig (sig);
-                       return md.AddToBlobHeap (sig.ToArray());
+                       sigIx = md.AddToBlobHeap (sig.ToArray());
+                       done = true;
+                       return sigIx;
                }
        }
 
@@ -2140,16 +2467,13 @@ namespace PEAPI {
                /// <param name="elementType">the type of the elements</param>
                /// <param name="dimensions">the number of dimensions</param>
                /// <param name="loBounds">lower bounds of dimensions</param>
-               /// <param name="upBounds">upper bounds of dimensions</param>
+               /// <param name="sizes">sizes for the dimensions</param>
                public BoundArray(Type elementType, uint dimensions, int[] loBounds, 
-                               int[] upBounds) : base (elementType,0x14) 
+                               int[] sizes) : base (elementType,0x14) 
                {
                        numDims = dimensions;
                        lowerBounds = loBounds;
-                       sizes = new int[loBounds.Length];
-                       for (int i=0; i < loBounds.Length; i++) {
-                               sizes[i] = upBounds[i] - loBounds[i] + 1;
-                       }
+                       this.sizes = sizes;
                }
 
                /// <summary>
@@ -2193,11 +2517,54 @@ namespace PEAPI {
                        if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
                                MetaData.CompressNum((uint)lowerBounds.Length,str);
                                for (int i=0; i < lowerBounds.Length; i++) {
-                                       MetaData.CompressNum((uint)lowerBounds[i],str);
+                                       CompressSignedNum (lowerBounds[i],str);
                                }
                        } else str.WriteByte(0);
                }
+               private void CompressSignedNum (int val, MemoryStream str)
+               {
+                       uint uval = (uint) val;
+                       byte sign = 0;
+                       if (val < 0) {
+                               val = -val;
+                               sign = 1;
+                       }
+
+                       /* Map the signed number to an unsigned number in two ways.
+
+                            fval: left-rotated 2's complement representation
+                            sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
+                                  the mapping is: x -> 2*|x| - signbit(x)
+                       */
+                       uint fval = (uval << 1) | sign;
+                       int sval = (val  << 1) - sign;
+
+                       /* An overly clever transformation: 
+
+                          a. sval is used to determine the number of bytes in the compressed representation.
+                          b. fval is truncated to the appropriate number of bits and output using the 
+                             normal unsigned-int compressor.
 
+                          However, or certain values, the truncated fval doesn't carry enough information to round trip.
+
+                               (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
+
+                          So, we use full 4 bytes to encode such values.
+
+                          LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
+                                    e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
+                       */
+                       if (sval <= 0x7F)
+                               MetaData.CompressNum (fval & 0x7F, str);
+                       else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
+                               MetaData.CompressNum (fval & 0x3FFF, str);
+                       else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
+                               MetaData.CompressNum (fval & 0x1FFFFFFF, str);
+                       else
+                               /* FIXME: number cannot be represented.  Report a warning.  */
+                               // throw new Exception ("cannot represent signed value" + -val);
+                               MetaData.CompressNum (fval, str);
+               }
        }
 
        #endregion
@@ -2315,7 +2682,7 @@ namespace PEAPI {
        /// <summary>
        /// Descriptor for THIS module
        /// </summary>
-       public class Module : ResolutionScope {
+       public class Module : ResolutionScope, IExternRef {
 
                Guid mvid;
                uint mvidIx = 0;
@@ -2331,6 +2698,21 @@ namespace PEAPI {
                        get { return mvid; }
                }
 
+               public ClassRef AddClass(string nsName, string name) 
+               {
+                       ClassRef aClass = new ClassRef (nsName, name, metaData);
+                       metaData.AddToTable (MDTable.TypeRef, aClass);
+                       aClass.SetParent (this);
+                       return aClass;
+               }
+
+               public ClassRef AddValueClass(string nsName, string name) 
+               {
+                       ClassRef aClass = AddClass (nsName, name);
+                       aClass.MakeValueClass (ValueClass.ValueType);
+                       return aClass;
+               }
+
                internal sealed override uint Size(MetaData md) 
                {
                        return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
@@ -2441,7 +2823,7 @@ namespace PEAPI {
                /// <returns>a descriptor for this method in anther module</returns>
                public MethodRef AddMethod(string name, Type retType, Type[] pars) 
                {
-                       MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
+                       MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
                        metaData.AddToTable(MDTable.MemberRef,meth);
                        return meth;
                }
@@ -2456,7 +2838,7 @@ namespace PEAPI {
                /// <returns>a descriptor for this method</returns>
                public MethodRef AddVarArgMethod(string name, Type retType, 
                                Type[] pars, Type[] optPars) {
-                       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
+                       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
                        metaData.AddToTable(MDTable.MemberRef,meth);
                        return meth;
                }
@@ -2734,27 +3116,27 @@ namespace PEAPI {
        }
 
        public class UIntConst : Constant {
-               long val;
+               ulong val;
 
-               public UIntConst(sbyte val) 
+               public UIntConst(byte val) 
                {
                        this.val = val;
                        size = 1;
                        type = PrimitiveType.UInt8;
                }
-               public UIntConst(short val) 
+               public UIntConst(ushort val) 
                {
                        this.val = val;
                        size = 2;
                        type = PrimitiveType.UInt16;
                }
-               public UIntConst(int val) 
+               public UIntConst(uint val) 
                {
                        this.val = val;
                        size = 4;
                        type = PrimitiveType.UInt32;
                }
-               public UIntConst(long val) 
+               public UIntConst(ulong val) 
                {
                        this.val = val;
                        size = 8;
@@ -2765,9 +3147,9 @@ namespace PEAPI {
                {
                        if (!addedToBlobHeap) {
                                switch (size) {
-                                       case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
-                                       case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
-                                       case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
+                                       case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
+                                       case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
+                                       case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
                                        default : blobIndex = md.AddToBlobHeap(val); break;
                                }
                                addedToBlobHeap = true;
@@ -2778,9 +3160,9 @@ namespace PEAPI {
                internal sealed override void Write(BinaryWriter bw) 
                {
                        switch (size) {
-                               case (1) : bw.Write((sbyte)val); break;
-                               case (2) : bw.Write((short)val); break;
-                               case (4) : bw.Write((int)val); break;
+                               case (1) : bw.Write((byte)val); break;
+                               case (2) : bw.Write((ushort)val); break;
+                               case (4) : bw.Write((uint)val); break;
                                default : bw.Write(val); break;
                        }
                }
@@ -3105,6 +3487,7 @@ namespace PEAPI {
        public class Property : Feature {
 
                private static readonly byte PropertyTag = 0x8;
+               private bool instance;
                MethodDef getterMeth;
                ConstantElem constVal;
                uint typeBlobIx = 0;
@@ -3157,12 +3540,20 @@ namespace PEAPI {
                        this.constVal = new ConstantElem(this,constVal);
                }
 
+               public void SetInstance (bool isInstance)
+               {
+                       this.instance = isInstance;
+               }
+
                internal sealed override void BuildTables(MetaData md) 
                {
                        if (done) return;
                        nameIx = md.AddToStringsHeap(name);
                        MemoryStream sig = new MemoryStream();
-                       sig.WriteByte(PropertyTag);
+                       byte tag = PropertyTag;
+                       if (instance)
+                               tag |= 0x20;
+                       sig.WriteByte(tag);
                        MetaData.CompressNum(numPars,sig);
                        returnType.TypeSig(sig);
                        for (int i=0; i < numPars; i++) {
@@ -3409,39 +3800,12 @@ namespace PEAPI {
 
        public abstract class Method : Member {
 
-               protected CallConv callConv = CallConv.Default;
-               protected Type retType;
-               protected int gen_param_count;
-
-               internal Method(string methName, Type rType) : base(methName)
-               {
-                       retType = rType;
-                       gen_param_count = 0;
-               }
-
-               /// <summary>
-               /// Add calling conventions to this method descriptor
-               /// </summary>
-               /// <param name="cconv"></param>
-               public void AddCallConv(CallConv cconv) 
-               {
-                       callConv |= cconv;
-               }
+               internal Method (string methName) : base (methName)
+               {}
 
+               public abstract void AddCallConv(CallConv cconv);
                internal abstract void TypeSig(MemoryStream sig);
-
-               internal uint GetSigIx(MetaData md) 
-               {
-                       MemoryStream sig = new MemoryStream();
-                       TypeSig(sig);
-                       return md.AddToBlobHeap(sig.ToArray());
-               }
-
-               internal Type GetRetType() 
-               {
-                       return retType;
-               }
-
+               internal abstract uint GetSigIx(MetaData md);
        }
 
        /**************************************************************************/  
@@ -3456,6 +3820,8 @@ namespace PEAPI {
                //private static readonly uint UnmanagedExport = 0x0008;
                // private static readonly byte LocalSigByte = 0x7;
                uint parIx = 0, textOffset = 0;
+               private CallConv callConv = CallConv.Default;
+               private int gen_param_count;
 
                MetaData metaData;
                CILInstructions code;
@@ -3471,20 +3837,23 @@ namespace PEAPI {
                ImplMap pinvokeImpl;
                Param ret_param;
 
-
-               internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) 
+               internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
+                       : this (md, 0, 0, name, ret_param, pars)
                {
-                       metaData = md;
-                       parList = pars;
-                       if (parList != null) numPars = parList.Length;
-                       tabIx = MDTable.Method;
                }
 
                internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, 
-                               Type retType, Param [] pars) : this (md, name, retType, pars)
+                               Param ret_param, Param [] pars) 
+                       : base (name)
                {
                        methFlags = (ushort)mAttrSet;
                        implFlags = (ushort)iAttrSet;
+                       this.ret_param = ret_param;
+                       metaData = md;
+                       parList = pars;
+                       if (parList != null) 
+                               numPars = parList.Length;
+                       tabIx = MDTable.Method;
                }
 
                internal Param[] GetPars() 
@@ -3492,6 +3861,18 @@ namespace PEAPI {
                        return parList;
                }
 
+               internal override uint GetSigIx(MetaData md)
+               {
+                       MemoryStream sig = new MemoryStream();
+                       TypeSig(sig);
+                       return md.AddToBlobHeap(sig.ToArray());
+               }
+
+               public override void AddCallConv(CallConv cconv)
+               {
+                       callConv |= cconv;
+               }
+               
                /// <summary>
                /// Add some attributes to this method descriptor
                /// </summary>
@@ -3521,7 +3902,15 @@ namespace PEAPI {
                /// </summary>
                public GenericParameter AddGenericParameter (short index, string name) 
                {
-                       GenericParameter gp = new GenericParameter (this, metaData, index, name);
+                       return AddGenericParameter (index, name, 0);
+               }
+
+               /// <summary>
+               ///  Add a named generic type parameter with attributes
+               /// </summary>
+               public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr) 
+               {
+                       GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
                        metaData.AddToTable (MDTable.GenericParam, gp);
                        gen_param_count ++;
                        return gp;
@@ -3550,7 +3939,6 @@ namespace PEAPI {
                /* Add Marshal info for return type */
                public void AddRetTypeMarshallInfo (NativeType marshallType) 
                {
-                       ret_param = new Param (ParamAttr.HasFieldMarshal, "", retType);
                        ret_param.AddMarshallInfo (marshallType);
                }
 
@@ -3585,7 +3973,7 @@ namespace PEAPI {
                        for (int i=0; i < numPars; i++) {
                                pars[i] = parList[i].GetParType();
                        }
-                       varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
+                       varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
 
                        if (varArgSigList == null)
                                varArgSigList = new ArrayList ();
@@ -3596,12 +3984,12 @@ namespace PEAPI {
                internal sealed override void TypeSig(MemoryStream sig) 
                {
                        sig.WriteByte((byte)callConv);
-                       MetaData.CompressNum((uint)numPars,sig);
                        if ((callConv & CallConv.Generic) == CallConv.Generic)
                                MetaData.CompressNum ((uint) gen_param_count, sig);
-                       if (ret_param != null)
-                               ret_param.seqNo = 0;
-                       retType.TypeSig(sig);
+                       MetaData.CompressNum((uint)numPars,sig);
+
+                       ret_param.seqNo = 0;
+                       ret_param.TypeSig (sig);
                        for (ushort i=0; i < numPars; i++) {
                                parList[i].seqNo = (ushort)(i+1);
                                parList[i].TypeSig(sig);
@@ -3630,7 +4018,7 @@ namespace PEAPI {
                        nameIx = md.AddToStringsHeap(name);
                        sigIx = GetSigIx(md);
                        parIx = md.TableIndex(MDTable.Param);
-                       if (ret_param != null) {
+                       if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
                                md.AddToTable(MDTable.Param, ret_param);
                                ret_param.BuildTables(md);
                        }
@@ -3697,25 +4085,37 @@ namespace PEAPI {
                Type[] parList, optParList;
                MetaDataElement parent;
                uint numPars = 0, numOptPars = 0;
+               CallConv callConv = CallConv.Default;
+               Type retType;
+               int gen_param_count;
 
                internal MethodRef(MetaDataElement paren, string name, Type retType,
-                               Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) 
+                               Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
                {
                        parent = paren;
                        parList = pars;
+                       this.retType = retType;
                        if (parList != null) numPars = (uint)parList.Length;
                        if (varArgMeth) {
                                optParList = optPars;
                                if (optParList != null) numOptPars = (uint)optParList.Length;
                                callConv = CallConv.Vararg;
                        }
+                       this.gen_param_count = gen_param_count;
                }
 
-               internal int GenParamCount {
-                       get { return gen_param_count; }
-                       set { gen_param_count = value; }
+               internal override uint GetSigIx(MetaData md)
+               {
+                       MemoryStream sig = new MemoryStream();
+                       TypeSig(sig);
+                       return md.AddToBlobHeap(sig.ToArray());
                }
 
+               public override void AddCallConv(CallConv cconv)
+               {
+                       callConv |= cconv;
+               }
+               
                internal sealed override void TypeSig(MemoryStream sig) 
                {
                        sig.WriteByte((byte)callConv);
@@ -3802,6 +4202,8 @@ namespace PEAPI {
                public static readonly NativeType VariantBool = new NativeType(0x25);
                public static readonly NativeType FuncPtr = new NativeType(0x26);
                public static readonly NativeType AsAny = new NativeType(0x28);
+               public static readonly NativeType LPStruct = new NativeType(0x2b);
+               public static readonly NativeType Error = new NativeType(0x2d);
 
                protected byte typeIndex;
 
@@ -4143,6 +4545,11 @@ namespace PEAPI {
                        tabIx = MDTable.AssemblyRef;
                }
 
+               public void AddAssemblyAttr (AssemAttr aa)
+               {
+                       flags |= (uint)aa;
+               }
+
                /// <summary>
                /// Add version information about this external assembly
                /// </summary>
@@ -4527,7 +4934,9 @@ namespace PEAPI {
                private static readonly uint max3BitSmlIx = 0x1FFF;
                private static readonly uint max5BitSmlIx = 0x7FF;
                // NOTE: version and stream name strings MUST always be quad padded
-#if NET_2_0 || BOOTSTRAP_NET_2_0
+#if NET_4_0
+               private static readonly string version = "v4.0.30319\0\0";
+#elif NET_2_0
                private static readonly string version = "v2.0.50727\0\0";
 #else
                private static readonly string version = "v1.1.4322\0\0\0";
@@ -4717,7 +5126,7 @@ namespace PEAPI {
                        cattr_list.Add (cattr);
                }
 
-               internal void AddDeclSecurity (DeclSecurity decl_sec)
+               internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
                {
                        if (declsec_list == null)
                                declsec_list = new ArrayList ();
@@ -4784,9 +5193,9 @@ namespace PEAPI {
 
                internal static void CompressNum(uint val, MemoryStream sig) 
                {
-                       if (val < 0x7F) {
+                       if (val <= 0x7F) {
                                sig.WriteByte((byte)val);
-                       } else if (val < 0x3FFF) {
+                       } else if (val <= 0x3FFF) {
                                byte b1 = (byte)((val >> 8) | 0x80);
                                byte b2 = (byte)(val & FileImage.iByteMask[0]);
                                sig.WriteByte(b1);
@@ -4936,7 +5345,7 @@ namespace PEAPI {
                {
                        long startTilde = output.Seek(0,SeekOrigin.Current);
                        output.Write((uint)0); // Reserved
-#if NET_2_0 || BOOTSTRAP_NET_2_0
+#if NET_2_0
                        output.Write((byte)2); // MajorVersion
                        output.Write((byte)0); // MinorVersion
 #else
@@ -4989,8 +5398,9 @@ namespace PEAPI {
                {
                        codeStart = codeStartOffset;
                        BuildTable(metaDataTables[(int)MDTable.TypeDef]);
+                       BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
                        BuildTable(metaDataTables[(int)MDTable.MemberRef]);
-#if NET_2_0 || BOOTSTRAP_NET_2_0
+#if NET_2_0
                        BuildTable(metaDataTables[(int)MDTable.GenericParam]);
                        BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
                        BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
@@ -5003,7 +5413,7 @@ namespace PEAPI {
                        }
 
                        if (declsec_list != null) {
-                               foreach (DeclSecurity decl_sec in declsec_list)
+                               foreach (BaseDeclSecurity decl_sec in declsec_list)
                                        decl_sec.BuildTables (this);
                        }
 
@@ -5035,12 +5445,11 @@ namespace PEAPI {
                        // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
 
                        SortTable(metaDataTables[(int)MDTable.Constant]);
-                       SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
                        SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
                        SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
                        SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
                        SortTable(metaDataTables[(int)MDTable.ImplMap]);
-#if NET_2_0 || BOOTSTRAP_NET_2_0
+#if NET_2_0
                        if (metaDataTables[(int)MDTable.GenericParam] != null) {
                                SortTable(metaDataTables[(int)MDTable.GenericParam]);
                                // Now add GenericParamConstraints
@@ -5051,6 +5460,7 @@ namespace PEAPI {
                        SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
 #endif 
                        SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
+                       SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
 
                }