--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection
+{
+ [Serializable]
+ public sealed class AmbiguousMatchException : Exception
+ {
+ public AmbiguousMatchException()
+ {
+ }
+
+ public AmbiguousMatchException(string message)
+ : base(message)
+ {
+ }
+
+ public AmbiguousMatchException(string message, Exception inner)
+ : base(message, inner)
+ {
+ }
+
+ private AmbiguousMatchException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+
+namespace IKVM.Reflection
+{
+ public abstract class Assembly : ICustomAttributeProvider
+ {
+ internal readonly Universe universe;
+
+ internal Assembly(Universe universe)
+ {
+ this.universe = universe;
+ }
+
+ public abstract Type[] GetTypes();
+ public abstract string FullName { get; }
+ public abstract AssemblyName GetName();
+ public abstract string ImageRuntimeVersion { get; }
+ public abstract Module ManifestModule { get; }
+ public abstract MethodInfo EntryPoint { get; }
+ public abstract string Location { get; }
+ public abstract AssemblyName[] GetReferencedAssemblies();
+ public abstract Module[] GetModules(bool getResourceModules);
+ public abstract Module[] GetLoadedModules(bool getResourceModules);
+ public abstract Module GetModule(string name);
+ public abstract string[] GetManifestResourceNames();
+ public abstract ManifestResourceInfo GetManifestResourceInfo(string resourceName);
+ public abstract System.IO.Stream GetManifestResourceStream(string resourceName);
+
+ internal abstract Type GetTypeImpl(string typeName);
+
+ public Module[] GetModules()
+ {
+ return GetModules(true);
+ }
+
+ public Module[] GetLoadedModules()
+ {
+ return GetLoadedModules(true);
+ }
+
+ public AssemblyName GetName(bool copiedName)
+ {
+ return GetName();
+ }
+
+ public bool ReflectionOnly
+ {
+ get { return true; }
+ }
+
+ public Type[] GetExportedTypes()
+ {
+ List<Type> list = new List<Type>();
+ foreach (Type type in GetTypes())
+ {
+ if (type.IsVisible)
+ {
+ list.Add(type);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public Type GetType(string typeName)
+ {
+ return GetType(typeName, false);
+ }
+
+ public Type GetType(string typeName, bool throwOnError)
+ {
+ TypeNameParser parser = TypeNameParser.Parse(typeName, throwOnError);
+ if (parser.Error)
+ {
+ return null;
+ }
+ if (parser.AssemblyName != null)
+ {
+ if (throwOnError)
+ {
+ throw new ArgumentException("Type names passed to Assembly.GetType() must not specify an assembly.");
+ }
+ else
+ {
+ return null;
+ }
+ }
+ return parser.Expand(GetTypeImpl(parser.FirstNamePart), this, throwOnError, typeName);
+ }
+
+ public virtual Module LoadModule(string moduleName, byte[] rawModule)
+ {
+ throw new NotSupportedException();
+ }
+
+ public Module LoadModule(string moduleName, byte[] rawModule, byte[] rawSymbolStore)
+ {
+ return LoadModule(moduleName, rawModule);
+ }
+
+ public bool IsDefined(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+ }
+
+ public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+ }
+
+ public static string CreateQualifiedName(string assemblyName, string typeName)
+ {
+ return assemblyName == null ? typeName : typeName + ", " + assemblyName;
+ }
+
+ public static Assembly GetAssembly(Type type)
+ {
+ return type.Assembly;
+ }
+
+ public string CodeBase
+ {
+ get
+ {
+ string path = this.Location.Replace(System.IO.Path.DirectorySeparatorChar, '/');
+ if (!path.StartsWith("/"))
+ {
+ path = "/" + path;
+ }
+ return "file://" + path;
+ }
+ }
+
+ internal abstract IList<CustomAttributeData> GetCustomAttributesData(Type attributeType);
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Globalization;
+using System.Configuration.Assemblies;
+using System.IO;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+ public sealed class AssemblyName : ICloneable
+ {
+ private readonly System.Reflection.AssemblyName name;
+ private string culture;
+
+ private AssemblyName(System.Reflection.AssemblyName name, string culture)
+ {
+ this.name = name;
+ this.culture = culture;
+ }
+
+ public AssemblyName()
+ {
+ name = new System.Reflection.AssemblyName();
+ }
+
+ public AssemblyName(string assemblyName)
+ {
+ name = new System.Reflection.AssemblyName(assemblyName);
+ }
+
+ public override string ToString()
+ {
+ string str = name.ToString();
+ if (culture != null)
+ {
+ str = str.Replace("Culture=neutral", "Culture=" + culture);
+ }
+ return str;
+ }
+
+ public string Name
+ {
+ get { return name.Name; }
+ set { name.Name = value; }
+ }
+
+ public CultureInfo CultureInfo
+ {
+ get { return name.CultureInfo; }
+ set
+ {
+ name.CultureInfo = value;
+ culture = null;
+ }
+ }
+
+ internal string Culture
+ {
+ set
+ {
+ culture = value;
+ name.CultureInfo = CultureInfo.InvariantCulture;
+ }
+ }
+
+ public Version Version
+ {
+ get { return name.Version; }
+ set { name.Version = value; }
+ }
+
+ public StrongNameKeyPair KeyPair
+ {
+ get { return name.KeyPair == null ? null : new StrongNameKeyPair(name.KeyPair); }
+ set { name.KeyPair = value == null ? null : value.keyPair; }
+ }
+
+ public string CodeBase
+ {
+ get { return name.CodeBase; }
+ set { name.CodeBase = value; }
+ }
+
+ public ProcessorArchitecture ProcessorArchitecture
+ {
+ get { return (ProcessorArchitecture)name.ProcessorArchitecture; }
+ set { name.ProcessorArchitecture = (System.Reflection.ProcessorArchitecture)value; }
+ }
+
+ public AssemblyNameFlags Flags
+ {
+ get { return (AssemblyNameFlags)name.Flags; }
+ set { name.Flags = (System.Reflection.AssemblyNameFlags)value; }
+ }
+
+ public AssemblyVersionCompatibility VersionCompatibility
+ {
+ get { return name.VersionCompatibility; }
+ set { name.VersionCompatibility = value; }
+ }
+
+ public byte[] GetPublicKey()
+ {
+ return name.GetPublicKey();
+ }
+
+ public void SetPublicKey(byte[] publicKey)
+ {
+ name.SetPublicKey(publicKey);
+ }
+
+ public byte[] GetPublicKeyToken()
+ {
+ return name.GetPublicKeyToken();
+ }
+
+ public void SetPublicKeyToken(byte[] publicKeyToken)
+ {
+ name.SetPublicKeyToken(publicKeyToken);
+ }
+
+ public AssemblyHashAlgorithm HashAlgorithm
+ {
+ get { return name.HashAlgorithm; }
+ set { name.HashAlgorithm = value; }
+ }
+
+ public string FullName
+ {
+ get
+ {
+ string str = name.FullName;
+ if (culture != null)
+ {
+ str = str.Replace("Culture=neutral", "Culture=" + culture);
+ }
+ return str;
+ }
+ }
+
+ public override bool Equals(object obj)
+ {
+ AssemblyName other = obj as AssemblyName;
+ return other != null && other.FullName == this.FullName;
+ }
+
+ public override int GetHashCode()
+ {
+ return FullName.GetHashCode();
+ }
+
+ public object Clone()
+ {
+ return new AssemblyName((System.Reflection.AssemblyName)name.Clone(), culture);
+ }
+
+ public static bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition)
+ {
+ return System.Reflection.AssemblyName.ReferenceMatchesDefinition(reference.name, definition.name);
+ }
+
+ public static AssemblyName GetAssemblyName(string path)
+ {
+ try
+ {
+ path = Path.GetFullPath(path);
+ using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ ModuleReader module = new ModuleReader(null, null, fs, path);
+ if (module.Assembly == null)
+ {
+ throw new BadImageFormatException("Module does not contain a manifest");
+ }
+ return module.Assembly.GetName();
+ }
+ }
+ catch (IOException x)
+ {
+ throw new FileNotFoundException(x.Message, x);
+ }
+ catch (UnauthorizedAccessException x)
+ {
+ throw new FileNotFoundException(x.Message, x);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection
+{
+ [Serializable]
+ public sealed class BadImageFormatException : Exception
+ {
+ public BadImageFormatException()
+ {
+ }
+
+ public BadImageFormatException(string message)
+ : base(message)
+ {
+ }
+
+ public BadImageFormatException(string message, Exception inner)
+ : base(message, inner)
+ {
+ }
+
+ private BadImageFormatException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Globalization;
+
+namespace IKVM.Reflection
+{
+ public abstract class Binder
+ {
+ protected Binder()
+ {
+ throw new NotSupportedException();
+ }
+
+ public abstract MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state);
+ public abstract FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture);
+ public abstract object ChangeType(object value, Type type, CultureInfo culture);
+ public abstract void ReorderArgumentArray(ref object[] args, object state);
+ public abstract MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers);
+ public abstract PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers);
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+
+namespace IKVM.Reflection
+{
+ public abstract class ConstructorInfo : MethodBase
+ {
+ public static readonly string ConstructorName = ".ctor";
+ public static readonly string TypeConstructorName = ".cctor";
+
+ internal abstract MethodInfo GetMethodInfo();
+
+ internal override MethodBase BindTypeParameters(Type type)
+ {
+ return new ConstructorInfoImpl((MethodInfo)GetMethodInfo().BindTypeParameters(type));
+ }
+
+ public sealed override MemberTypes MemberType
+ {
+ get { return MemberTypes.Constructor; }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get { return GetMethodInfo().ContainsGenericParameters; }
+ }
+
+ public sealed override ParameterInfo[] GetParameters()
+ {
+ ParameterInfo[] parameters = GetMethodInfo().GetParameters();
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = new ParameterInfoWrapper(this, parameters[i]);
+ }
+ return parameters;
+ }
+
+ private sealed class ParameterInfoWrapper : ParameterInfo
+ {
+ private readonly ConstructorInfo ctor;
+ private readonly ParameterInfo forward;
+
+ internal ParameterInfoWrapper(ConstructorInfo ctor, ParameterInfo forward)
+ {
+ this.ctor = ctor;
+ this.forward = forward;
+ }
+
+ public override string Name
+ {
+ get { return forward.Name; }
+ }
+
+ public override Type ParameterType
+ {
+ get { return forward.ParameterType; }
+ }
+
+ public override ParameterAttributes Attributes
+ {
+ get { return forward.Attributes; }
+ }
+
+ public override int Position
+ {
+ get { return forward.Position; }
+ }
+
+ public override object RawDefaultValue
+ {
+ get { return forward.RawDefaultValue; }
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return forward.GetOptionalCustomModifiers();
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return forward.GetRequiredCustomModifiers();
+ }
+
+ public override MemberInfo Member
+ {
+ get { return ctor; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return forward.MetadataToken; }
+ }
+
+ internal override Module Module
+ {
+ get { return ctor.Module; }
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return forward.GetCustomAttributesData(attributeType);
+ }
+ }
+ }
+
+ sealed class ConstructorInfoImpl : ConstructorInfo
+ {
+ private readonly MethodInfo method;
+
+ internal ConstructorInfoImpl(MethodInfo method)
+ {
+ this.method = method;
+ }
+
+ public override bool Equals(object obj)
+ {
+ ConstructorInfoImpl other = obj as ConstructorInfoImpl;
+ return other != null && other.method.Equals(method);
+ }
+
+ public override int GetHashCode()
+ {
+ return method.GetHashCode();
+ }
+
+ public override MethodBody GetMethodBody()
+ {
+ return method.GetMethodBody();
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get { return method.CallingConvention; }
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return method.Attributes; }
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return method.GetMethodImplementationFlags();
+ }
+
+ internal override int ParameterCount
+ {
+ get { return method.ParameterCount; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return method.DeclaringType; }
+ }
+
+ public override string Name
+ {
+ get { return method.Name; }
+ }
+
+ public override string ToString()
+ {
+ return method.ToString();
+ }
+
+ public override Module Module
+ {
+ get { return method.Module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return method.MetadataToken; }
+ }
+
+ internal override MethodInfo GetMethodInfo()
+ {
+ return method;
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return method.GetCustomAttributesData(attributeType);
+ }
+
+ internal override MethodInfo GetMethodOnTypeDefinition()
+ {
+ return method.GetMethodOnTypeDefinition();
+ }
+
+ internal override MethodSignature MethodSignature
+ {
+ get { return method.MethodSignature; }
+ }
+
+ internal override int ImportTo(Emit.ModuleBuilder module)
+ {
+ return method.ImportTo(module);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+ public sealed class CustomAttributeData
+ {
+ internal static readonly IList<CustomAttributeData> EmptyList = new List<CustomAttributeData>(0).AsReadOnly();
+ private Module module;
+ private int index;
+ private ConstructorInfo lazyConstructor;
+ private IList<CustomAttributeTypedArgument> lazyConstructorArguments;
+ private IList<CustomAttributeNamedArgument> lazyNamedArguments;
+
+ internal CustomAttributeData(Module module, int index)
+ {
+ this.module = module;
+ this.index = index;
+ }
+
+ internal CustomAttributeData(ConstructorInfo constructor, object[] args, List<CustomAttributeNamedArgument> namedArguments)
+ {
+ this.lazyConstructor = constructor;
+ MethodSignature sig = constructor.MethodSignature;
+ List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
+ for (int i = 0; i < args.Length; i++)
+ {
+ list.Add(new CustomAttributeTypedArgument(sig.GetParameterType(i), args[i]));
+ }
+ lazyConstructorArguments = list.AsReadOnly();
+ if (namedArguments == null)
+ {
+ this.lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
+ }
+ else
+ {
+ this.lazyNamedArguments = namedArguments.AsReadOnly();
+ }
+ }
+
+ internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, ByteReader br)
+ {
+ this.lazyConstructor = constructor;
+ if (br.Length == 0)
+ {
+ // it's legal to have an empty blob
+ lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
+ lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
+ }
+ else
+ {
+ if (br.ReadUInt16() != 1)
+ {
+ throw new BadImageFormatException();
+ }
+ lazyConstructorArguments = ReadConstructorArguments(asm, br, constructor);
+ lazyNamedArguments = ReadNamedArguments(asm, br, br.ReadUInt16(), constructor.DeclaringType);
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append('[');
+ sb.Append(Constructor.DeclaringType.FullName);
+ sb.Append('(');
+ string sep = "";
+ foreach (CustomAttributeTypedArgument arg in ConstructorArguments)
+ {
+ sb.Append(sep);
+ sep = ", ";
+ AppendValue(sb, arg);
+ }
+ foreach (CustomAttributeNamedArgument named in NamedArguments)
+ {
+ sb.Append(sep);
+ sep = ", ";
+ sb.Append(named.MemberInfo.Name);
+ sb.Append(" = ");
+ AppendValue(sb, named.TypedValue);
+ }
+ sb.Append(')');
+ sb.Append(']');
+ return sb.ToString();
+ }
+
+ private static void AppendValue(StringBuilder sb, CustomAttributeTypedArgument arg)
+ {
+ if (arg.ArgumentType == arg.ArgumentType.Module.universe.System_String)
+ {
+ sb.Append('"').Append(arg.Value).Append('"');
+ }
+ else
+ {
+ if (arg.ArgumentType.IsEnum)
+ {
+ sb.Append('(');
+ sb.Append(arg.ArgumentType.FullName);
+ sb.Append(')');
+ }
+ sb.Append(arg.Value);
+ }
+ }
+
+ internal static void ReadDeclarativeSecurity(Assembly asm, List<CustomAttributeData> list, int action, ByteReader br)
+ {
+ Universe u = asm.universe;
+ if (br.PeekByte() == '.')
+ {
+ br.ReadByte();
+ int count = br.ReadCompressedInt();
+ for (int j = 0; j < count; j++)
+ {
+ Type type = ReadType(asm, br);
+ ConstructorInfo constructor;
+ if (type == u.System_Security_Permissions_HostProtectionAttribute && action == (int)System.Security.Permissions.SecurityAction.LinkDemand)
+ {
+ constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
+ }
+ else
+ {
+ constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { u.System_Security_Permissions_SecurityAction }, null);
+ }
+ // LAMESPEC there is an additional length here (probably of the named argument list)
+ ByteReader slice = br.Slice(br.ReadCompressedInt());
+ // LAMESPEC the count of named arguments is a compressed integer (instead of UInt16 as NumNamed in custom attributes)
+ list.Add(new CustomAttributeData(constructor, action, ReadNamedArguments(asm, slice, slice.ReadCompressedInt(), type)));
+ }
+ }
+ else
+ {
+ // .NET 1.x format (xml)
+ char[] buf = new char[br.Length / 2];
+ for (int i = 0; i < buf.Length; i++)
+ {
+ buf[i] = br.ReadChar();
+ }
+ string xml = new String(buf);
+ ConstructorInfo constructor = u.System_Security_Permissions_PermissionSetAttribute.GetConstructor(new Type[] { u.System_Security_Permissions_SecurityAction });
+ List<CustomAttributeNamedArgument> args = new List<CustomAttributeNamedArgument>();
+ args.Add(new CustomAttributeNamedArgument(u.System_Security_Permissions_PermissionSetAttribute.GetProperty("XML"),
+ new CustomAttributeTypedArgument(u.System_String, xml)));
+ list.Add(new CustomAttributeData(constructor, action, args));
+ }
+ }
+
+ private CustomAttributeData(ConstructorInfo constructor, int securityAction, IList<CustomAttributeNamedArgument> namedArguments)
+ {
+ Universe u = constructor.Module.universe;
+ this.lazyConstructor = constructor;
+ List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
+ list.Add(new CustomAttributeTypedArgument(u.System_Security_Permissions_SecurityAction, securityAction));
+ this.lazyConstructorArguments = list.AsReadOnly();
+ this.lazyNamedArguments = namedArguments;
+ }
+
+ private static Type ReadFieldOrPropType(Assembly asm, ByteReader br)
+ {
+ Universe u = asm.universe;
+ switch (br.ReadByte())
+ {
+ case Signature.ELEMENT_TYPE_BOOLEAN:
+ return u.System_Boolean;
+ case Signature.ELEMENT_TYPE_CHAR:
+ return u.System_Char;
+ case Signature.ELEMENT_TYPE_I1:
+ return u.System_SByte;
+ case Signature.ELEMENT_TYPE_U1:
+ return u.System_Byte;
+ case Signature.ELEMENT_TYPE_I2:
+ return u.System_Int16;
+ case Signature.ELEMENT_TYPE_U2:
+ return u.System_UInt16;
+ case Signature.ELEMENT_TYPE_I4:
+ return u.System_Int32;
+ case Signature.ELEMENT_TYPE_U4:
+ return u.System_UInt32;
+ case Signature.ELEMENT_TYPE_I8:
+ return u.System_Int64;
+ case Signature.ELEMENT_TYPE_U8:
+ return u.System_UInt64;
+ case Signature.ELEMENT_TYPE_R4:
+ return u.System_Single;
+ case Signature.ELEMENT_TYPE_R8:
+ return u.System_Double;
+ case Signature.ELEMENT_TYPE_STRING:
+ return u.System_String;
+ case Signature.ELEMENT_TYPE_SZARRAY:
+ return ReadFieldOrPropType(asm, br).MakeArrayType();
+ case 0x55:
+ return ReadType(asm, br);
+ case 0x50:
+ return u.System_Type;
+ case 0x51:
+ return u.System_Object;
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+
+ private static CustomAttributeTypedArgument ReadFixedArg(Assembly asm, ByteReader br, Type type)
+ {
+ Universe u = asm.universe;
+ if (type == u.System_String)
+ {
+ return new CustomAttributeTypedArgument(type, br.ReadString());
+ }
+ else if (type == u.System_Type)
+ {
+ return new CustomAttributeTypedArgument(type, ReadType(asm, br));
+ }
+ else if (type == u.System_Object)
+ {
+ return ReadFixedArg(asm, br, ReadFieldOrPropType(asm, br));
+ }
+ else if (type.IsArray)
+ {
+ int length = br.ReadInt32();
+ if (length == -1)
+ {
+ return new CustomAttributeTypedArgument(type, null);
+ }
+ Type elementType = type.GetElementType();
+ CustomAttributeTypedArgument[] array = new CustomAttributeTypedArgument[length];
+ for (int i = 0; i < length; i++)
+ {
+ array[i] = ReadFixedArg(asm, br, elementType);
+ }
+ return new CustomAttributeTypedArgument(type, array);
+ }
+ else if (type.IsEnum)
+ {
+ return new CustomAttributeTypedArgument(type, ReadFixedArg(asm, br, type.GetEnumUnderlyingTypeImpl()).Value);
+ }
+ else
+ {
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.Boolean:
+ return new CustomAttributeTypedArgument(type, br.ReadByte() != 0);
+ case TypeCode.Char:
+ return new CustomAttributeTypedArgument(type, br.ReadChar());
+ case TypeCode.Single:
+ return new CustomAttributeTypedArgument(type, br.ReadSingle());
+ case TypeCode.Double:
+ return new CustomAttributeTypedArgument(type, br.ReadDouble());
+ case TypeCode.SByte:
+ return new CustomAttributeTypedArgument(type, br.ReadSByte());
+ case TypeCode.Int16:
+ return new CustomAttributeTypedArgument(type, br.ReadInt16());
+ case TypeCode.Int32:
+ return new CustomAttributeTypedArgument(type, br.ReadInt32());
+ case TypeCode.Int64:
+ return new CustomAttributeTypedArgument(type, br.ReadInt64());
+ case TypeCode.Byte:
+ return new CustomAttributeTypedArgument(type, br.ReadByte());
+ case TypeCode.UInt16:
+ return new CustomAttributeTypedArgument(type, br.ReadUInt16());
+ case TypeCode.UInt32:
+ return new CustomAttributeTypedArgument(type, br.ReadUInt32());
+ case TypeCode.UInt64:
+ return new CustomAttributeTypedArgument(type, br.ReadUInt64());
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ private static Type ReadType(Assembly asm, ByteReader br)
+ {
+ string typeName = br.ReadString();
+ if (typeName == null)
+ {
+ return null;
+ }
+ if (typeName.Length > 0 && typeName[typeName.Length - 1] == 0)
+ {
+ // there are broken compilers that emit an extra NUL character after the type name
+ typeName = typeName.Substring(0, typeName.Length - 1);
+ }
+ return asm.universe.GetType(asm, typeName, true);
+ }
+
+ private static IList<CustomAttributeTypedArgument> ReadConstructorArguments(Assembly asm, ByteReader br, ConstructorInfo constructor)
+ {
+ MethodSignature sig = constructor.MethodSignature;
+ int count = sig.GetParameterCount();
+ List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>(count);
+ for (int i = 0; i < count; i++)
+ {
+ list.Add(ReadFixedArg(asm, br, sig.GetParameterType(i)));
+ }
+ return list.AsReadOnly();
+ }
+
+ private static IList<CustomAttributeNamedArgument> ReadNamedArguments(Assembly asm, ByteReader br, int named, Type type)
+ {
+ List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>(named);
+ for (int i = 0; i < named; i++)
+ {
+ byte fieldOrProperty = br.ReadByte();
+ Type fieldOrPropertyType = ReadFieldOrPropType(asm, br);
+ string name = br.ReadString();
+ CustomAttributeTypedArgument value = ReadFixedArg(asm, br, fieldOrPropertyType);
+ MemberInfo member;
+ switch (fieldOrProperty)
+ {
+ case 0x53:
+ member = GetField(type, name);
+ break;
+ case 0x54:
+ member = GetProperty(type, name);
+ break;
+ default:
+ throw new BadImageFormatException();
+ }
+ if (member == null)
+ {
+ throw new BadImageFormatException();
+ }
+ list.Add(new CustomAttributeNamedArgument(member, value));
+ }
+ return list.AsReadOnly();
+ }
+
+ private static FieldInfo GetField(Type type, string name)
+ {
+ for (; type != null; type = type.BaseType)
+ {
+ foreach (FieldInfo field in type.__GetDeclaredFields())
+ {
+ if (field.IsPublic && !field.IsStatic && field.Name == name)
+ {
+ return field;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static PropertyInfo GetProperty(Type type, string name)
+ {
+ for (; type != null; type = type.BaseType)
+ {
+ foreach (PropertyInfo property in type.__GetDeclaredProperties())
+ {
+ if (property.IsPublic && !property.IsStatic && property.Name == name)
+ {
+ return property;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void __ReadTypeName(out string ns, out string name)
+ {
+ if (lazyConstructor == null)
+ {
+ ModuleReader mod = module as ModuleReader;
+ if (mod != null)
+ {
+ int methodToken = mod.CustomAttribute.records[index].Type;
+ if ((methodToken >> 24) == MemberRefTable.Index)
+ {
+ int methodIndex = (methodToken & 0xFFFFFF) - 1;
+ int typeToken = mod.MemberRef.records[methodIndex].Class;
+ if ((typeToken >> 24) == TypeRefTable.Index)
+ {
+ int typeIndex = (typeToken & 0xFFFFFF) - 1;
+ int typeNameSpace = mod.TypeRef.records[typeIndex].TypeNameSpace;
+ ns = typeNameSpace == 0 ? null : mod.GetString(typeNameSpace);
+ name = mod.GetString(mod.TypeRef.records[typeIndex].TypeName);
+ return;
+ }
+ }
+ }
+ }
+ ns = Constructor.DeclaringType.Namespace;
+ name = Constructor.DeclaringType.Name;
+ }
+
+ public ConstructorInfo Constructor
+ {
+ get
+ {
+ if (lazyConstructor == null)
+ {
+ lazyConstructor = (ConstructorInfo)module.ResolveMethod(module.CustomAttribute.records[index].Type);
+ }
+ return lazyConstructor;
+ }
+ }
+
+ public IList<CustomAttributeTypedArgument> ConstructorArguments
+ {
+ get
+ {
+ if (lazyConstructorArguments == null)
+ {
+ LazyParseArguments();
+ }
+ return lazyConstructorArguments;
+ }
+ }
+
+ public IList<CustomAttributeNamedArgument> NamedArguments
+ {
+ get
+ {
+ if (lazyNamedArguments == null)
+ {
+ LazyParseArguments();
+ }
+ return lazyNamedArguments;
+ }
+ }
+
+ private void LazyParseArguments()
+ {
+ ByteReader br = module.GetBlob(module.CustomAttribute.records[index].Value);
+ if (br.Length == 0)
+ {
+ // it's legal to have an empty blob
+ lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
+ lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
+ }
+ else
+ {
+ if (br.ReadUInt16() != 1)
+ {
+ throw new BadImageFormatException();
+ }
+ lazyConstructorArguments = ReadConstructorArguments(module.Assembly, br, Constructor);
+ lazyNamedArguments = ReadNamedArguments(module.Assembly, br, br.ReadUInt16(), Constructor.DeclaringType);
+ }
+ }
+
+ public CustomAttributeBuilder __ToBuilder()
+ {
+ object[] args = new object[ConstructorArguments.Count];
+ for (int i = 0; i < args.Length; i++)
+ {
+ args[i] = ConstructorArguments[i].Value;
+ }
+ List<PropertyInfo> namedProperties = new List<PropertyInfo>();
+ List<object> propertyValues = new List<object>();
+ List<FieldInfo> namedFields = new List<FieldInfo>();
+ List<object> fieldValues = new List<object>();
+ foreach (CustomAttributeNamedArgument named in NamedArguments)
+ {
+ if (named.MemberInfo is PropertyInfo)
+ {
+ namedProperties.Add((PropertyInfo)named.MemberInfo);
+ propertyValues.Add(named.TypedValue.Value);
+ }
+ else
+ {
+ namedFields.Add((FieldInfo)named.MemberInfo);
+ fieldValues.Add(named.TypedValue.Value);
+ }
+ }
+ return new CustomAttributeBuilder(Constructor, args, namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray());
+ }
+
+ public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo member)
+ {
+ return member.GetCustomAttributesData(null);
+ }
+
+ public static IList<CustomAttributeData> GetCustomAttributes(Assembly assembly)
+ {
+ return assembly.GetCustomAttributesData(null);
+ }
+
+ public static IList<CustomAttributeData> GetCustomAttributes(Module module)
+ {
+ return module.GetCustomAttributesData(null);
+ }
+
+ public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo parameter)
+ {
+ return parameter.GetCustomAttributesData(null);
+ }
+
+ public static IList<CustomAttributeData> __GetCustomAttributes(Assembly assembly, Type attributeType, bool inherit)
+ {
+ return assembly.GetCustomAttributesData(attributeType);
+ }
+
+ public static IList<CustomAttributeData> __GetCustomAttributes(Module module, Type attributeType, bool inherit)
+ {
+ return module.GetCustomAttributesData(attributeType);
+ }
+
+ public static IList<CustomAttributeData> __GetCustomAttributes(ParameterInfo parameter, Type attributeType, bool inherit)
+ {
+ return parameter.GetCustomAttributesData(attributeType);
+ }
+
+ public static IList<CustomAttributeData> __GetCustomAttributes(MemberInfo member, Type attributeType, bool inherit)
+ {
+ if (!inherit || !IsInheritableAttribute(attributeType))
+ {
+ return member.GetCustomAttributesData(attributeType);
+ }
+ List<CustomAttributeData> list = new List<CustomAttributeData>();
+ for (; ; )
+ {
+ list.AddRange(member.GetCustomAttributesData(attributeType));
+ Type type = member as Type;
+ if (type != null)
+ {
+ type = type.BaseType;
+ if (type == null)
+ {
+ return list;
+ }
+ member = type;
+ continue;
+ }
+ MethodInfo method = member as MethodInfo;
+ if (method != null)
+ {
+ MemberInfo prev = member;
+ method = method.GetBaseDefinition();
+ if (method == null || method == prev)
+ {
+ return list;
+ }
+ member = method;
+ continue;
+ }
+ return list;
+ }
+ }
+
+ public static IList<CustomAttributeData> __GetDeclarativeSecurity(Assembly assembly)
+ {
+ return assembly.ManifestModule.GetDeclarativeSecurity(0x20000001);
+ }
+
+ public static IList<CustomAttributeData> __GetDeclarativeSecurity(Type type)
+ {
+ if ((type.Attributes & TypeAttributes.HasSecurity) != 0)
+ {
+ return type.Module.GetDeclarativeSecurity(type.MetadataToken);
+ }
+ else
+ {
+ return EmptyList;
+ }
+ }
+
+ public static IList<CustomAttributeData> __GetDeclarativeSecurity(MethodBase method)
+ {
+ if ((method.Attributes & MethodAttributes.HasSecurity) != 0)
+ {
+ return method.Module.GetDeclarativeSecurity(method.MetadataToken);
+ }
+ else
+ {
+ return EmptyList;
+ }
+ }
+
+ private static bool IsInheritableAttribute(Type attribute)
+ {
+ Type attributeUsageAttribute = attribute.Module.universe.System_AttributeUsageAttribute;
+ IList<CustomAttributeData> attr = attribute.GetCustomAttributesData(attributeUsageAttribute);
+ if (attr.Count != 0)
+ {
+ foreach (CustomAttributeNamedArgument named in attr[0].NamedArguments)
+ {
+ if (named.MemberInfo.Name == "Inherited")
+ {
+ return (bool)named.TypedValue.Value;
+ }
+ }
+ }
+ return true;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ public struct CustomAttributeNamedArgument
+ {
+ private readonly MemberInfo member;
+ private readonly CustomAttributeTypedArgument value;
+
+ internal CustomAttributeNamedArgument(MemberInfo member, CustomAttributeTypedArgument value)
+ {
+ this.member = member;
+ this.value = value;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return this == obj as CustomAttributeNamedArgument?;
+ }
+
+ public override int GetHashCode()
+ {
+ return member.GetHashCode() ^ 53 * value.GetHashCode();
+ }
+
+ public MemberInfo MemberInfo
+ {
+ get { return member; }
+ }
+
+ public CustomAttributeTypedArgument TypedValue
+ {
+ get { return value; }
+ }
+
+ public static bool operator ==(CustomAttributeNamedArgument arg1, CustomAttributeNamedArgument arg2)
+ {
+ return arg1.member.Equals(arg2.member) && arg1.value == arg2.value;
+ }
+
+ public static bool operator !=(CustomAttributeNamedArgument arg1, CustomAttributeNamedArgument arg2)
+ {
+ return !(arg1 == arg2);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ public struct CustomAttributeTypedArgument
+ {
+ private readonly Type type;
+ private readonly object value;
+
+ internal CustomAttributeTypedArgument(Type type, object value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return this == obj as CustomAttributeTypedArgument?;
+ }
+
+ public override int GetHashCode()
+ {
+ return type.GetHashCode() ^ 77 * (value == null ? 0 : value.GetHashCode());
+ }
+
+ public Type ArgumentType
+ {
+ get { return type; }
+ }
+
+ public Object Value
+ {
+ get { return value; }
+ }
+
+ public static bool operator ==(CustomAttributeTypedArgument arg1, CustomAttributeTypedArgument arg2)
+ {
+ return arg1.type.Equals(arg2.type) && (arg1.value == arg2.value || (arg1.value != null && arg1.value.Equals(arg2.value)));
+ }
+
+ public static bool operator !=(CustomAttributeTypedArgument arg1, CustomAttributeTypedArgument arg2)
+ {
+ return !(arg1 == arg2);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Configuration.Assemblies;
+using System.IO;
+using System.Diagnostics;
+using System.Globalization;
+using System.Security.Cryptography;
+using System.Security;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class AssemblyBuilder : Assembly
+ {
+ private readonly string name;
+ private ushort majorVersion;
+ private ushort minorVersion;
+ private ushort buildVersion;
+ private ushort revisionVersion;
+ private string culture;
+ private AssemblyNameFlags flags;
+ private AssemblyHashAlgorithm hashAlgorithm;
+ private StrongNameKeyPair keyPair;
+ private byte[] publicKey;
+ internal readonly string dir;
+ private readonly PermissionSet requiredPermissions;
+ private readonly PermissionSet optionalPermissions;
+ private readonly PermissionSet refusedPermissions;
+ private PEFileKinds fileKind = PEFileKinds.Dll;
+ private MethodInfo entryPoint;
+ private VersionInfo versionInfo;
+ private ResourceSection unmanagedResources;
+ private string imageRuntimeVersion;
+ internal int mdStreamVersion = 0x20000;
+ private Module pseudoManifestModule;
+ private readonly List<ResourceFile> resourceFiles = new List<ResourceFile>();
+ private readonly List<ModuleBuilder> modules = new List<ModuleBuilder>();
+ private readonly List<Module> addedModules = new List<Module>();
+ private readonly List<CustomAttributeBuilder> customAttributes = new List<CustomAttributeBuilder>();
+ private readonly List<CustomAttributeBuilder> declarativeSecurity = new List<CustomAttributeBuilder>();
+ private readonly List<Type> typeForwarders = new List<Type>();
+
+ private struct ResourceFile
+ {
+ internal string Name;
+ internal string FileName;
+ internal ResourceAttributes Attributes;
+ }
+
+ internal AssemblyBuilder(Universe universe, AssemblyName name, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
+ : base(universe)
+ {
+ this.name = name.Name;
+ SetVersionHelper(name.Version);
+ if (name.CultureInfo != null && !string.IsNullOrEmpty(name.CultureInfo.Name))
+ {
+ this.culture = name.CultureInfo.Name;
+ }
+ this.flags = name.Flags;
+ this.hashAlgorithm = name.HashAlgorithm;
+ if (this.hashAlgorithm == AssemblyHashAlgorithm.None)
+ {
+ this.hashAlgorithm = AssemblyHashAlgorithm.SHA1;
+ }
+ this.keyPair = name.KeyPair;
+ if (this.keyPair != null)
+ {
+ this.publicKey = this.keyPair.PublicKey;
+ }
+ else
+ {
+ byte[] publicKey = name.GetPublicKey();
+ if (publicKey != null && publicKey.Length != 0)
+ {
+ this.publicKey = (byte[])publicKey.Clone();
+ }
+ }
+ this.dir = dir ?? ".";
+ this.requiredPermissions = requiredPermissions;
+ this.optionalPermissions = optionalPermissions;
+ this.refusedPermissions = refusedPermissions;
+ if (universe.HasMscorlib && universe.Mscorlib.ImageRuntimeVersion != null)
+ {
+ this.imageRuntimeVersion = universe.Mscorlib.ImageRuntimeVersion;
+ }
+ else
+ {
+ this.imageRuntimeVersion = typeof(object).Assembly.ImageRuntimeVersion;
+ }
+ }
+
+ private void SetVersionHelper(Version version)
+ {
+ if (version == null)
+ {
+ majorVersion = 0;
+ minorVersion = 0;
+ buildVersion = 0;
+ revisionVersion = 0;
+ }
+ else
+ {
+ majorVersion = (ushort)version.Major;
+ minorVersion = (ushort)version.Minor;
+ buildVersion = version.Build == -1 ? (ushort)0 : (ushort)version.Build;
+ revisionVersion = version.Revision == -1 ? (ushort)0 : (ushort)version.Revision;
+ }
+ }
+
+ public void __SetAssemblyVersion(Version version)
+ {
+ AssemblyName oldName = GetName();
+ SetVersionHelper(version);
+ universe.RenameAssembly(this, oldName);
+ }
+
+ public void __SetAssemblyCulture(string cultureName)
+ {
+ AssemblyName oldName = GetName();
+ this.culture = cultureName;
+ universe.RenameAssembly(this, oldName);
+ }
+
+ public void __SetAssemblyKeyPair(StrongNameKeyPair keyPair)
+ {
+ AssemblyName oldName = GetName();
+ this.keyPair = keyPair;
+ if (keyPair != null)
+ {
+ this.publicKey = keyPair.PublicKey;
+ }
+ universe.RenameAssembly(this, oldName);
+ }
+
+ // this is used in combination with delay signing
+ public void __SetAssemblyPublicKey(byte[] publicKey)
+ {
+ AssemblyName oldName = GetName();
+ this.publicKey = publicKey == null ? null : (byte[])publicKey.Clone();
+ universe.RenameAssembly(this, oldName);
+ }
+
+ public void __SetAssemblyAlgorithmId(AssemblyHashAlgorithm hashAlgorithm)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ }
+
+ public void __SetAssemblyFlags(AssemblyNameFlags flags)
+ {
+ this.flags = flags;
+ }
+
+ public override AssemblyName GetName()
+ {
+ AssemblyName n = new AssemblyName();
+ n.Name = name;
+ n.Version = new Version(majorVersion, minorVersion, buildVersion, revisionVersion);
+ n.Culture = culture;
+ n.HashAlgorithm = hashAlgorithm;
+ n.Flags = flags;
+ n.SetPublicKey(publicKey != null ? (byte[])publicKey.Clone() : Empty<byte>.Array);
+ n.KeyPair = keyPair;
+ return n;
+ }
+
+ public override string FullName
+ {
+ get { return GetName().FullName; }
+ }
+
+ public override string Location
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public ModuleBuilder DefineDynamicModule(string name, string fileName)
+ {
+ return DefineDynamicModule(name, fileName, false);
+ }
+
+ public ModuleBuilder DefineDynamicModule(string name, string fileName, bool emitSymbolInfo)
+ {
+ ModuleBuilder module = new ModuleBuilder(this, name, fileName, emitSymbolInfo);
+ modules.Add(module);
+ return module;
+ }
+
+ public ModuleBuilder GetDynamicModule(string name)
+ {
+ foreach (ModuleBuilder module in modules)
+ {
+ if (module.Name == name)
+ {
+ return module;
+ }
+ }
+ return null;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ customAttributes.Add(customBuilder);
+ }
+
+ public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+ {
+ declarativeSecurity.Add(customBuilder);
+ }
+
+ public void __AddTypeForwarder(Type type)
+ {
+ typeForwarders.Add(type);
+ }
+
+ public void SetEntryPoint(MethodInfo entryMethod)
+ {
+ SetEntryPoint(entryMethod, PEFileKinds.ConsoleApplication);
+ }
+
+ public void SetEntryPoint(MethodInfo entryMethod, PEFileKinds fileKind)
+ {
+ this.entryPoint = entryMethod;
+ this.fileKind = fileKind;
+ }
+
+ public void Save(string assemblyFileName)
+ {
+ Save(assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
+ }
+
+ public void Save(string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+ {
+ ModuleBuilder manifestModule = null;
+
+ foreach (ModuleBuilder moduleBuilder in modules)
+ {
+ moduleBuilder.PopulatePropertyAndEventTables();
+
+ if (manifestModule == null
+ && string.Compare(moduleBuilder.fileName, assemblyFileName, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ manifestModule = moduleBuilder;
+ }
+ }
+
+ if (manifestModule == null)
+ {
+ manifestModule = DefineDynamicModule("RefEmit_OnDiskManifestModule", assemblyFileName, false);
+ }
+
+ AssemblyTable.Record assemblyRecord = new AssemblyTable.Record();
+ assemblyRecord.HashAlgId = (int)hashAlgorithm;
+ assemblyRecord.Name = manifestModule.Strings.Add(name);
+ assemblyRecord.MajorVersion = majorVersion;
+ assemblyRecord.MinorVersion = minorVersion;
+ assemblyRecord.BuildNumber = buildVersion;
+ assemblyRecord.RevisionNumber = revisionVersion;
+ if (publicKey != null)
+ {
+ assemblyRecord.PublicKey = manifestModule.Blobs.Add(ByteBuffer.Wrap(publicKey));
+ assemblyRecord.Flags = (int)(flags | AssemblyNameFlags.PublicKey);
+ }
+ else
+ {
+ assemblyRecord.Flags = (int)(flags & ~AssemblyNameFlags.PublicKey);
+ }
+ if (culture != null)
+ {
+ assemblyRecord.Culture = manifestModule.Strings.Add(culture);
+ }
+ int token = 0x20000000 + manifestModule.AssemblyTable.AddRecord(assemblyRecord);
+
+#pragma warning disable 618
+ // this values are obsolete, but we already know that so we disable the warning
+ System.Security.Permissions.SecurityAction requestMinimum = System.Security.Permissions.SecurityAction.RequestMinimum;
+ System.Security.Permissions.SecurityAction requestOptional = System.Security.Permissions.SecurityAction.RequestOptional;
+ System.Security.Permissions.SecurityAction requestRefuse = System.Security.Permissions.SecurityAction.RequestRefuse;
+#pragma warning restore 618
+ if (requiredPermissions != null)
+ {
+ manifestModule.AddDeclarativeSecurity(token, requestMinimum, requiredPermissions);
+ }
+ if (optionalPermissions != null)
+ {
+ manifestModule.AddDeclarativeSecurity(token, requestOptional, optionalPermissions);
+ }
+ if (refusedPermissions != null)
+ {
+ manifestModule.AddDeclarativeSecurity(token, requestRefuse, refusedPermissions);
+ }
+
+ if (versionInfo != null)
+ {
+ versionInfo.SetName(GetName());
+ versionInfo.SetFileName(assemblyFileName);
+ foreach (CustomAttributeBuilder cab in customAttributes)
+ {
+ // .NET doesn't support copying blob custom attributes into the version info
+ if (!cab.HasBlob)
+ {
+ versionInfo.SetAttribute(cab);
+ }
+ }
+ ByteBuffer versionInfoData = new ByteBuffer(512);
+ versionInfo.Write(versionInfoData);
+ if (unmanagedResources == null)
+ {
+ unmanagedResources = new ResourceSection();
+ }
+ unmanagedResources.AddVersionInfo(versionInfoData);
+ }
+
+ foreach (CustomAttributeBuilder cab in customAttributes)
+ {
+ // we intentionally don't filter out the version info (pseudo) custom attributes (to be compatible with .NET)
+ manifestModule.SetCustomAttribute(0x20000001, cab);
+ }
+
+ manifestModule.AddDeclarativeSecurity(0x20000001, declarativeSecurity);
+
+ foreach (Type type in typeForwarders)
+ {
+ manifestModule.AddTypeForwarder(type);
+ }
+
+ foreach (ResourceFile resfile in resourceFiles)
+ {
+ int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/);
+ ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
+ rec.Offset = 0;
+ rec.Flags = (int)resfile.Attributes;
+ rec.Name = manifestModule.Strings.Add(resfile.Name);
+ rec.Implementation = fileToken;
+ manifestModule.ManifestResource.AddRecord(rec);
+ }
+
+ int entryPointToken = 0;
+
+ foreach (ModuleBuilder moduleBuilder in modules)
+ {
+ moduleBuilder.FillAssemblyRefTable();
+ if (moduleBuilder != manifestModule)
+ {
+ int fileToken;
+ if (entryPoint != null && entryPoint.Module == moduleBuilder)
+ {
+ ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, entryPoint.MetadataToken);
+ entryPointToken = fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
+ }
+ else
+ {
+ ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, 0);
+ fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
+ }
+ moduleBuilder.ExportTypes(fileToken, manifestModule);
+ }
+ }
+
+ foreach (Module module in addedModules)
+ {
+ int fileToken = AddFile(manifestModule, module.FullyQualifiedName, 0 /*ContainsMetaData*/);
+ module.ExportTypes(fileToken, manifestModule);
+ }
+
+ if (entryPointToken == 0 && entryPoint != null)
+ {
+ entryPointToken = entryPoint.MetadataToken;
+ }
+
+ // finally, write the manifest module
+ ModuleWriter.WriteModule(keyPair, publicKey, manifestModule, fileKind, portableExecutableKind, imageFileMachine, unmanagedResources ?? manifestModule.unmanagedResources, entryPointToken);
+ }
+
+ private int AddFile(ModuleBuilder manifestModule, string fileName, int flags)
+ {
+ SHA1Managed hash = new SHA1Managed();
+ string fullPath = fileName;
+ if (dir != null)
+ {
+ fullPath = Path.Combine(dir, fileName);
+ }
+ using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
+ {
+ using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
+ {
+ byte[] buf = new byte[8192];
+ ModuleWriter.HashChunk(fs, cs, buf, (int)fs.Length);
+ }
+ }
+ FileTable.Record file = new FileTable.Record();
+ file.Flags = flags;
+ file.Name = manifestModule.Strings.Add(Path.GetFileName(fileName));
+ file.HashValue = manifestModule.Blobs.Add(ByteBuffer.Wrap(hash.Hash));
+ return 0x26000000 + manifestModule.File.AddRecord(file);
+ }
+
+ public void AddResourceFile(string name, string fileName)
+ {
+ AddResourceFile(name, fileName, ResourceAttributes.Public);
+ }
+
+ public void AddResourceFile(string name, string fileName, ResourceAttributes attribs)
+ {
+ ResourceFile resfile = new ResourceFile();
+ resfile.Name = name;
+ resfile.FileName = fileName;
+ resfile.Attributes = attribs;
+ resourceFiles.Add(resfile);
+ }
+
+ public void DefineVersionInfoResource()
+ {
+ versionInfo = new VersionInfo();
+ }
+
+ public void DefineVersionInfoResource(string product, string productVersion, string company, string copyright, string trademark)
+ {
+ versionInfo = new VersionInfo();
+ versionInfo.product = product;
+ versionInfo.informationalVersion = productVersion;
+ versionInfo.company = company;
+ versionInfo.copyright = copyright;
+ versionInfo.trademark = trademark;
+ }
+
+ public void __DefineIconResource(byte[] iconFile)
+ {
+ unmanagedResources = new ResourceSection();
+ unmanagedResources.AddIcon(iconFile);
+ }
+
+ public void __DefineUnmanagedResource(byte[] resource)
+ {
+ // The standard .NET DefineUnmanagedResource(byte[]) is useless, because it embeds "resource" (as-is) as the .rsrc section,
+ // but it doesn't set the PE file Resource Directory entry to point to it. That's why we have a renamed version, which behaves
+ // like DefineUnmanagedResource(string).
+ unmanagedResources = new ResourceSection();
+ unmanagedResources.ExtractResources(resource);
+ }
+
+ public void DefineUnmanagedResource(string resourceFileName)
+ {
+ // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
+ // also setting the Resource Directory entry.
+ __DefineUnmanagedResource(File.ReadAllBytes(resourceFileName));
+ }
+
+ public override Type[] GetTypes()
+ {
+ List<Type> list = new List<Type>();
+ foreach (ModuleBuilder module in modules)
+ {
+ module.GetTypesImpl(list);
+ }
+ foreach (Module module in addedModules)
+ {
+ module.GetTypesImpl(list);
+ }
+ return list.ToArray();
+ }
+
+ internal override Type GetTypeImpl(string typeName)
+ {
+ foreach (ModuleBuilder mb in modules)
+ {
+ Type type = mb.GetTypeImpl(typeName);
+ if (type != null)
+ {
+ return type;
+ }
+ }
+ foreach (Module module in addedModules)
+ {
+ Type type = module.GetTypeImpl(typeName);
+ if (type != null)
+ {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ public override string ImageRuntimeVersion
+ {
+ get { return imageRuntimeVersion; }
+ }
+
+ public void __SetImageRuntimeVersion(string imageRuntimeVersion, int mdStreamVersion)
+ {
+ this.imageRuntimeVersion = imageRuntimeVersion;
+ this.mdStreamVersion = mdStreamVersion;
+ }
+
+ public override Module ManifestModule
+ {
+ get
+ {
+ if (pseudoManifestModule == null)
+ {
+ pseudoManifestModule = new ManifestModule(this);
+ }
+ return pseudoManifestModule;
+ }
+ }
+
+ public override MethodInfo EntryPoint
+ {
+ get { return entryPoint; }
+ }
+
+ public override AssemblyName[] GetReferencedAssemblies()
+ {
+ return Empty<AssemblyName>.Array;
+ }
+
+ public override Module[] GetLoadedModules(bool getResourceModules)
+ {
+ return GetModules(getResourceModules);
+ }
+
+ public override Module[] GetModules(bool getResourceModules)
+ {
+ List<Module> list = new List<Module>();
+ foreach (ModuleBuilder module in modules)
+ {
+ if (getResourceModules || !module.IsResource())
+ {
+ list.Add(module);
+ }
+ }
+ foreach (Module module in addedModules)
+ {
+ if (getResourceModules || !module.IsResource())
+ {
+ list.Add(module);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public override Module GetModule(string name)
+ {
+ foreach (ModuleBuilder module in modules)
+ {
+ if (module.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return module;
+ }
+ }
+ foreach (Module module in addedModules)
+ {
+ if (module.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return module;
+ }
+ }
+ return null;
+ }
+
+ public Module __AddModule(RawModule module)
+ {
+ Module mod = module.ToModule(this);
+ addedModules.Add(mod);
+ return mod;
+ }
+
+ public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override string[] GetManifestResourceNames()
+ {
+ throw new NotSupportedException();
+ }
+
+ public override Stream GetManifestResourceStream(string resourceName)
+ {
+ throw new NotSupportedException();
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ List<CustomAttributeData> list = new List<CustomAttributeData>();
+ foreach (CustomAttributeBuilder cab in customAttributes)
+ {
+ if (attributeType == null || attributeType.IsAssignableFrom(cab.Constructor.DeclaringType))
+ {
+ list.Add(cab.ToData(this));
+ }
+ }
+ return list;
+ }
+ }
+
+ sealed class ManifestModule : Module
+ {
+ private readonly AssemblyBuilder assembly;
+ private readonly Guid guid = Guid.NewGuid();
+
+ internal ManifestModule(AssemblyBuilder assembly)
+ : base(assembly.universe)
+ {
+ this.assembly = assembly;
+ }
+
+ public override int MDStreamVersion
+ {
+ get { return assembly.mdStreamVersion; }
+ }
+
+ public override Assembly Assembly
+ {
+ get { return assembly; }
+ }
+
+ internal override Type GetTypeImpl(string typeName)
+ {
+ return null;
+ }
+
+ internal override void GetTypesImpl(List<Type> list)
+ {
+ }
+
+ public override string FullyQualifiedName
+ {
+ get { return Path.Combine(assembly.dir, "RefEmit_InMemoryManifestModule"); }
+ }
+
+ public override string Name
+ {
+ get { return "<In Memory Module>"; }
+ }
+
+ public override Guid ModuleVersionId
+ {
+ get { return guid; }
+ }
+
+ public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new ArgumentException();
+ }
+
+ public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new ArgumentException();
+ }
+
+ public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new ArgumentException();
+ }
+
+ public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new ArgumentException();
+ }
+
+ public override string ResolveString(int metadataToken)
+ {
+ throw new ArgumentException();
+ }
+
+ public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+ {
+ throw new ArgumentException();
+ }
+
+ public override string ScopeName
+ {
+ get { return "RefEmit_InMemoryManifestModule"; }
+ }
+
+ public override AssemblyName[] __GetReferencedAssemblies()
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal override Type GetModuleType()
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class ConstructorBuilder : ConstructorInfo
+ {
+ private readonly MethodBuilder methodBuilder;
+
+ internal ConstructorBuilder(MethodBuilder mb)
+ {
+ this.methodBuilder = mb;
+ }
+
+ public override bool Equals(object obj)
+ {
+ ConstructorBuilder other = obj as ConstructorBuilder;
+ return other != null && other.methodBuilder.Equals(methodBuilder);
+ }
+
+ public override int GetHashCode()
+ {
+ return methodBuilder.GetHashCode();
+ }
+
+ public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
+ {
+ return methodBuilder.DefineParameter(position, attributes, strParamName);
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ methodBuilder.SetCustomAttribute(customBuilder);
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ methodBuilder.SetCustomAttribute(con, binaryAttribute);
+ }
+
+ public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+ {
+ methodBuilder.__AddDeclarativeSecurity(customBuilder);
+ }
+
+ public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+ {
+ methodBuilder.AddDeclarativeSecurity(securityAction, permissionSet);
+ }
+
+ public void SetImplementationFlags(MethodImplAttributes attributes)
+ {
+ methodBuilder.SetImplementationFlags(attributes);
+ }
+
+ public ILGenerator GetILGenerator()
+ {
+ return methodBuilder.GetILGenerator();
+ }
+
+ public ILGenerator GetILGenerator(int streamSize)
+ {
+ return methodBuilder.GetILGenerator(streamSize);
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get { return methodBuilder.CallingConvention; }
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return methodBuilder.Attributes; }
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return methodBuilder.GetMethodImplementationFlags();
+ }
+
+ public Type ReturnType
+ {
+ get { return methodBuilder.ReturnType; }
+ }
+
+ internal override int ParameterCount
+ {
+ get { return methodBuilder.ParameterCount; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return methodBuilder.DeclaringType; }
+ }
+
+ public override string Name
+ {
+ get { return methodBuilder.Name; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return methodBuilder.MetadataToken; }
+ }
+
+ public override Module Module
+ {
+ get { return methodBuilder.Module; }
+ }
+
+ public Module GetModule()
+ {
+ return methodBuilder.GetModule();
+ }
+
+ public MethodToken GetToken()
+ {
+ return methodBuilder.GetToken();
+ }
+
+ public override MethodBody GetMethodBody()
+ {
+ return methodBuilder.GetMethodBody();
+ }
+
+ public bool InitLocals
+ {
+ get { return methodBuilder.InitLocals; }
+ set { methodBuilder.InitLocals = value; }
+ }
+
+ internal override MethodInfo GetMethodInfo()
+ {
+ return methodBuilder;
+ }
+
+ internal override MethodInfo GetMethodOnTypeDefinition()
+ {
+ return methodBuilder;
+ }
+
+ internal override MethodSignature MethodSignature
+ {
+ get { return methodBuilder.MethodSignature; }
+ }
+
+ internal override int ImportTo(ModuleBuilder module)
+ {
+ return module.ImportMember(methodBuilder);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class CustomAttributeBuilder
+ {
+ private readonly ConstructorInfo con;
+ private readonly byte[] blob;
+ private readonly object[] constructorArgs;
+ private readonly PropertyInfo[] namedProperties;
+ private readonly object[] propertyValues;
+ private readonly FieldInfo[] namedFields;
+ private readonly object[] fieldValues;
+
+ internal CustomAttributeBuilder(ConstructorInfo con, byte[] blob)
+ {
+ this.con = con;
+ this.blob = blob;
+ }
+
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs)
+ : this(con, constructorArgs, null, null, null,null)
+ {
+ }
+
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, FieldInfo[] namedFields, object[] fieldValues)
+ : this(con, constructorArgs, null, null, namedFields, fieldValues)
+ {
+ }
+
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues)
+ : this(con, constructorArgs, namedProperties, propertyValues, null, null)
+ {
+ }
+
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues)
+ {
+ this.con = con;
+ this.constructorArgs = constructorArgs;
+ this.namedProperties = namedProperties;
+ this.propertyValues = propertyValues;
+ this.namedFields = namedFields;
+ this.fieldValues = fieldValues;
+ }
+
+ private sealed class BlobWriter
+ {
+ private readonly ModuleBuilder moduleBuilder;
+ private readonly CustomAttributeBuilder cab;
+ private readonly ByteBuffer bb;
+
+ internal BlobWriter(ModuleBuilder moduleBuilder, CustomAttributeBuilder cab, ByteBuffer bb)
+ {
+ this.moduleBuilder = moduleBuilder;
+ this.cab = cab;
+ this.bb = bb;
+ }
+
+ internal void WriteCustomAttributeBlob()
+ {
+ // prolog
+ WriteUInt16(1);
+ ParameterInfo[] pi = cab.con.GetParameters();
+ for (int i = 0; i < pi.Length; i++)
+ {
+ WriteFixedArg(pi[i].ParameterType, cab.constructorArgs[i]);
+ }
+ WriteNamedArguments(false);
+ }
+
+ internal void WriteNamedArguments(bool forDeclSecurity)
+ {
+ // NumNamed
+ int named = 0;
+ if (cab.namedFields != null)
+ {
+ named += cab.namedFields.Length;
+ }
+ if (cab.namedProperties != null)
+ {
+ named += cab.namedProperties.Length;
+ }
+ if (forDeclSecurity)
+ {
+ WritePackedLen(named);
+ }
+ else
+ {
+ WriteUInt16((ushort)named);
+ }
+ if (cab.namedFields != null)
+ {
+ for (int i = 0; i < cab.namedFields.Length; i++)
+ {
+ WriteNamedArg(0x53, cab.namedFields[i].FieldType, cab.namedFields[i].Name, cab.fieldValues[i]);
+ }
+ }
+ if (cab.namedProperties != null)
+ {
+ for (int i = 0; i < cab.namedProperties.Length; i++)
+ {
+ WriteNamedArg(0x54, cab.namedProperties[i].PropertyType, cab.namedProperties[i].Name, cab.propertyValues[i]);
+ }
+ }
+ }
+
+ private void WriteNamedArg(byte fieldOrProperty, Type type, string name, object value)
+ {
+ WriteByte(fieldOrProperty);
+ WriteFieldOrPropType(type);
+ WriteString(name);
+ WriteFixedArg(type, value);
+ }
+
+ private void WriteByte(byte value)
+ {
+ bb.Write(value);
+ }
+
+ private void WriteUInt16(ushort value)
+ {
+ bb.Write(value);
+ }
+
+ private void WriteInt32(int value)
+ {
+ bb.Write(value);
+ }
+
+ private void WriteFixedArg(Type type, object value)
+ {
+ Universe u = moduleBuilder.universe;
+ if (type == u.System_String)
+ {
+ WriteString((string)value);
+ }
+ else if (type == u.System_Type)
+ {
+ WriteTypeName((Type)value);
+ }
+ else if (type == u.System_Object)
+ {
+ if (value == null)
+ {
+ type = u.System_String;
+ }
+ else if (value is Type)
+ {
+ // value.GetType() would return a subclass of Type, but we don't want to deal with that
+ type = u.System_Type;
+ }
+ else
+ {
+ type = u.Import(value.GetType());
+ }
+ WriteFieldOrPropType(type);
+ WriteFixedArg(type, value);
+ }
+ else if (type.IsArray)
+ {
+ if (value == null)
+ {
+ WriteInt32(-1);
+ }
+ else
+ {
+ Array array = (Array)value;
+ Type elemType = type.GetElementType();
+ WriteInt32(array.Length);
+ foreach (object val in array)
+ {
+ WriteFixedArg(elemType, val);
+ }
+ }
+ }
+ else if (type.IsEnum)
+ {
+ WriteFixedArg(type.GetEnumUnderlyingTypeImpl(), value);
+ }
+ else
+ {
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.Boolean:
+ WriteByte((bool)value ? (byte)1 : (byte)0);
+ break;
+ case TypeCode.Char:
+ WriteUInt16((char)value);
+ break;
+ case TypeCode.SByte:
+ WriteByte((byte)(sbyte)value);
+ break;
+ case TypeCode.Byte:
+ WriteByte((byte)value);
+ break;
+ case TypeCode.Int16:
+ WriteUInt16((ushort)(short)value);
+ break;
+ case TypeCode.UInt16:
+ WriteUInt16((ushort)value);
+ break;
+ case TypeCode.Int32:
+ WriteInt32((int)value);
+ break;
+ case TypeCode.UInt32:
+ WriteInt32((int)(uint)value);
+ break;
+ case TypeCode.Int64:
+ WriteInt64((long)value);
+ break;
+ case TypeCode.UInt64:
+ WriteInt64((long)(ulong)value);
+ break;
+ case TypeCode.Single:
+ WriteSingle((float)value);
+ break;
+ case TypeCode.Double:
+ WriteDouble((double)value);
+ break;
+ default:
+ throw new ArgumentException();
+ }
+ }
+ }
+
+ private void WriteInt64(long value)
+ {
+ bb.Write(value);
+ }
+
+ private void WriteSingle(float value)
+ {
+ bb.Write(value);
+ }
+
+ private void WriteDouble(double value)
+ {
+ bb.Write(value);
+ }
+
+ private void WriteTypeName(Type type)
+ {
+ string name = null;
+ if (type != null)
+ {
+ if (type.Assembly == moduleBuilder.Assembly)
+ {
+ name = type.FullName;
+ }
+ else
+ {
+ name = type.AssemblyQualifiedName;
+ }
+ }
+ WriteString(name);
+ }
+
+ private void WriteString(string val)
+ {
+ bb.Write(val);
+ }
+
+ private void WritePackedLen(int len)
+ {
+ bb.WriteCompressedInt(len);
+ }
+
+ private void WriteFieldOrPropType(Type type)
+ {
+ Universe u = type.Module.universe;
+ if (type == u.System_Type)
+ {
+ WriteByte(0x50);
+ }
+ else if (type == u.System_Object)
+ {
+ WriteByte(0x51);
+ }
+ else if (type.IsArray)
+ {
+ WriteByte(0x1D);
+ WriteFieldOrPropType(type.GetElementType());
+ }
+ else if (type.IsEnum)
+ {
+ WriteByte(0x55);
+ WriteTypeName(type);
+ }
+ else
+ {
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.Boolean:
+ WriteByte(0x02);
+ break;
+ case TypeCode.Char:
+ WriteByte(0x03);
+ break;
+ case TypeCode.SByte:
+ WriteByte(0x04);
+ break;
+ case TypeCode.Byte:
+ WriteByte(0x05);
+ break;
+ case TypeCode.Int16:
+ WriteByte(0x06);
+ break;
+ case TypeCode.UInt16:
+ WriteByte(0x07);
+ break;
+ case TypeCode.Int32:
+ WriteByte(0x08);
+ break;
+ case TypeCode.UInt32:
+ WriteByte(0x09);
+ break;
+ case TypeCode.Int64:
+ WriteByte(0x0A);
+ break;
+ case TypeCode.UInt64:
+ WriteByte(0x0B);
+ break;
+ case TypeCode.Single:
+ WriteByte(0x0C);
+ break;
+ case TypeCode.Double:
+ WriteByte(0x0D);
+ break;
+ case TypeCode.String:
+ WriteByte(0x0E);
+ break;
+ default:
+ throw new ArgumentException();
+ }
+ }
+ }
+ }
+
+ internal bool IsPseudoCustomAttribute
+ {
+ get { return con.DeclaringType.IsPseudoCustomAttribute; }
+ }
+
+ internal ConstructorInfo Constructor
+ {
+ get { return con; }
+ }
+
+ internal int WriteBlob(ModuleBuilder moduleBuilder)
+ {
+ ByteBuffer bb = new ByteBuffer(100);
+ if (blob != null)
+ {
+ bb.Write(blob);
+ }
+ else
+ {
+ BlobWriter bw = new BlobWriter(moduleBuilder, this, bb);
+ bw.WriteCustomAttributeBlob();
+ }
+ return moduleBuilder.Blobs.Add(bb);
+ }
+
+ internal object GetConstructorArgument(int pos)
+ {
+ return constructorArgs[pos];
+ }
+
+ internal int ConstructorArgumentCount
+ {
+ get { return constructorArgs == null ? 0 : constructorArgs.Length; }
+ }
+
+ internal T? GetFieldValue<T>(string name) where T : struct
+ {
+ object val = GetFieldValue(name);
+ if (val is T)
+ {
+ return (T)val;
+ }
+ else if (val != null)
+ {
+ if (typeof(T).IsEnum)
+ {
+ Debug.Assert(Enum.GetUnderlyingType(typeof(T)) == val.GetType());
+ return (T)Enum.ToObject(typeof(T), val);
+ }
+ else
+ {
+ Debug.Assert(Enum.GetUnderlyingType(val.GetType()) == typeof(T));
+ return (T)Convert.ChangeType(val, typeof(T));
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ internal object GetFieldValue(string name)
+ {
+ if (namedFields != null)
+ {
+ for (int i = 0; i < namedFields.Length; i++)
+ {
+ if (namedFields[i].Name == name)
+ {
+ return fieldValues[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ internal void WriteNamedArgumentsForDeclSecurity(ModuleBuilder moduleBuilder, ByteBuffer bb)
+ {
+ BlobWriter bw = new BlobWriter(moduleBuilder, this, bb);
+ bw.WriteNamedArguments(true);
+ }
+
+ internal CustomAttributeData ToData(Assembly asm)
+ {
+ if (blob != null)
+ {
+ return new CustomAttributeData(asm, con, new IKVM.Reflection.Reader.ByteReader(blob, 0, blob.Length));
+ }
+ else
+ {
+ List<CustomAttributeNamedArgument> namedArgs = new List<CustomAttributeNamedArgument>();
+ if (namedProperties != null)
+ {
+ for (int i = 0; i < namedProperties.Length; i++)
+ {
+ namedArgs.Add(new CustomAttributeNamedArgument(namedProperties[i], new CustomAttributeTypedArgument(namedProperties[i].PropertyType, propertyValues[i])));
+ }
+ }
+ if (namedFields != null)
+ {
+ for (int i = 0; i < namedFields.Length; i++)
+ {
+ namedArgs.Add(new CustomAttributeNamedArgument(namedFields[i], new CustomAttributeTypedArgument(namedFields[i].FieldType, fieldValues[i])));
+ }
+ }
+ return new CustomAttributeData(con, constructorArgs, namedArgs);
+ }
+ }
+
+ internal bool HasBlob
+ {
+ get { return blob != null; }
+ }
+
+ internal CustomAttributeBuilder DecodeBlob(Assembly asm)
+ {
+ if (blob == null)
+ {
+ return this;
+ }
+ else
+ {
+ return ToData(asm).__ToBuilder();
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class EnumBuilder : Type
+ {
+ private readonly TypeBuilder typeBuilder;
+ private readonly FieldBuilder fieldBuilder;
+
+ internal EnumBuilder(TypeBuilder typeBuilder, FieldBuilder fieldBuilder)
+ {
+ this.typeBuilder = typeBuilder;
+ this.fieldBuilder = fieldBuilder;
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get { return typeBuilder.UnderlyingSystemType; }
+ }
+
+ public override Type BaseType
+ {
+ get { return typeBuilder.BaseType; }
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return typeBuilder.Attributes; }
+ }
+
+ public override Module Module
+ {
+ get { return typeBuilder.Module; }
+ }
+
+ public FieldBuilder DefineLiteral(string literalName, object literalValue)
+ {
+ FieldBuilder fb = typeBuilder.DefineField(literalName, typeBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
+ fb.SetConstant(literalValue);
+ return fb;
+ }
+
+ public Type CreateType()
+ {
+ return typeBuilder.CreateType();
+ }
+
+ public TypeToken TypeToken
+ {
+ get { return typeBuilder.TypeToken; }
+ }
+
+ public FieldBuilder UnderlyingField
+ {
+ get { return fieldBuilder; }
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ typeBuilder.SetCustomAttribute(con, binaryAttribute);
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ typeBuilder.SetCustomAttribute(customBuilder);
+ }
+
+ public override Type GetEnumUnderlyingType()
+ {
+ return fieldBuilder.FieldType;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+
+namespace IKVM.Reflection.Emit
+{
+ public enum AssemblyBuilderAccess
+ {
+ Save = 2,
+ ReflectionOnly = 6,
+ }
+
+ public enum OpCodeType
+ {
+ Annotation = 0,
+ Macro = 1,
+ Nternal = 2,
+ Objmodel = 3,
+ Prefix = 4,
+ Primitive = 5,
+ }
+
+ public enum OperandType
+ {
+ InlineBrTarget = 0,
+ InlineField = 1,
+ InlineI = 2,
+ InlineI8 = 3,
+ InlineMethod = 4,
+ InlineNone = 5,
+ InlinePhi = 6,
+ InlineR = 7,
+ InlineSig = 9,
+ InlineString = 10,
+ InlineSwitch = 11,
+ InlineTok = 12,
+ InlineType = 13,
+ InlineVar = 14,
+ ShortInlineBrTarget = 15,
+ ShortInlineI = 16,
+ ShortInlineR = 17,
+ ShortInlineVar = 18,
+ }
+
+ public enum FlowControl
+ {
+ Branch = 0,
+ Break = 1,
+ Call = 2,
+ Cond_Branch = 3,
+ Meta = 4,
+ Next = 5,
+ Return = 7,
+ Throw = 8,
+ }
+
+ public enum PackingSize
+ {
+ Unspecified = 0,
+ Size1 = 1,
+ Size2 = 2,
+ Size4 = 4,
+ Size8 = 8,
+ Size16 = 16,
+ Size32 = 32,
+ Size64 = 64,
+ Size128 = 128,
+ }
+
+ public enum PEFileKinds
+ {
+ Dll = 1,
+ ConsoleApplication = 2,
+ WindowApplication = 3,
+ }
+
+ public enum StackBehaviour
+ {
+ Pop0 = 0,
+ Pop1 = 1,
+ Pop1_pop1 = 2,
+ Popi = 3,
+ Popi_pop1 = 4,
+ Popi_popi = 5,
+ Popi_popi8 = 6,
+ Popi_popi_popi = 7,
+ Popi_popr4 = 8,
+ Popi_popr8 = 9,
+ Popref = 10,
+ Popref_pop1 = 11,
+ Popref_popi = 12,
+ Popref_popi_popi = 13,
+ Popref_popi_popi8 = 14,
+ Popref_popi_popr4 = 15,
+ Popref_popi_popr8 = 16,
+ Popref_popi_popref = 17,
+ Push0 = 18,
+ Push1 = 19,
+ Push1_push1 = 20,
+ Pushi = 21,
+ Pushi8 = 22,
+ Pushr4 = 23,
+ Pushr8 = 24,
+ Pushref = 25,
+ Varpop = 26,
+ Varpush = 27,
+ Popref_popi_pop1 = 28,
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class EventBuilder : EventInfo
+ {
+ private readonly TypeBuilder typeBuilder;
+ private readonly string name;
+ private EventAttributes attributes;
+ private readonly int eventtype;
+ private MethodBuilder addOnMethod;
+ private MethodBuilder removeOnMethod;
+ private MethodBuilder fireMethod;
+ private List<MethodBuilder> otherMethods;
+ private int lazyPseudoToken;
+
+ internal EventBuilder(TypeBuilder typeBuilder, string name, EventAttributes attributes, Type eventtype)
+ {
+ this.typeBuilder = typeBuilder;
+ this.name = name;
+ this.attributes = attributes;
+ this.eventtype = typeBuilder.ModuleBuilder.GetTypeTokenForMemberRef(eventtype);
+ }
+
+ public void SetAddOnMethod(MethodBuilder mdBuilder)
+ {
+ addOnMethod = mdBuilder;
+ }
+
+ public void SetRemoveOnMethod(MethodBuilder mdBuilder)
+ {
+ removeOnMethod = mdBuilder;
+ }
+
+ public void SetRaiseMethod(MethodBuilder mdBuilder)
+ {
+ fireMethod = mdBuilder;
+ }
+
+ public void AddOtherMethod(MethodBuilder mdBuilder)
+ {
+ if (otherMethods == null)
+ {
+ otherMethods = new List<MethodBuilder>();
+ }
+ otherMethods.Add(mdBuilder);
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ Universe u = typeBuilder.ModuleBuilder.universe;
+ if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+ {
+ attributes |= EventAttributes.SpecialName;
+ }
+ else
+ {
+ if (lazyPseudoToken == 0)
+ {
+ lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+ }
+ typeBuilder.ModuleBuilder.SetCustomAttribute(lazyPseudoToken, customBuilder);
+ }
+ }
+
+ public override EventAttributes Attributes
+ {
+ get { return attributes; }
+ }
+
+ public override MethodInfo GetAddMethod(bool nonPublic)
+ {
+ return nonPublic || (addOnMethod != null && addOnMethod.IsPublic) ? addOnMethod : null;
+ }
+
+ public override MethodInfo GetRemoveMethod(bool nonPublic)
+ {
+ return nonPublic || (removeOnMethod != null && removeOnMethod.IsPublic) ? removeOnMethod : null;
+ }
+
+ public override MethodInfo GetRaiseMethod(bool nonPublic)
+ {
+ return nonPublic || (fireMethod != null && fireMethod.IsPublic) ? fireMethod : null;
+ }
+
+ public override MethodInfo[] GetOtherMethods(bool nonPublic)
+ {
+ List<MethodInfo> list = new List<MethodInfo>();
+ if (otherMethods != null)
+ {
+ foreach (MethodInfo method in otherMethods)
+ {
+ if (nonPublic || method.IsPublic)
+ {
+ list.Add(method);
+ }
+ }
+ }
+ return list.ToArray();
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeBuilder; }
+ }
+
+ public override string Name
+ {
+ get { return name; }
+ }
+
+ public override Module Module
+ {
+ get { return typeBuilder.ModuleBuilder; }
+ }
+
+ public EventToken GetEventToken()
+ {
+ if (lazyPseudoToken == 0)
+ {
+ lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+ }
+ return new EventToken(lazyPseudoToken);
+ }
+
+ public override Type EventHandlerType
+ {
+ get { return typeBuilder.ModuleBuilder.ResolveType(eventtype); }
+ }
+
+ internal void Bake()
+ {
+ EventTable.Record rec = new EventTable.Record();
+ rec.EventFlags = (short)attributes;
+ rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name);
+ rec.EventType = eventtype;
+ int token = 0x14000000 | typeBuilder.ModuleBuilder.Event.AddRecord(rec);
+
+ if (lazyPseudoToken != 0)
+ {
+ typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token);
+ }
+
+ if (addOnMethod != null)
+ {
+ AddMethodSemantics(MethodSemanticsTable.AddOn, addOnMethod.MetadataToken, token);
+ }
+ if (removeOnMethod != null)
+ {
+ AddMethodSemantics(MethodSemanticsTable.RemoveOn, removeOnMethod.MetadataToken, token);
+ }
+ if (fireMethod != null)
+ {
+ AddMethodSemantics(MethodSemanticsTable.Fire, fireMethod.MetadataToken, token);
+ }
+ if (otherMethods != null)
+ {
+ foreach (MethodBuilder method in otherMethods)
+ {
+ AddMethodSemantics(MethodSemanticsTable.Other, method.MetadataToken, token);
+ }
+ }
+ }
+
+ private void AddMethodSemantics(short semantics, int methodToken, int propertyToken)
+ {
+ MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record();
+ rec.Semantics = semantics;
+ rec.Method = methodToken;
+ rec.Association = propertyToken;
+ typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec);
+ }
+
+ internal override bool IsPublic
+ {
+ get
+ {
+ if ((addOnMethod != null && addOnMethod.IsPublic) || (removeOnMethod != null && removeOnMethod.IsPublic) || (fireMethod != null && fireMethod.IsPublic))
+ {
+ return true;
+ }
+ if (otherMethods != null)
+ {
+ foreach (MethodBuilder method in otherMethods)
+ {
+ if (method.IsPublic)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ internal override bool IsStatic
+ {
+ get
+ {
+ if ((addOnMethod != null && addOnMethod.IsStatic) || (removeOnMethod != null && removeOnMethod.IsStatic) || (fireMethod != null && fireMethod.IsStatic))
+ {
+ return true;
+ }
+ if (otherMethods != null)
+ {
+ foreach (MethodBuilder method in otherMethods)
+ {
+ if (method.IsStatic)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Runtime.CompilerServices;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class FieldBuilder : FieldInfo
+ {
+ private readonly TypeBuilder typeBuilder;
+ private readonly string name;
+ private readonly int pseudoToken;
+ private FieldAttributes attribs;
+ private readonly int nameIndex;
+ private readonly int signature;
+ private readonly FieldSignature fieldSig;
+
+ internal FieldBuilder(TypeBuilder type, string name, Type fieldType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attribs)
+ {
+ this.typeBuilder = type;
+ this.name = name;
+ this.pseudoToken = type.ModuleBuilder.AllocPseudoToken();
+ this.nameIndex = type.ModuleBuilder.Strings.Add(name);
+ this.fieldSig = FieldSignature.Create(fieldType, optionalCustomModifiers, requiredCustomModifiers);
+ ByteBuffer sig = new ByteBuffer(5);
+ fieldSig.WriteSig(this.typeBuilder.ModuleBuilder, sig);
+ this.signature = this.typeBuilder.ModuleBuilder.Blobs.Add(sig);
+ this.attribs = attribs;
+ this.typeBuilder.ModuleBuilder.Field.AddVirtualRecord();
+ }
+
+ public void SetConstant(object defaultValue)
+ {
+ attribs |= FieldAttributes.HasDefault;
+ typeBuilder.ModuleBuilder.AddConstant(pseudoToken, defaultValue);
+ }
+
+ public override object GetRawConstantValue()
+ {
+ return typeBuilder.Module.Constant.GetRawConstantValue(typeBuilder.Module, this.MetadataToken);
+ }
+
+ public void __SetDataAndRVA(byte[] data)
+ {
+ attribs |= FieldAttributes.HasFieldRVA;
+ FieldRVATable.Record rec = new FieldRVATable.Record();
+ rec.RVA = typeBuilder.ModuleBuilder.initializedData.Position;
+ rec.Field = pseudoToken;
+ typeBuilder.ModuleBuilder.FieldRVA.AddRecord(rec);
+ typeBuilder.ModuleBuilder.initializedData.Write(data);
+ }
+
+ public override void __GetDataFromRVA(byte[] data, int offset, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ Universe u = this.Module.universe;
+ if (customBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_FieldOffsetAttribute)
+ {
+ customBuilder = customBuilder.DecodeBlob(this.Module.Assembly);
+ SetOffset((int)customBuilder.GetConstructorArgument(0));
+ }
+ else if (customBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_MarshalAsAttribute)
+ {
+ MarshalSpec.SetMarshalAsAttribute(typeBuilder.ModuleBuilder, pseudoToken, customBuilder);
+ attribs |= FieldAttributes.HasFieldMarshal;
+ }
+ else if (customBuilder.Constructor.DeclaringType == u.System_NonSerializedAttribute)
+ {
+ attribs |= FieldAttributes.NotSerialized;
+ }
+ else if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+ {
+ attribs |= FieldAttributes.SpecialName;
+ }
+ else
+ {
+ typeBuilder.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
+ }
+ }
+
+ public void SetOffset(int iOffset)
+ {
+ FieldLayoutTable.Record rec = new FieldLayoutTable.Record();
+ rec.Offset = iOffset;
+ rec.Field = pseudoToken;
+ typeBuilder.ModuleBuilder.FieldLayout.AddRecord(rec);
+ }
+
+ public override FieldAttributes Attributes
+ {
+ get { return attribs; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeBuilder.IsModulePseudoType ? null : typeBuilder; }
+ }
+
+ public override string Name
+ {
+ get { return name; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return pseudoToken; }
+ }
+
+ public override Module Module
+ {
+ get { return typeBuilder.Module; }
+ }
+
+ public FieldToken GetToken()
+ {
+ return new FieldToken(pseudoToken);
+ }
+
+ internal void WriteFieldRecords(MetadataWriter mw)
+ {
+ mw.Write((short)attribs);
+ mw.WriteStringIndex(nameIndex);
+ mw.WriteBlobIndex(signature);
+ }
+
+ internal void FixupToken(int token)
+ {
+ typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token);
+ }
+
+ internal override FieldSignature FieldSignature
+ {
+ get { return fieldSig; }
+ }
+
+ internal override int ImportTo(ModuleBuilder other)
+ {
+ if (typeBuilder.IsGenericTypeDefinition)
+ {
+ return other.ImportMember(TypeBuilder.GetField(typeBuilder, this));
+ }
+ else if (other == typeBuilder.ModuleBuilder)
+ {
+ return pseudoToken;
+ }
+ else
+ {
+ return other.ImportMethodOrField(typeBuilder, name, fieldSig);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Diagnostics.SymbolStore;
+using System.Diagnostics;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public struct Label
+ {
+ // 1-based here, to make sure that an uninitialized Label isn't valid
+ private readonly int index1;
+
+ internal Label(int index)
+ {
+ this.index1 = index + 1;
+ }
+
+ internal int Index
+ {
+ get { return index1 - 1; }
+ }
+
+ public bool Equals(Label other)
+ {
+ return other.index1 == index1;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return this == obj as Label?;
+ }
+
+ public override int GetHashCode()
+ {
+ return index1;
+ }
+
+ public static bool operator ==(Label arg1, Label arg2)
+ {
+ return arg1.index1 == arg2.index1;
+ }
+
+ public static bool operator !=(Label arg1, Label arg2)
+ {
+ return !(arg1 == arg2);
+ }
+ }
+
+ public sealed class LocalBuilder
+ {
+ private readonly Type localType;
+ private readonly int index;
+ private readonly bool pinned;
+ internal string name;
+ internal int startOffset;
+ internal int endOffset;
+
+ internal LocalBuilder(Type localType, int index, bool pinned)
+ {
+ this.localType = localType;
+ this.index = index;
+ this.pinned = pinned;
+ }
+
+ public void SetLocalSymInfo(string name)
+ {
+ this.name = name;
+ }
+
+ public void SetLocalSymInfo(string name, int startOffset, int endOffset)
+ {
+ this.name = name;
+ this.startOffset = startOffset;
+ this.endOffset = endOffset;
+ }
+
+ public Type LocalType
+ {
+ get { return localType; }
+ }
+
+ public int LocalIndex
+ {
+ get { return index; }
+ }
+
+ public bool IsPinned
+ {
+ get { return pinned; }
+ }
+ }
+
+ public sealed class ILGenerator
+ {
+ private static readonly Type FAULT = new BakedType(null); // the type we use here doesn't matter, as long as it can never be used as a real exception type
+ private readonly ModuleBuilder moduleBuilder;
+ private readonly ByteBuffer code;
+ private readonly List<LocalBuilder> locals = new List<LocalBuilder>();
+ private readonly List<int> tokenFixups = new List<int>();
+ private readonly List<int> labels = new List<int>();
+ private readonly List<int> labelStackHeight = new List<int>();
+ private readonly List<LabelFixup> labelFixups = new List<LabelFixup>();
+ private readonly List<SequencePoint> sequencePoints = new List<SequencePoint>();
+ private readonly List<ExceptionBlock> exceptions = new List<ExceptionBlock>();
+ private readonly Stack<ExceptionBlock> exceptionStack = new Stack<ExceptionBlock>();
+ private ushort maxStack;
+ private int stackHeight;
+ private Scope scope;
+ private byte exceptionBlockAssistanceMode = EBAM_COMPAT;
+ private const byte EBAM_COMPAT = 0;
+ private const byte EBAM_DISABLE = 1;
+ private const byte EBAM_CLEVER = 2;
+
+ private struct LabelFixup
+ {
+ internal int label;
+ internal int offset;
+ }
+
+ private sealed class ExceptionBlock : IComparer<ExceptionBlock>
+ {
+ internal readonly int ordinal;
+ internal Label labelEnd;
+ internal int tryOffset;
+ internal int tryLength;
+ internal int handlerOffset;
+ internal int handlerLength;
+ internal Type exceptionType; // null = finally block or handler with filter, FAULT = fault block
+ internal int filterOffset;
+
+ internal ExceptionBlock(int ordinal)
+ {
+ this.ordinal = ordinal;
+ }
+
+ int IComparer<ExceptionBlock>.Compare(ExceptionBlock x, ExceptionBlock y)
+ {
+ // Mono's sort insists on doing unnecessary comparisons
+ if (x == y)
+ {
+ return 0;
+ }
+ if (x.tryOffset >= y.handlerOffset && x.tryOffset + x.tryLength <= y.handlerOffset + y.handlerLength)
+ {
+ return -1;
+ }
+ if (y.tryOffset >= x.handlerOffset && y.tryOffset + y.tryLength <= x.handlerOffset + x.handlerLength)
+ {
+ return 1;
+ }
+ if (x.tryOffset == y.tryOffset && x.tryLength == y.tryLength)
+ {
+ return x.ordinal < y.ordinal ? -1 : 1;
+ }
+ if (x.tryOffset + x.tryLength <= y.tryOffset)
+ {
+ return -1;
+ }
+ if (y.tryOffset + y.tryLength <= x.tryOffset)
+ {
+ return 1;
+ }
+ if (x.tryOffset > y.tryOffset || (x.tryOffset == y.tryOffset && x.tryLength < y.tryLength))
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+
+ private struct SequencePoint
+ {
+ internal ISymbolDocumentWriter document;
+ internal int offset;
+ internal int startLine;
+ internal int startColumn;
+ internal int endLine;
+ internal int endColumn;
+ }
+
+ private sealed class Scope
+ {
+ internal readonly Scope parent;
+ internal readonly List<Scope> children = new List<Scope>();
+ internal readonly List<LocalBuilder> locals = new List<LocalBuilder>();
+ internal int startOffset;
+ internal int endOffset;
+
+ internal Scope(Scope parent)
+ {
+ this.parent = parent;
+ }
+ }
+
+ internal ILGenerator(ModuleBuilder moduleBuilder, int initialCapacity)
+ {
+ this.code = new ByteBuffer(initialCapacity);
+ this.moduleBuilder = moduleBuilder;
+ if (moduleBuilder.symbolWriter != null)
+ {
+ scope = new Scope(null);
+ }
+ }
+
+ private bool IsLabelReachable(Label label)
+ {
+ return labelStackHeight[label.Index] != -1;
+ }
+
+ // non-standard API
+ public void __DisableExceptionBlockAssistance()
+ {
+ exceptionBlockAssistanceMode = EBAM_DISABLE;
+ }
+
+ // non-standard API
+ public void __CleverExceptionBlockAssistance()
+ {
+ exceptionBlockAssistanceMode = EBAM_CLEVER;
+ }
+
+ // new in .NET 4.0
+ public int ILOffset
+ {
+ get { return code.Position; }
+ }
+
+ public void BeginCatchBlock(Type exceptionType)
+ {
+ ExceptionBlock block = exceptionStack.Peek();
+ if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
+ {
+ if (exceptionType == null)
+ {
+ Emit(OpCodes.Endfilter);
+ }
+ else
+ {
+ Emit(OpCodes.Leave, block.labelEnd);
+ }
+ }
+ stackHeight = 0;
+ UpdateStack(1);
+ if (block.tryLength == 0)
+ {
+ block.tryLength = code.Position - block.tryOffset;
+ }
+ else if (exceptionType != null)
+ {
+ block.handlerLength = code.Position - block.handlerOffset;
+ exceptionStack.Pop();
+ ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count);
+ newBlock.labelEnd = block.labelEnd;
+ newBlock.tryOffset = block.tryOffset;
+ newBlock.tryLength = block.tryLength;
+ block = newBlock;
+ exceptions.Add(block);
+ exceptionStack.Push(block);
+ }
+ block.handlerOffset = code.Position;
+ block.exceptionType = exceptionType;
+ }
+
+ public Label BeginExceptionBlock()
+ {
+ ExceptionBlock block = new ExceptionBlock(exceptions.Count);
+ block.labelEnd = DefineLabel();
+ block.tryOffset = code.Position;
+ exceptionStack.Push(block);
+ exceptions.Add(block);
+ return block.labelEnd;
+ }
+
+ public void BeginExceptFilterBlock()
+ {
+ ExceptionBlock block = BeginFinallyFilterFaultBlock();
+ block.filterOffset = code.Position;
+ UpdateStack(1);
+ }
+
+ public void BeginFaultBlock()
+ {
+ ExceptionBlock block = BeginFinallyFilterFaultBlock();
+ block.handlerOffset = code.Position;
+ block.exceptionType = FAULT;
+ }
+
+ public void BeginFinallyBlock()
+ {
+ ExceptionBlock block = BeginFinallyFilterFaultBlock();
+ block.handlerOffset = code.Position;
+ }
+
+ private ExceptionBlock BeginFinallyFilterFaultBlock()
+ {
+ ExceptionBlock block = exceptionStack.Peek();
+ if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
+ {
+ Emit(OpCodes.Leave, block.labelEnd);
+ }
+ if (block.handlerOffset == 0)
+ {
+ block.tryLength = code.Position - block.tryOffset;
+ }
+ else
+ {
+ block.handlerLength = code.Position - block.handlerOffset;
+ Label labelEnd;
+ if (exceptionBlockAssistanceMode != EBAM_COMPAT)
+ {
+ labelEnd = block.labelEnd;
+ }
+ else
+ {
+ MarkLabel(block.labelEnd);
+ labelEnd = DefineLabel();
+ Emit(OpCodes.Leave, labelEnd);
+ }
+ exceptionStack.Pop();
+ ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count);
+ newBlock.labelEnd = labelEnd;
+ newBlock.tryOffset = block.tryOffset;
+ newBlock.tryLength = code.Position - block.tryOffset;
+ block = newBlock;
+ exceptions.Add(block);
+ exceptionStack.Push(block);
+ }
+ stackHeight = 0;
+ return block;
+ }
+
+ public void EndExceptionBlock()
+ {
+ ExceptionBlock block = exceptionStack.Pop();
+ if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
+ {
+ if (block.filterOffset != 0 || (block.exceptionType != null && block.exceptionType != FAULT))
+ {
+ Emit(OpCodes.Leave, block.labelEnd);
+ }
+ else
+ {
+ Emit(OpCodes.Endfinally);
+ }
+ }
+ MarkLabel(block.labelEnd);
+ block.handlerLength = code.Position - block.handlerOffset;
+ }
+
+ public void BeginScope()
+ {
+ Scope newScope = new Scope(scope);
+ scope.children.Add(newScope);
+ scope = newScope;
+ scope.startOffset = code.Position;
+ }
+
+ public void UsingNamespace(string usingNamespace)
+ {
+ if (moduleBuilder.symbolWriter != null)
+ {
+ moduleBuilder.symbolWriter.UsingNamespace(usingNamespace);
+ }
+ }
+
+ public LocalBuilder DeclareLocal(Type localType)
+ {
+ return DeclareLocal(localType, false);
+ }
+
+ public LocalBuilder DeclareLocal(Type localType, bool pinned)
+ {
+ LocalBuilder local = new LocalBuilder(localType, locals.Count, pinned);
+ locals.Add(local);
+ if (scope != null)
+ {
+ scope.locals.Add(local);
+ }
+ return local;
+ }
+
+ public Label DefineLabel()
+ {
+ Label label = new Label(labels.Count);
+ labels.Add(-1);
+ labelStackHeight.Add(-1);
+ return label;
+ }
+
+ public void Emit(OpCode opc)
+ {
+ Debug.Assert(opc != OpCodes.Ret || (opc == OpCodes.Ret && stackHeight <= 1));
+ if (opc.Value < 0)
+ {
+ code.Write((byte)(opc.Value >> 8));
+ }
+ code.Write((byte)opc.Value);
+ switch (opc.FlowControl)
+ {
+ case FlowControl.Branch:
+ case FlowControl.Break:
+ case FlowControl.Return:
+ case FlowControl.Throw:
+ stackHeight = -1;
+ break;
+ default:
+ UpdateStack(opc.StackDiff);
+ break;
+ }
+ }
+
+ private void UpdateStack(int stackdiff)
+ {
+ if (stackHeight == -1)
+ {
+ // we're about to emit code that is either unreachable or reachable only via a backward branch
+ stackHeight = 0;
+ }
+ Debug.Assert(stackHeight >= 0 && stackHeight <= ushort.MaxValue);
+ stackHeight += stackdiff;
+ Debug.Assert(stackHeight >= 0 && stackHeight <= ushort.MaxValue);
+ maxStack = Math.Max(maxStack, (ushort)stackHeight);
+ }
+
+ public void Emit(OpCode opc, byte arg)
+ {
+ Emit(opc);
+ code.Write(arg);
+ }
+
+ public void Emit(OpCode opc, double arg)
+ {
+ Emit(opc);
+ code.Write(arg);
+ }
+
+ public void Emit(OpCode opc, FieldInfo field)
+ {
+ Emit(opc);
+ WriteToken(moduleBuilder.GetFieldToken(field));
+ }
+
+ public void Emit(OpCode opc, short arg)
+ {
+ Emit(opc);
+ code.Write(arg);
+ }
+
+ public void Emit(OpCode opc, int arg)
+ {
+ Emit(opc);
+ code.Write(arg);
+ }
+
+ public void Emit(OpCode opc, long arg)
+ {
+ Emit(opc);
+ code.Write(arg);
+ }
+
+ public void Emit(OpCode opc, Label label)
+ {
+ // We need special stackHeight handling for unconditional branches,
+ // because the branch and next flows have differing stack heights.
+ // Note that this assumes that unconditional branches do not push/pop.
+ int flowStackHeight = this.stackHeight;
+ Emit(opc);
+ if (opc == OpCodes.Leave || opc == OpCodes.Leave_S)
+ {
+ flowStackHeight = 0;
+ }
+ else if (opc.FlowControl != FlowControl.Branch)
+ {
+ flowStackHeight = this.stackHeight;
+ }
+ // if the label has already been marked, we can emit the branch offset directly
+ if (labels[label.Index] != -1)
+ {
+ if (labelStackHeight[label.Index] != flowStackHeight && (labelStackHeight[label.Index] != 0 || flowStackHeight != -1))
+ {
+ // the "backward branch constraint" prohibits this, so we don't need to support it
+ throw new NotSupportedException("'Backward branch constraints' violated");
+ }
+ if (opc.OperandType == OperandType.ShortInlineBrTarget)
+ {
+ WriteByteBranchOffset(labels[label.Index] - (code.Position + 1));
+ }
+ else
+ {
+ code.Write(labels[label.Index] - (code.Position + 4));
+ }
+ }
+ else
+ {
+ Debug.Assert(labelStackHeight[label.Index] == -1 || labelStackHeight[label.Index] == flowStackHeight || (flowStackHeight == -1 && labelStackHeight[label.Index] == 0));
+ labelStackHeight[label.Index] = flowStackHeight;
+ LabelFixup fix = new LabelFixup();
+ fix.label = label.Index;
+ fix.offset = code.Position;
+ labelFixups.Add(fix);
+ if (opc.OperandType == OperandType.ShortInlineBrTarget)
+ {
+ code.Write((byte)1);
+ }
+ else
+ {
+ code.Write(4);
+ }
+ }
+ }
+
+ private void WriteByteBranchOffset(int offset)
+ {
+ if (offset < -128 || offset > 127)
+ {
+ throw new NotSupportedException("Branch offset of " + offset + " does not fit in one-byte branch target at position " + code.Position);
+ }
+ code.Write((byte)offset);
+ }
+
+ public void Emit(OpCode opc, Label[] labels)
+ {
+ Emit(opc);
+ LabelFixup fix = new LabelFixup();
+ fix.label = -1;
+ fix.offset = code.Position;
+ labelFixups.Add(fix);
+ code.Write(labels.Length);
+ foreach (Label label in labels)
+ {
+ code.Write(label.Index);
+ if (this.labels[label.Index] != -1)
+ {
+ if (labelStackHeight[label.Index] != stackHeight)
+ {
+ // the "backward branch constraint" prohibits this, so we don't need to support it
+ throw new NotSupportedException();
+ }
+ }
+ else
+ {
+ Debug.Assert(labelStackHeight[label.Index] == -1 || labelStackHeight[label.Index] == stackHeight);
+ labelStackHeight[label.Index] = stackHeight;
+ }
+ }
+ }
+
+ public void Emit(OpCode opc, LocalBuilder local)
+ {
+ if ((opc == OpCodes.Ldloc || opc == OpCodes.Ldloca || opc == OpCodes.Stloc) && local.LocalIndex < 256)
+ {
+ if (opc == OpCodes.Ldloc)
+ {
+ switch (local.LocalIndex)
+ {
+ case 0:
+ Emit(OpCodes.Ldloc_0);
+ break;
+ case 1:
+ Emit(OpCodes.Ldloc_1);
+ break;
+ case 2:
+ Emit(OpCodes.Ldloc_2);
+ break;
+ case 3:
+ Emit(OpCodes.Ldloc_3);
+ break;
+ default:
+ Emit(OpCodes.Ldloc_S);
+ code.Write((byte)local.LocalIndex);
+ break;
+ }
+ }
+ else if (opc == OpCodes.Ldloca)
+ {
+ Emit(OpCodes.Ldloca_S);
+ code.Write((byte)local.LocalIndex);
+ }
+ else if (opc == OpCodes.Stloc)
+ {
+ switch (local.LocalIndex)
+ {
+ case 0:
+ Emit(OpCodes.Stloc_0);
+ break;
+ case 1:
+ Emit(OpCodes.Stloc_1);
+ break;
+ case 2:
+ Emit(OpCodes.Stloc_2);
+ break;
+ case 3:
+ Emit(OpCodes.Stloc_3);
+ break;
+ default:
+ Emit(OpCodes.Stloc_S);
+ code.Write((byte)local.LocalIndex);
+ break;
+ }
+ }
+ }
+ else
+ {
+ Emit(opc);
+ switch (opc.OperandType)
+ {
+ case OperandType.InlineVar:
+ code.Write((ushort)local.LocalIndex);
+ break;
+ case OperandType.ShortInlineVar:
+ code.Write((byte)local.LocalIndex);
+ break;
+ }
+ }
+ }
+
+ private void WriteToken(FieldToken token)
+ {
+ if (token.IsPseudoToken)
+ {
+ tokenFixups.Add(code.Position);
+ }
+ code.Write(token.Token);
+ }
+
+ private void WriteToken(MethodToken token)
+ {
+ if (token.IsPseudoToken)
+ {
+ tokenFixups.Add(code.Position);
+ }
+ code.Write(token.Token);
+ }
+
+ private void UpdateStack(OpCode opc, bool hasthis, Type returnType, int parameterCount)
+ {
+ if (opc == OpCodes.Jmp)
+ {
+ stackHeight = -1;
+ }
+ else if (opc.FlowControl == FlowControl.Call)
+ {
+ int stackdiff = 0;
+ if ((hasthis && opc != OpCodes.Newobj) || opc == OpCodes.Calli)
+ {
+ // pop this
+ stackdiff--;
+ }
+ // pop parameters
+ stackdiff -= parameterCount;
+ if (returnType != moduleBuilder.universe.System_Void)
+ {
+ // push return value
+ stackdiff++;
+ }
+ UpdateStack(stackdiff);
+ }
+ }
+
+ public void Emit(OpCode opc, MethodInfo method)
+ {
+ Emit(opc);
+ WriteToken(moduleBuilder.GetMethodTokenForIL(method));
+ UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount);
+ }
+
+ public void Emit(OpCode opc, ConstructorInfo constructor)
+ {
+ Emit(opc, constructor.GetMethodInfo());
+ }
+
+ public void Emit(OpCode opc, sbyte arg)
+ {
+ Emit(opc);
+ code.Write(arg);
+ }
+
+ public void Emit(OpCode opc, float arg)
+ {
+ Emit(opc);
+ code.Write(arg);
+ }
+
+ public void Emit(OpCode opc, string str)
+ {
+ Emit(opc);
+ code.Write(0x70000000 | moduleBuilder.UserStrings.Add(str));
+ }
+
+ public void Emit(OpCode opc, Type type)
+ {
+ Emit(opc);
+ if (opc == OpCodes.Ldtoken)
+ {
+ code.Write(moduleBuilder.GetTypeToken(type).Token);
+ }
+ else
+ {
+ code.Write(moduleBuilder.GetTypeTokenForMemberRef(type));
+ }
+ }
+
+ public void Emit(OpCode opcode, SignatureHelper signature)
+ {
+ Emit(opcode);
+ UpdateStack(opcode, signature.HasThis, signature.ReturnType, signature.ParameterCount);
+ code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(signature.GetSignature(moduleBuilder))));
+ }
+
+ public void EmitCall(OpCode opc, MethodInfo method, Type[] optionalParameterTypes)
+ {
+ if (optionalParameterTypes == null || optionalParameterTypes.Length == 0)
+ {
+ Emit(opc, method);
+ }
+ else
+ {
+ Emit(opc);
+ UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount + optionalParameterTypes.Length);
+ ByteBuffer sig = new ByteBuffer(16);
+ method.MethodSignature.WriteMethodRefSig(moduleBuilder, sig, optionalParameterTypes);
+ MemberRefTable.Record record = new MemberRefTable.Record();
+ if (method.Module == moduleBuilder)
+ {
+ record.Class = method.MetadataToken;
+ }
+ else
+ {
+ record.Class = moduleBuilder.GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
+ }
+ record.Name = moduleBuilder.Strings.Add(method.Name);
+ record.Signature = moduleBuilder.Blobs.Add(sig);
+ code.Write(0x0A000000 | moduleBuilder.MemberRef.FindOrAddRecord(record));
+ }
+ }
+
+ public void __EmitCall(OpCode opc, ConstructorInfo constructor, Type[] optionalParameterTypes)
+ {
+ EmitCall(opc, constructor.GetMethodInfo(), optionalParameterTypes);
+ }
+
+ public void EmitCalli(OpCode opc, CallingConvention callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ returnType = returnType ?? moduleBuilder.universe.System_Void;
+ Emit(opc);
+ UpdateStack(opc, false, returnType, parameterTypes.Length);
+ ByteBuffer sig = new ByteBuffer(16);
+ Signature.WriteStandAloneMethodSig(moduleBuilder, sig, callingConvention, returnType, parameterTypes);
+ code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(sig)));
+ }
+
+ public void EmitCalli(OpCode opc, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+ {
+ returnType = returnType ?? moduleBuilder.universe.System_Void;
+ optionalParameterTypes = optionalParameterTypes ?? Type.EmptyTypes;
+ Emit(opc);
+ UpdateStack(opc, (callingConvention & CallingConventions.HasThis | CallingConventions.ExplicitThis) == CallingConventions.HasThis, returnType, parameterTypes.Length + optionalParameterTypes.Length);
+ ByteBuffer sig = new ByteBuffer(16);
+ Signature.WriteStandAloneMethodSig(moduleBuilder, sig, callingConvention, returnType, parameterTypes, optionalParameterTypes);
+ code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(sig)));
+ }
+
+ public void EmitWriteLine(string text)
+ {
+ Universe u = moduleBuilder.universe;
+ Emit(OpCodes.Ldstr, text);
+ Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("WriteLine", new Type[] { u.System_String }));
+ }
+
+ public void EmitWriteLine(FieldInfo field)
+ {
+ Universe u = moduleBuilder.universe;
+ Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("get_Out"));
+ if (field.IsStatic)
+ {
+ Emit(OpCodes.Ldsfld, field);
+ }
+ else
+ {
+ Emit(OpCodes.Ldarg_0);
+ Emit(OpCodes.Ldfld, field);
+ }
+ Emit(OpCodes.Callvirt, u.Import(typeof(System.IO.TextWriter)).GetMethod("WriteLine", new Type[] { field.FieldType }));
+ }
+
+ public void EmitWriteLine(LocalBuilder local)
+ {
+ Universe u = moduleBuilder.universe;
+ Emit(OpCodes.Call, u.Import(typeof(Console)).GetMethod("get_Out"));
+ Emit(OpCodes.Ldloc, local);
+ Emit(OpCodes.Callvirt, u.Import(typeof(System.IO.TextWriter)).GetMethod("WriteLine", new Type[] { local.LocalType }));
+ }
+
+ public void EndScope()
+ {
+ scope.endOffset = code.Position;
+ scope = scope.parent;
+ }
+
+ public void MarkLabel(Label loc)
+ {
+ Debug.Assert(stackHeight == -1 || labelStackHeight[loc.Index] == -1 || stackHeight == labelStackHeight[loc.Index]);
+ labels[loc.Index] = code.Position;
+ if (labelStackHeight[loc.Index] == -1)
+ {
+ if (stackHeight == -1)
+ {
+ // We're at a location that can only be reached by a backward branch,
+ // so according to the "backward branch constraint" that must mean the stack is empty,
+ // but note that this may be an unused label followed by another label that is used and
+ // that does have a non-zero stack height, so we don't yet set stackHeight here.
+ labelStackHeight[loc.Index] = 0;
+ }
+ else
+ {
+ labelStackHeight[loc.Index] = stackHeight;
+ }
+ }
+ else
+ {
+ Debug.Assert(stackHeight == -1 || stackHeight == labelStackHeight[loc.Index]);
+ stackHeight = labelStackHeight[loc.Index];
+ }
+ }
+
+ public void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn)
+ {
+ SequencePoint sp = new SequencePoint();
+ sp.document = document;
+ sp.offset = code.Position;
+ sp.startLine = startLine;
+ sp.startColumn = startColumn;
+ sp.endLine = endLine;
+ sp.endColumn = endColumn;
+ sequencePoints.Add(sp);
+ }
+
+ public void ThrowException(Type excType)
+ {
+ Emit(OpCodes.Newobj, excType.GetConstructor(Type.EmptyTypes));
+ Emit(OpCodes.Throw);
+ }
+
+ internal int WriteBody(bool initLocals)
+ {
+ if (moduleBuilder.symbolWriter != null)
+ {
+ Debug.Assert(scope != null && scope.parent == null);
+ scope.endOffset = code.Position;
+ }
+
+ ResolveBranches();
+
+ ByteBuffer bb = moduleBuilder.methodBodies;
+
+ int localVarSigTok = 0;
+
+ int rva;
+ if (locals.Count == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64)
+ {
+ rva = WriteTinyHeaderAndCode(bb);
+ }
+ else
+ {
+ rva = WriteFatHeaderAndCode(bb, ref localVarSigTok, initLocals);
+ }
+
+ if (moduleBuilder.symbolWriter != null)
+ {
+ if (sequencePoints.Count != 0)
+ {
+ ISymbolDocumentWriter document = sequencePoints[0].document;
+ int[] offsets = new int[sequencePoints.Count];
+ int[] lines = new int[sequencePoints.Count];
+ int[] columns = new int[sequencePoints.Count];
+ int[] endLines = new int[sequencePoints.Count];
+ int[] endColumns = new int[sequencePoints.Count];
+ for (int i = 0; i < sequencePoints.Count; i++)
+ {
+ if (sequencePoints[i].document != document)
+ {
+ throw new NotImplementedException();
+ }
+ offsets[i] = sequencePoints[i].offset;
+ lines[i] = sequencePoints[i].startLine;
+ columns[i] = sequencePoints[i].startColumn;
+ endLines[i] = sequencePoints[i].endLine;
+ endColumns[i] = sequencePoints[i].endColumn;
+ }
+ moduleBuilder.symbolWriter.DefineSequencePoints(document, offsets, lines, columns, endLines, endColumns);
+ }
+
+ WriteScope(scope, localVarSigTok);
+ }
+ return rva;
+ }
+
+ private void ResolveBranches()
+ {
+ foreach (LabelFixup fixup in labelFixups)
+ {
+ // is it a switch?
+ if (fixup.label == -1)
+ {
+ code.Position = fixup.offset;
+ int count = code.GetInt32AtCurrentPosition();
+ int offset = fixup.offset + 4 + 4 * count;
+ code.Position += 4;
+ for (int i = 0; i < count; i++)
+ {
+ int index = code.GetInt32AtCurrentPosition();
+ code.Write(labels[index] - offset);
+ }
+ }
+ else
+ {
+ code.Position = fixup.offset;
+ byte size = code.GetByteAtCurrentPosition();
+ int branchOffset = labels[fixup.label] - (code.Position + size);
+ if (size == 1)
+ {
+ WriteByteBranchOffset(branchOffset);
+ }
+ else
+ {
+ code.Write(branchOffset);
+ }
+ }
+ }
+ }
+
+ private int WriteTinyHeaderAndCode(ByteBuffer bb)
+ {
+ int rva = bb.Position;
+ const byte CorILMethod_TinyFormat = 0x2;
+ bb.Write((byte)(CorILMethod_TinyFormat | (code.Length << 2)));
+ WriteCode(bb);
+ return rva;
+ }
+
+ private int WriteFatHeaderAndCode(ByteBuffer bb, ref int localVarSigTok, bool initLocals)
+ {
+ // fat headers require 4-byte alignment
+ bb.Align(4);
+ int rva = bb.Position;
+
+ if (locals.Count != 0)
+ {
+ ByteBuffer localVarSig = new ByteBuffer(locals.Count + 2);
+ Signature.WriteLocalVarSig(moduleBuilder, localVarSig, locals);
+ localVarSigTok = 0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(localVarSig));
+ }
+
+ const byte CorILMethod_FatFormat = 0x03;
+ const byte CorILMethod_MoreSects = 0x08;
+ const byte CorILMethod_InitLocals = 0x10;
+
+ short flagsAndSize = (short)(CorILMethod_FatFormat | (3 << 12));
+ if (initLocals)
+ {
+ flagsAndSize |= CorILMethod_InitLocals;
+ }
+
+ if (exceptions.Count > 0)
+ {
+ flagsAndSize |= CorILMethod_MoreSects;
+ }
+
+ bb.Write(flagsAndSize);
+ bb.Write(maxStack);
+ bb.Write(code.Length);
+ bb.Write(localVarSigTok);
+
+ WriteCode(bb);
+
+ if (exceptions.Count > 0)
+ {
+ bb.Align(4);
+
+ bool fat = false;
+ foreach (ExceptionBlock block in exceptions)
+ {
+ if (block.tryOffset > 65535 || block.tryLength > 255 || block.handlerOffset > 65535 || block.handlerLength > 255)
+ {
+ fat = true;
+ break;
+ }
+ }
+ exceptions.Sort(exceptions[0]);
+ if (exceptions.Count * 12 + 4 > 255)
+ {
+ fat = true;
+ }
+ const byte CorILMethod_Sect_EHTable = 0x1;
+ const byte CorILMethod_Sect_FatFormat = 0x40;
+ const short COR_ILEXCEPTION_CLAUSE_EXCEPTION = 0x0000;
+ const short COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001;
+ const short COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002;
+ const short COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004;
+
+ if (fat)
+ {
+ bb.Write((byte)(CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat));
+ int dataSize = exceptions.Count * 24 + 4;
+ bb.Write((byte)dataSize);
+ bb.Write((short)(dataSize >> 8));
+ foreach (ExceptionBlock block in exceptions)
+ {
+ if (block.exceptionType == FAULT)
+ {
+ bb.Write((int)COR_ILEXCEPTION_CLAUSE_FAULT);
+ }
+ else if (block.filterOffset != 0)
+ {
+ bb.Write((int)COR_ILEXCEPTION_CLAUSE_FILTER);
+ }
+ else if (block.exceptionType != null)
+ {
+ bb.Write((int)COR_ILEXCEPTION_CLAUSE_EXCEPTION);
+ }
+ else
+ {
+ bb.Write((int)COR_ILEXCEPTION_CLAUSE_FINALLY);
+ }
+ bb.Write(block.tryOffset);
+ bb.Write(block.tryLength);
+ bb.Write(block.handlerOffset);
+ bb.Write(block.handlerLength);
+ if (block.exceptionType != null && block.exceptionType != FAULT)
+ {
+ bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
+ }
+ else
+ {
+ bb.Write(block.filterOffset);
+ }
+ }
+ }
+ else
+ {
+ bb.Write(CorILMethod_Sect_EHTable);
+ bb.Write((byte)(exceptions.Count * 12 + 4));
+ bb.Write((short)0);
+ foreach (ExceptionBlock block in exceptions)
+ {
+ if (block.exceptionType == FAULT)
+ {
+ bb.Write(COR_ILEXCEPTION_CLAUSE_FAULT);
+ }
+ else if (block.filterOffset != 0)
+ {
+ bb.Write(COR_ILEXCEPTION_CLAUSE_FILTER);
+ }
+ else if (block.exceptionType != null)
+ {
+ bb.Write(COR_ILEXCEPTION_CLAUSE_EXCEPTION);
+ }
+ else
+ {
+ bb.Write(COR_ILEXCEPTION_CLAUSE_FINALLY);
+ }
+ bb.Write((short)block.tryOffset);
+ bb.Write((byte)block.tryLength);
+ bb.Write((short)block.handlerOffset);
+ bb.Write((byte)block.handlerLength);
+ if (block.exceptionType != null && block.exceptionType != FAULT)
+ {
+ bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
+ }
+ else
+ {
+ bb.Write(block.filterOffset);
+ }
+ }
+ }
+ }
+ return rva;
+ }
+
+ private void WriteCode(ByteBuffer bb)
+ {
+ int codeOffset = bb.Position;
+ foreach (int fixup in this.tokenFixups)
+ {
+ moduleBuilder.tokenFixupOffsets.Add(fixup + codeOffset);
+ }
+ bb.Write(code);
+ }
+
+ private void WriteScope(Scope scope, int localVarSigTok)
+ {
+ moduleBuilder.symbolWriter.OpenScope(scope.startOffset);
+ foreach (LocalBuilder local in scope.locals)
+ {
+ if (local.name != null)
+ {
+ int startOffset = local.startOffset;
+ int endOffset = local.endOffset;
+ if (startOffset == 0 && endOffset == 0)
+ {
+ startOffset = scope.startOffset;
+ endOffset = scope.endOffset;
+ }
+ moduleBuilder.symbolWriter.DefineLocalVariable2(local.name, 0, localVarSigTok, SymAddressKind.ILOffset, local.LocalIndex, 0, 0, startOffset, endOffset);
+ }
+ }
+ foreach (Scope child in scope.children)
+ {
+ WriteScope(child, localVarSigTok);
+ }
+ moduleBuilder.symbolWriter.CloseScope(scope.endOffset);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Diagnostics.SymbolStore;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class MethodBuilder : MethodInfo
+ {
+ private readonly TypeBuilder typeBuilder;
+ private readonly string name;
+ private readonly int nameIndex;
+ private readonly int pseudoToken;
+ private int signature;
+ private Type returnType;
+ private Type[] parameterTypes;
+ private Type[][][] modifiers; // see PackedCustomModifiers
+ private MethodAttributes attributes;
+ private MethodImplAttributes implFlags;
+ private ILGenerator ilgen;
+ private int rva;
+ private readonly CallingConventions callingConvention;
+ private List<ParameterBuilder> parameters;
+ private GenericTypeParameterBuilder[] gtpb;
+ private List<CustomAttributeBuilder> declarativeSecurity;
+ private MethodSignature methodSignature;
+ private bool initLocals = true;
+
+ internal MethodBuilder(TypeBuilder typeBuilder, string name, MethodAttributes attributes, CallingConventions callingConvention)
+ {
+ this.typeBuilder = typeBuilder;
+ this.name = name;
+ this.pseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+ // because all the MethodBuilders constitute a virtual MethodDef table, we cannot allocate the string during WriteMethodDefRecord,
+ // since by then the metadata has already been frozen
+ this.nameIndex = typeBuilder.ModuleBuilder.Strings.Add(name);
+ this.attributes = attributes;
+ if ((attributes & MethodAttributes.Static) == 0)
+ {
+ callingConvention |= CallingConventions.HasThis;
+ }
+ this.callingConvention = callingConvention;
+ }
+
+ public ILGenerator GetILGenerator()
+ {
+ return GetILGenerator(16);
+ }
+
+ public ILGenerator GetILGenerator(int streamSize)
+ {
+ if (ilgen == null)
+ {
+ ilgen = new ILGenerator(typeBuilder.ModuleBuilder, streamSize);
+ }
+ return ilgen;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ private void SetDllImportPseudoCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ CallingConvention? callingConvention = customBuilder.GetFieldValue<CallingConvention>("CallingConvention");
+ CharSet? charSet = customBuilder.GetFieldValue<CharSet>("CharSet");
+ SetDllImportPseudoCustomAttribute((string)customBuilder.GetConstructorArgument(0),
+ (string)customBuilder.GetFieldValue("EntryPoint"),
+ callingConvention,
+ charSet,
+ (bool?)customBuilder.GetFieldValue("BestFitMapping"),
+ (bool?)customBuilder.GetFieldValue("ThrowOnUnmappableChar"),
+ (bool?)customBuilder.GetFieldValue("SetLastError"),
+ (bool?)customBuilder.GetFieldValue("PreserveSig"),
+ (bool?)customBuilder.GetFieldValue("ExactSpelling"));
+ }
+
+ internal void SetDllImportPseudoCustomAttribute(string dllName, string entryName, CallingConvention? nativeCallConv, CharSet? nativeCharSet,
+ bool? bestFitMapping, bool? throwOnUnmappableChar, bool? setLastError, bool? preserveSig, bool? exactSpelling)
+ {
+ const short NoMangle = 0x0001;
+ const short CharSetMask = 0x0006;
+ const short CharSetNotSpec = 0x0000;
+ const short CharSetAnsi = 0x0002;
+ const short CharSetUnicode = 0x0004;
+ const short CharSetAuto = 0x0006;
+ const short SupportsLastError = 0x0040;
+ const short CallConvMask = 0x0700;
+ const short CallConvWinapi = 0x0100;
+ const short CallConvCdecl = 0x0200;
+ const short CallConvStdcall = 0x0300;
+ const short CallConvThiscall = 0x0400;
+ const short CallConvFastcall = 0x0500;
+ // non-standard flags
+ const short BestFitOn = 0x0010;
+ const short BestFitOff = 0x0020;
+ const short CharMapErrorOn = 0x1000;
+ const short CharMapErrorOff = 0x2000;
+ int name = this.nameIndex;
+ short flags = CharSetNotSpec | CallConvWinapi;
+ if (bestFitMapping.HasValue)
+ {
+ flags |= bestFitMapping.Value ? BestFitOn : BestFitOff;
+ }
+ if (throwOnUnmappableChar.HasValue)
+ {
+ flags |= throwOnUnmappableChar.Value ? CharMapErrorOn : CharMapErrorOff;
+ }
+ if (nativeCallConv.HasValue)
+ {
+ flags &= ~CallConvMask;
+ switch (nativeCallConv.Value)
+ {
+ case System.Runtime.InteropServices.CallingConvention.Cdecl:
+ flags |= CallConvCdecl;
+ break;
+ case System.Runtime.InteropServices.CallingConvention.FastCall:
+ flags |= CallConvFastcall;
+ break;
+ case System.Runtime.InteropServices.CallingConvention.StdCall:
+ flags |= CallConvStdcall;
+ break;
+ case System.Runtime.InteropServices.CallingConvention.ThisCall:
+ flags |= CallConvThiscall;
+ break;
+ case System.Runtime.InteropServices.CallingConvention.Winapi:
+ flags |= CallConvWinapi;
+ break;
+ }
+ }
+ if (nativeCharSet.HasValue)
+ {
+ flags &= ~CharSetMask;
+ switch (nativeCharSet.Value)
+ {
+ case CharSet.Ansi:
+ case CharSet.None:
+ flags |= CharSetAnsi;
+ break;
+ case CharSet.Auto:
+ flags |= CharSetAuto;
+ break;
+ case CharSet.Unicode:
+ flags |= CharSetUnicode;
+ break;
+ }
+ }
+ if (entryName != null)
+ {
+ name = this.ModuleBuilder.Strings.Add(entryName);
+ }
+ if (exactSpelling.HasValue && exactSpelling.Value)
+ {
+ flags |= NoMangle;
+ }
+ if (!preserveSig.HasValue || preserveSig.Value)
+ {
+ implFlags |= MethodImplAttributes.PreserveSig;
+ }
+ if (setLastError.HasValue && setLastError.Value)
+ {
+ flags |= SupportsLastError;
+ }
+ ImplMapTable.Record rec = new ImplMapTable.Record();
+ rec.MappingFlags = flags;
+ rec.MemberForwarded = pseudoToken;
+ rec.ImportName = name;
+ rec.ImportScope = this.ModuleBuilder.ModuleRef.FindOrAddRecord(dllName == null ? 0 : this.ModuleBuilder.Strings.Add(dllName));
+ this.ModuleBuilder.ImplMap.AddRecord(rec);
+ }
+
+ private void SetMethodImplAttribute(CustomAttributeBuilder customBuilder)
+ {
+ MethodImplOptions opt;
+ switch (customBuilder.Constructor.ParameterCount)
+ {
+ case 0:
+ opt = 0;
+ break;
+ case 1:
+ {
+ object val = customBuilder.GetConstructorArgument(0);
+ if (val is short)
+ {
+ opt = (MethodImplOptions)(short)val;
+ }
+ else if (val is int)
+ {
+ opt = (MethodImplOptions)(int)val;
+ }
+ else
+ {
+ opt = (MethodImplOptions)val;
+ }
+ break;
+ }
+ default:
+ throw new NotSupportedException();
+ }
+ MethodCodeType? type = customBuilder.GetFieldValue<MethodCodeType>("MethodCodeType");
+ implFlags = (MethodImplAttributes)opt;
+ if (type.HasValue)
+ {
+ implFlags |= (MethodImplAttributes)type;
+ }
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ Universe u = this.ModuleBuilder.universe;
+ Type type = customBuilder.Constructor.DeclaringType;
+ if (type == u.System_Runtime_InteropServices_DllImportAttribute)
+ {
+ attributes |= MethodAttributes.PinvokeImpl;
+ SetDllImportPseudoCustomAttribute(customBuilder.DecodeBlob(this.Module.Assembly));
+ }
+ else if (type == u.System_Runtime_CompilerServices_MethodImplAttribute)
+ {
+ SetMethodImplAttribute(customBuilder.DecodeBlob(this.Module.Assembly));
+ }
+ else if (type == u.System_Runtime_InteropServices_PreserveSigAttribute)
+ {
+ implFlags |= MethodImplAttributes.PreserveSig;
+ }
+ else if (type == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+ {
+ attributes |= MethodAttributes.SpecialName;
+ }
+ else
+ {
+ if (type == u.System_Security_SuppressUnmanagedCodeSecurityAttribute)
+ {
+ attributes |= MethodAttributes.HasSecurity;
+ }
+ this.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
+ }
+ }
+
+ public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+ {
+ attributes |= MethodAttributes.HasSecurity;
+ if (declarativeSecurity == null)
+ {
+ declarativeSecurity = new List<CustomAttributeBuilder>();
+ }
+ declarativeSecurity.Add(customBuilder);
+ }
+
+ public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+ {
+ this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, securityAction, permissionSet);
+ this.attributes |= MethodAttributes.HasSecurity;
+ }
+
+ public void SetImplementationFlags(MethodImplAttributes attributes)
+ {
+ implFlags = attributes;
+ }
+
+ public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
+ {
+ // the parameter is named "position", but it is actually a sequence number (i.e. 0 = return parameter, 1 = first parameter)
+ int sequence = position--;
+ if (parameters == null)
+ {
+ parameters = new List<ParameterBuilder>();
+ }
+ this.ModuleBuilder.Param.AddVirtualRecord();
+ ParameterBuilder pb = new ParameterBuilder(this.ModuleBuilder, sequence, attributes, strParamName);
+ if (parameters.Count == 0 || position > parameters[parameters.Count - 1].Position)
+ {
+ parameters.Add(pb);
+ }
+ else
+ {
+ for (int i = 0; i < parameters.Count; i++)
+ {
+ if (parameters[i].Position > position)
+ {
+ parameters.Insert(i, pb);
+ break;
+ }
+ }
+ }
+ return pb;
+ }
+
+ public void SetParameters(params Type[] parameterTypes)
+ {
+ this.parameterTypes = Util.Copy(parameterTypes);
+ }
+
+ public void SetReturnType(Type returnType)
+ {
+ this.returnType = returnType ?? this.Module.universe.System_Void;
+ }
+
+ public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ this.returnType = returnType ?? this.Module.universe.System_Void;
+ this.parameterTypes = Util.Copy(parameterTypes);
+ this.modifiers = PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers,
+ parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, this.parameterTypes.Length);
+ }
+
+ public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
+ {
+ gtpb = new GenericTypeParameterBuilder[names.Length];
+ for (int i = 0; i < names.Length; i++)
+ {
+ gtpb[i] = new GenericTypeParameterBuilder(names[i], null, this, i);
+ }
+ return (GenericTypeParameterBuilder[])gtpb.Clone();
+ }
+
+ public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ return new GenericMethodInstance(typeBuilder, this, typeArguments);
+ }
+
+ public override MethodInfo GetGenericMethodDefinition()
+ {
+ if (gtpb == null)
+ {
+ throw new InvalidOperationException();
+ }
+ return this;
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ return Util.Copy(gtpb);
+ }
+
+ internal override Type GetGenericMethodArgument(int index)
+ {
+ return gtpb[index];
+ }
+
+ internal override int GetGenericMethodArgumentCount()
+ {
+ return gtpb == null ? 0 : gtpb.Length;
+ }
+
+ public override Type ReturnType
+ {
+ get { return returnType; }
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get { return new ParameterInfoImpl(this, -1); }
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return attributes; }
+ }
+
+ public void __SetAttributes(MethodAttributes attributes)
+ {
+ this.attributes = attributes;
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return implFlags;
+ }
+
+ private sealed class ParameterInfoImpl : ParameterInfo
+ {
+ private readonly MethodBuilder method;
+ private readonly int parameter;
+
+ internal ParameterInfoImpl(MethodBuilder method, int parameter)
+ {
+ this.method = method;
+ this.parameter = parameter;
+ }
+
+ private ParameterBuilder ParameterBuilder
+ {
+ get
+ {
+ if (method.parameters != null)
+ {
+ foreach (ParameterBuilder pb in method.parameters)
+ {
+ if (pb.Position == parameter)
+ {
+ return pb;
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ ParameterBuilder pb = this.ParameterBuilder;
+ return pb != null ? pb.Name : null;
+ }
+ }
+
+ public override Type ParameterType
+ {
+ get { return parameter == -1 ? method.returnType : method.parameterTypes[parameter]; }
+ }
+
+ public override ParameterAttributes Attributes
+ {
+ get
+ {
+ ParameterBuilder pb = this.ParameterBuilder;
+ return pb != null ? (ParameterAttributes)pb.Attributes : ParameterAttributes.None;
+ }
+ }
+
+ public override int Position
+ {
+ get { return parameter; }
+ }
+
+ public override object RawDefaultValue
+ {
+ get
+ {
+ ParameterBuilder pb = this.ParameterBuilder;
+ if (pb != null && (pb.Attributes & (int)ParameterAttributes.HasDefault) != 0)
+ {
+ return method.ModuleBuilder.Constant.GetRawConstantValue(method.ModuleBuilder, pb.PseudoToken);
+ }
+ if (pb != null && (pb.Attributes & (int)ParameterAttributes.Optional) != 0)
+ {
+ return Missing.Value;
+ }
+ return null;
+ }
+ }
+
+ private Type[] GetCustomModifiers(int optOrReq)
+ {
+ if (method.modifiers == null || method.modifiers[parameter + 1] == null)
+ {
+ return Type.EmptyTypes;
+ }
+ return Util.Copy(method.modifiers[parameter + 1][optOrReq]);
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return GetCustomModifiers(0);
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return GetCustomModifiers(1);
+ }
+
+ public override MemberInfo Member
+ {
+ get { return method; }
+ }
+
+ public override int MetadataToken
+ {
+ get
+ {
+ ParameterBuilder pb = this.ParameterBuilder;
+ return pb != null ? pb.PseudoToken : 0x08000000;
+ }
+ }
+
+ internal override Module Module
+ {
+ get { return method.Module; }
+ }
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length];
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = new ParameterInfoImpl(this, i);
+ }
+ return parameters;
+ }
+
+ internal override int ParameterCount
+ {
+ get { return parameterTypes.Length; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeBuilder.IsModulePseudoType ? null : typeBuilder; }
+ }
+
+ public override string Name
+ {
+ get { return name; }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get { return callingConvention; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return pseudoToken; }
+ }
+
+ public override bool IsGenericMethod
+ {
+ get { return gtpb != null; }
+ }
+
+ public override bool IsGenericMethodDefinition
+ {
+ get { return gtpb != null; }
+ }
+
+ public override Module Module
+ {
+ get { return typeBuilder.Module; }
+ }
+
+ public Module GetModule()
+ {
+ return typeBuilder.Module;
+ }
+
+ public MethodToken GetToken()
+ {
+ return new MethodToken(pseudoToken);
+ }
+
+ public override MethodBody GetMethodBody()
+ {
+ throw new NotSupportedException();
+ }
+
+ public bool InitLocals
+ {
+ get { return initLocals; }
+ set { initLocals = value; }
+ }
+
+ internal void Bake()
+ {
+ this.signature = this.ModuleBuilder.GetSignatureBlobIndex(this.MethodSignature);
+
+ if (ilgen != null)
+ {
+ if (this.ModuleBuilder.symbolWriter != null)
+ {
+ this.ModuleBuilder.symbolWriter.OpenMethod(new SymbolToken(-pseudoToken | 0x06000000));
+ }
+ rva = ilgen.WriteBody(initLocals);
+ if (this.ModuleBuilder.symbolWriter != null)
+ {
+ this.ModuleBuilder.symbolWriter.CloseMethod();
+ }
+ ilgen = null;
+ }
+ else
+ {
+ rva = -1;
+ }
+
+ if (declarativeSecurity != null)
+ {
+ this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, declarativeSecurity);
+ }
+ }
+
+ internal ModuleBuilder ModuleBuilder
+ {
+ get { return typeBuilder.ModuleBuilder; }
+ }
+
+ internal void WriteMethodDefRecord(int baseRVA, MetadataWriter mw, ref int paramList)
+ {
+ if (rva != -1)
+ {
+ mw.Write(rva + baseRVA);
+ }
+ else
+ {
+ mw.Write(0);
+ }
+ mw.Write((short)implFlags);
+ mw.Write((short)attributes);
+ mw.WriteStringIndex(nameIndex);
+ mw.WriteBlobIndex(signature);
+ mw.WriteParam(paramList);
+ if (parameters != null)
+ {
+ paramList += parameters.Count;
+ }
+ }
+
+ internal void WriteParamRecords(MetadataWriter mw)
+ {
+ if (parameters != null)
+ {
+ foreach (ParameterBuilder pb in parameters)
+ {
+ pb.WriteParamRecord(mw);
+ }
+ }
+ }
+
+ internal void FixupToken(int token, ref int parameterToken)
+ {
+ typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token);
+ if (parameters != null)
+ {
+ foreach (ParameterBuilder pb in parameters)
+ {
+ pb.FixupToken(parameterToken++);
+ }
+ }
+ }
+
+ internal override MethodSignature MethodSignature
+ {
+ get
+ {
+ if (methodSignature == null)
+ {
+ methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, modifiers, callingConvention, gtpb == null ? 0 : gtpb.Length);
+ }
+ return methodSignature;
+ }
+ }
+
+ internal override int ImportTo(ModuleBuilder other)
+ {
+ if (typeBuilder.IsGenericTypeDefinition)
+ {
+ return other.ImportMember(TypeBuilder.GetMethod(typeBuilder, this));
+ }
+ else if (other == typeBuilder.ModuleBuilder)
+ {
+ return pseudoToken;
+ }
+ else
+ {
+ return other.ImportMethodOrField(typeBuilder, name, this.MethodSignature);
+ }
+ }
+
+ internal void CheckBaked()
+ {
+ typeBuilder.CheckBaked();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Diagnostics;
+using System.Diagnostics.SymbolStore;
+using System.Security.Cryptography;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class ModuleBuilder : Module, ITypeOwner
+ {
+ private static readonly bool usePublicKeyAssemblyReference = false;
+ private readonly Guid mvid = Guid.NewGuid();
+ private long imageBaseAddress = 0x00400000;
+ private readonly AssemblyBuilder asm;
+ internal readonly string moduleName;
+ internal readonly string fileName;
+ internal readonly ISymbolWriterImpl symbolWriter;
+ private readonly TypeBuilder moduleType;
+ private readonly List<TypeBuilder> types = new List<TypeBuilder>();
+ private readonly Dictionary<Type, int> typeTokens = new Dictionary<Type, int>();
+ private readonly Dictionary<Type, int> memberRefTypeTokens = new Dictionary<Type, int>();
+ private readonly Dictionary<string, TypeBuilder> fullNameToType = new Dictionary<string, TypeBuilder>();
+ internal readonly ByteBuffer methodBodies = new ByteBuffer(128 * 1024);
+ internal readonly List<int> tokenFixupOffsets = new List<int>();
+ internal readonly ByteBuffer initializedData = new ByteBuffer(512);
+ internal readonly ByteBuffer manifestResources = new ByteBuffer(512);
+ internal ResourceSection unmanagedResources;
+ private readonly Dictionary<MemberInfo, int> importedMembers = new Dictionary<MemberInfo, int>();
+ private readonly Dictionary<MemberRefKey, int> importedMemberRefs = new Dictionary<MemberRefKey, int>();
+ private readonly Dictionary<Assembly, int> referencedAssemblies = new Dictionary<Assembly, int>();
+ private List<AssemblyName> referencedAssemblyNames;
+ private int nextPseudoToken = -1;
+ private readonly List<int> resolvedTokens = new List<int>();
+ internal readonly TableHeap Tables = new TableHeap();
+ internal readonly StringHeap Strings = new StringHeap();
+ internal readonly UserStringHeap UserStrings = new UserStringHeap();
+ internal readonly GuidHeap Guids = new GuidHeap();
+ internal readonly BlobHeap Blobs = new BlobHeap();
+
+ struct MemberRefKey : IEquatable<MemberRefKey>
+ {
+ private readonly Type type;
+ private readonly string name;
+ private readonly Signature signature;
+
+ internal MemberRefKey(Type type, string name, Signature signature)
+ {
+ this.type = type;
+ this.name = name;
+ this.signature = signature;
+ }
+
+ public bool Equals(MemberRefKey other)
+ {
+ return other.type.Equals(type)
+ && other.name == name
+ && other.signature.Equals(signature);
+ }
+
+ public override bool Equals(object obj)
+ {
+ MemberRefKey? other = obj as MemberRefKey?;
+ return other != null && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode();
+ }
+ }
+
+ internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
+ : base(asm.universe)
+ {
+ this.asm = asm;
+ this.moduleName = moduleName;
+ this.fileName = fileName;
+ if (emitSymbolInfo)
+ {
+ symbolWriter = SymbolSupport.CreateSymbolWriterFor(this);
+ }
+ // <Module> must be the first record in the TypeDef table
+ moduleType = new TypeBuilder(this, "<Module>", null, 0);
+ types.Add(moduleType);
+ }
+
+ internal void PopulatePropertyAndEventTables()
+ {
+ // LAMESPEC the PropertyMap and EventMap tables are not required to be sorted by the CLI spec,
+ // but .NET sorts them and Mono requires them to be sorted, so we have to populate the
+ // tables in the right order
+ foreach (TypeBuilder type in types)
+ {
+ type.PopulatePropertyAndEventTables();
+ }
+ }
+
+ internal void WriteTypeDefTable(MetadataWriter mw)
+ {
+ int fieldList = 1;
+ int methodList = 1;
+ foreach (TypeBuilder type in types)
+ {
+ type.WriteTypeDefRecord(mw, ref fieldList, ref methodList);
+ }
+ }
+
+ internal void WriteMethodDefTable(int baseRVA, MetadataWriter mw)
+ {
+ int paramList = 1;
+ foreach (TypeBuilder type in types)
+ {
+ type.WriteMethodDefRecords(baseRVA, mw, ref paramList);
+ }
+ }
+
+ internal void WriteParamTable(MetadataWriter mw)
+ {
+ foreach (TypeBuilder type in types)
+ {
+ type.WriteParamRecords(mw);
+ }
+ }
+
+ internal void WriteFieldTable(MetadataWriter mw)
+ {
+ foreach (TypeBuilder type in types)
+ {
+ type.WriteFieldRecords(mw);
+ }
+ }
+
+ internal int AllocPseudoToken()
+ {
+ return nextPseudoToken--;
+ }
+
+ public TypeBuilder DefineType(string name)
+ {
+ return DefineType(name, TypeAttributes.Class);
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr)
+ {
+ return DefineType(name, attr, null);
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
+ {
+ return DefineType(name, attr, parent, PackingSize.Unspecified, 0);
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
+ {
+ return DefineType(name, attr, parent, PackingSize.Unspecified, typesize);
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
+ {
+ return DefineType(name, attr, parent, packsize, 0);
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
+ {
+ TypeBuilder tb = DefineType(name, attr, parent);
+ foreach (Type iface in interfaces)
+ {
+ tb.AddInterfaceImplementation(iface);
+ }
+ return tb;
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
+ {
+ if (parent == null && (attr & TypeAttributes.Interface) == 0)
+ {
+ parent = universe.System_Object;
+ }
+ TypeBuilder typeBuilder = new TypeBuilder(this, name, parent, attr);
+ PostDefineType(typeBuilder, packingSize, typesize);
+ return typeBuilder;
+ }
+
+ public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
+ {
+ TypeBuilder tb = DefineType(name, (visibility & TypeAttributes.VisibilityMask) | TypeAttributes.Sealed, universe.System_Enum);
+ FieldBuilder fb = tb.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
+ return new EnumBuilder(tb, fb);
+ }
+
+ internal TypeBuilder DefineNestedTypeHelper(TypeBuilder enclosingType, string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
+ {
+ if (parent == null && (attr & TypeAttributes.Interface) == 0)
+ {
+ parent = universe.System_Object;
+ }
+ TypeBuilder typeBuilder = new TypeBuilder(enclosingType, name, parent, attr);
+ PostDefineType(typeBuilder, packingSize, typesize);
+ if (enclosingType != null)
+ {
+ NestedClassTable.Record rec = new NestedClassTable.Record();
+ rec.NestedClass = typeBuilder.MetadataToken;
+ rec.EnclosingClass = enclosingType.MetadataToken;
+ this.NestedClass.AddRecord(rec);
+ }
+ return typeBuilder;
+ }
+
+ private void PostDefineType(TypeBuilder typeBuilder, PackingSize packingSize, int typesize)
+ {
+ types.Add(typeBuilder);
+ fullNameToType.Add(typeBuilder.FullName, typeBuilder);
+ if (packingSize != PackingSize.Unspecified || typesize != 0)
+ {
+ ClassLayoutTable.Record rec = new ClassLayoutTable.Record();
+ rec.PackingSize = (short)packingSize;
+ rec.ClassSize = typesize;
+ rec.Parent = typeBuilder.MetadataToken;
+ this.ClassLayout.AddRecord(rec);
+ }
+ }
+
+ public FieldBuilder __DefineField(string name, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
+ {
+ return moduleType.DefineField(name, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
+ }
+
+ public ConstructorBuilder __DefineModuleInitializer(MethodAttributes visibility)
+ {
+ return moduleType.DefineConstructor(visibility | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
+ }
+
+ public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
+ {
+ return moduleType.DefineUninitializedData(name, size, attributes);
+ }
+
+ public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
+ {
+ return moduleType.DefineInitializedData(name, data, attributes);
+ }
+
+ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
+ }
+
+ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return moduleType.DefineMethod(name, attributes, callingConvention, returnType, parameterTypes);
+ }
+
+ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ return moduleType.DefineMethod(name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return moduleType.DefinePInvokeMethod(name, dllName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return moduleType.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
+ }
+
+ public void CreateGlobalFunctions()
+ {
+ moduleType.CreateType();
+ }
+
+ internal void AddTypeForwarder(Type type)
+ {
+ ExportType(type);
+ foreach (Type nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
+ {
+ // we export all nested types (i.e. even the private ones)
+ // (this behavior is the same as the C# compiler)
+ AddTypeForwarder(nested);
+ }
+ }
+
+ private int ExportType(Type type)
+ {
+ ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
+ rec.TypeDefId = type.MetadataToken;
+ rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+ if (type.IsNested)
+ {
+ rec.Flags = 0;
+ rec.TypeNamespace = 0;
+ rec.Implementation = ExportType(type.DeclaringType);
+ }
+ else
+ {
+ rec.Flags = 0x00200000; // CorTypeAttr.tdForwarder
+ string ns = type.Namespace;
+ rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
+ rec.Implementation = ImportAssemblyRef(type.Assembly);
+ }
+ return 0x27000000 | this.ExportedType.FindOrAddRecord(rec);
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ SetCustomAttribute(0x00000001, customBuilder);
+ }
+
+ internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
+ {
+ Debug.Assert(!customBuilder.IsPseudoCustomAttribute);
+ CustomAttributeTable.Record rec = new CustomAttributeTable.Record();
+ rec.Parent = token;
+ rec.Type = this.GetConstructorToken(customBuilder.Constructor).Token;
+ rec.Value = customBuilder.WriteBlob(this);
+ this.CustomAttribute.AddRecord(rec);
+ }
+
+ internal void AddDeclarativeSecurity(int token, System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+ {
+ DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
+ rec.Action = (short)securityAction;
+ rec.Parent = token;
+ // like Ref.Emit, we're using the .NET 1.x xml format
+ rec.PermissionSet = this.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
+ this.DeclSecurity.AddRecord(rec);
+ }
+
+ internal void AddDeclarativeSecurity(int token, List<CustomAttributeBuilder> declarativeSecurity)
+ {
+ Dictionary<int, List<CustomAttributeBuilder>> ordered = new Dictionary<int, List<CustomAttributeBuilder>>();
+ foreach (CustomAttributeBuilder cab in declarativeSecurity)
+ {
+ int action;
+ // check for HostProtectionAttribute without SecurityAction
+ if (cab.ConstructorArgumentCount == 0)
+ {
+ action = (int)System.Security.Permissions.SecurityAction.LinkDemand;
+ }
+ else
+ {
+ action = (int)cab.GetConstructorArgument(0);
+ }
+ List<CustomAttributeBuilder> list;
+ if (!ordered.TryGetValue(action, out list))
+ {
+ list = new List<CustomAttributeBuilder>();
+ ordered.Add(action, list);
+ }
+ list.Add(cab);
+ }
+ foreach (KeyValuePair<int, List<CustomAttributeBuilder>> kv in ordered)
+ {
+ DeclSecurityTable.Record rec = new DeclSecurityTable.Record();
+ rec.Action = (short)kv.Key;
+ rec.Parent = token;
+ rec.PermissionSet = WriteDeclSecurityBlob(kv.Value);
+ this.DeclSecurity.AddRecord(rec);
+ }
+ }
+
+ private int WriteDeclSecurityBlob(List<CustomAttributeBuilder> list)
+ {
+ ByteBuffer namedArgs = new ByteBuffer(100);
+ ByteBuffer bb = new ByteBuffer(list.Count * 100);
+ bb.Write((byte)'.');
+ bb.WriteCompressedInt(list.Count);
+ foreach (CustomAttributeBuilder cab in list)
+ {
+ bb.Write(cab.Constructor.DeclaringType.AssemblyQualifiedName);
+ namedArgs.Clear();
+ cab.WriteNamedArgumentsForDeclSecurity(this, namedArgs);
+ bb.WriteCompressedInt(namedArgs.Length);
+ bb.Write(namedArgs);
+ }
+ return this.Blobs.Add(bb);
+ }
+
+ public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
+ {
+ ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
+ rec.Offset = manifestResources.Position;
+ rec.Flags = (int)attribute;
+ rec.Name = this.Strings.Add(name);
+ rec.Implementation = 0;
+ this.ManifestResource.AddRecord(rec);
+ manifestResources.Write(0); // placeholder for the length
+ manifestResources.Write(stream);
+ int savePosition = manifestResources.Position;
+ manifestResources.Position = rec.Offset;
+ manifestResources.Write(savePosition - (manifestResources.Position + 4));
+ manifestResources.Position = savePosition;
+ }
+
+ public override Assembly Assembly
+ {
+ get { return asm; }
+ }
+
+ internal override Type GetTypeImpl(string typeName)
+ {
+ TypeBuilder type;
+ fullNameToType.TryGetValue(typeName, out type);
+ return type;
+ }
+
+ internal override void GetTypesImpl(List<Type> list)
+ {
+ foreach (Type type in types)
+ {
+ if (type != moduleType)
+ {
+ list.Add(type);
+ }
+ }
+ }
+
+ public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
+ {
+ return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
+ }
+
+ public TypeToken GetTypeToken(string name)
+ {
+ return new TypeToken(GetType(name, true, false).MetadataToken);
+ }
+
+ public TypeToken GetTypeToken(Type type)
+ {
+ if (type.Module == this)
+ {
+ return new TypeToken(type.GetModuleBuilderToken());
+ }
+ else
+ {
+ return new TypeToken(ImportType(type));
+ }
+ }
+
+ internal int GetTypeTokenForMemberRef(Type type)
+ {
+ if (type.IsGenericTypeDefinition)
+ {
+ int token;
+ if (!memberRefTypeTokens.TryGetValue(type, out token))
+ {
+ ByteBuffer spec = new ByteBuffer(5);
+ Signature.WriteTypeSpec(this, spec, type);
+ token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
+ memberRefTypeTokens.Add(type, token);
+ }
+ return token;
+ }
+ else if (type.IsModulePseudoType)
+ {
+ return 0x1A000000 | this.ModuleRef.FindOrAddRecord(this.Strings.Add(type.Module.ScopeName));
+ }
+ else
+ {
+ return GetTypeToken(type).Token;
+ }
+ }
+
+ private static bool IsFromGenericTypeDefinition(MemberInfo member)
+ {
+ Type decl = member.DeclaringType;
+ return decl != null && decl.IsGenericTypeDefinition;
+ }
+
+ public FieldToken GetFieldToken(FieldInfo field)
+ {
+ // NOTE for some reason, when TypeBuilder.GetFieldToken() is used on a field in a generic type definition,
+ // a memberref token is returned (confirmed on .NET) unlike for Get(Method|Constructor)Token which always
+ // simply returns the MethodDef token (if the method is from the same module).
+ FieldBuilder fb = field as FieldBuilder;
+ if (fb != null && fb.Module == this && !IsFromGenericTypeDefinition(fb))
+ {
+ return new FieldToken(fb.MetadataToken);
+ }
+ else
+ {
+ return new FieldToken(ImportMember(field));
+ }
+ }
+
+ public MethodToken GetMethodToken(MethodInfo method)
+ {
+ MethodBuilder mb = method as MethodBuilder;
+ if (mb != null && mb.ModuleBuilder == this)
+ {
+ return new MethodToken(mb.MetadataToken);
+ }
+ else
+ {
+ return new MethodToken(ImportMember(method));
+ }
+ }
+
+ // when we refer to a method on a generic type definition in the IL stream,
+ // we need to use a MemberRef (even if the method is in the same module)
+ internal MethodToken GetMethodTokenForIL(MethodInfo method)
+ {
+ if (method.IsGenericMethodDefinition)
+ {
+ method = method.MakeGenericMethod(method.GetGenericArguments());
+ }
+ if (IsFromGenericTypeDefinition(method))
+ {
+ return new MethodToken(ImportMember(method));
+ }
+ else
+ {
+ return GetMethodToken(method);
+ }
+ }
+
+ public MethodToken GetConstructorToken(ConstructorInfo constructor)
+ {
+ if (constructor.Module == this && constructor.GetMethodInfo() is MethodBuilder)
+ {
+ return new MethodToken(constructor.MetadataToken);
+ }
+ else
+ {
+ return new MethodToken(ImportMember(constructor));
+ }
+ }
+
+ internal int ImportMember(MethodBase member)
+ {
+ int token;
+ if (!importedMembers.TryGetValue(member, out token))
+ {
+ token = member.ImportTo(this);
+ importedMembers.Add(member, token);
+ }
+ return token;
+ }
+
+ internal int ImportMember(FieldInfo member)
+ {
+ int token;
+ if (!importedMembers.TryGetValue(member, out token))
+ {
+ token = member.ImportTo(this);
+ importedMembers.Add(member, token);
+ }
+ return token;
+ }
+
+ internal int ImportMethodOrField(Type declaringType, string name, Signature sig)
+ {
+ int token;
+ if (!importedMemberRefs.TryGetValue(new MemberRefKey(declaringType, name, sig), out token))
+ {
+ MemberRefTable.Record rec = new MemberRefTable.Record();
+ rec.Class = GetTypeTokenForMemberRef(declaringType);
+ rec.Name = this.Strings.Add(name);
+ ByteBuffer bb = new ByteBuffer(16);
+ sig.WriteSig(this, bb);
+ rec.Signature = this.Blobs.Add(bb);
+ token = 0x0A000000 | this.MemberRef.AddRecord(rec);
+ importedMemberRefs.Add(new MemberRefKey(declaringType, name, sig), token);
+ }
+ return token;
+ }
+
+ internal int ImportType(Type type)
+ {
+ int token;
+ if (!typeTokens.TryGetValue(type, out token))
+ {
+ if (type.HasElementType || (type.IsGenericType && !type.IsGenericTypeDefinition))
+ {
+ ByteBuffer spec = new ByteBuffer(5);
+ Signature.WriteTypeSpec(this, spec, type);
+ token = 0x1B000000 | this.TypeSpec.AddRecord(this.Blobs.Add(spec));
+ }
+ else
+ {
+ TypeRefTable.Record rec = new TypeRefTable.Record();
+ if (type.IsNested)
+ {
+ rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
+ rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+ rec.TypeNameSpace = 0;
+ }
+ else
+ {
+ rec.ResolutionScope = ImportAssemblyRef(type.Assembly);
+ rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+ string ns = type.Namespace;
+ rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
+ }
+ token = 0x01000000 | this.TypeRef.AddRecord(rec);
+ }
+ typeTokens.Add(type, token);
+ }
+ return token;
+ }
+
+ private int ImportAssemblyRef(Assembly asm)
+ {
+ int token;
+ if (!referencedAssemblies.TryGetValue(asm, out token))
+ {
+ // We can't write the AssemblyRef record here yet, because the identity of the assembly can still change
+ // (if it's an AssemblyBuilder).
+ // We set the high bit of rid in the token to make sure we emit obviously broken metadata,
+ // if we forget to patch up the token somewhere.
+ token = 0x23800001 + referencedAssemblies.Count;
+ referencedAssemblies.Add(asm, token);
+ }
+ return token;
+ }
+
+ internal void FillAssemblyRefTable()
+ {
+ int[] realtokens = new int[referencedAssemblies.Count];
+ foreach (KeyValuePair<Assembly, int> kv in referencedAssemblies)
+ {
+ realtokens[(kv.Value & 0x7FFFFF) - 1] = FindOrAddAssemblyRef(kv.Key.GetName());
+ }
+ // now fixup the resolution scopes in TypeRef
+ for (int i = 0; i < this.TypeRef.records.Length; i++)
+ {
+ int resolutionScope = this.TypeRef.records[i].ResolutionScope;
+ if ((resolutionScope >> 24) == AssemblyRefTable.Index)
+ {
+ this.TypeRef.records[i].ResolutionScope = realtokens[(resolutionScope & 0x7FFFFF) - 1];
+ }
+ }
+ // and implementation in ExportedType
+ for (int i = 0; i < this.ExportedType.records.Length; i++)
+ {
+ int implementation = this.ExportedType.records[i].Implementation;
+ if ((implementation >> 24) == AssemblyRefTable.Index)
+ {
+ this.ExportedType.records[i].Implementation = realtokens[(implementation & 0x7FFFFF) - 1];
+ }
+ }
+ }
+
+ private int FindOrAddAssemblyRef(AssemblyName name)
+ {
+ AssemblyRefTable.Record rec = new AssemblyRefTable.Record();
+ Version ver = name.Version;
+ rec.MajorVersion = (ushort)ver.Major;
+ rec.MinorVersion = (ushort)ver.Minor;
+ rec.BuildNumber = (ushort)ver.Build;
+ rec.RevisionNumber = (ushort)ver.Revision;
+ rec.Flags = (int)(name.Flags & AssemblyNameFlags.Retargetable);
+ byte[] publicKeyOrToken = null;
+ if (usePublicKeyAssemblyReference)
+ {
+ publicKeyOrToken = name.GetPublicKey();
+ }
+ if (publicKeyOrToken == null || publicKeyOrToken.Length == 0)
+ {
+ publicKeyOrToken = name.GetPublicKeyToken();
+ }
+ else
+ {
+ const int PublicKey = 0x0001;
+ rec.Flags |= PublicKey;
+ }
+ rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(publicKeyOrToken));
+ rec.Name = this.Strings.Add(name.Name);
+ if (name.CultureInfo != null)
+ {
+ rec.Culture = this.Strings.Add(name.CultureInfo.Name);
+ }
+ else
+ {
+ rec.Culture = 0;
+ }
+ rec.HashValue = 0;
+ return 0x23000000 | this.AssemblyRef.FindOrAddRecord(rec);
+ }
+
+ internal void WriteSymbolTokenMap()
+ {
+ for (int i = 0; i < resolvedTokens.Count; i++)
+ {
+ int newToken = resolvedTokens[i];
+ // The symbol API doesn't support remapping arbitrary integers, the types have to be the same,
+ // so we copy the type from the newToken, because our pseudo tokens don't have a type.
+ // (see MethodToken.SymbolToken)
+ int oldToken = (i + 1) | (newToken & ~0xFFFFFF);
+ SymbolSupport.RemapToken(symbolWriter, oldToken, newToken);
+ }
+ }
+
+ internal void RegisterTokenFixup(int pseudoToken, int realToken)
+ {
+ int index = -(pseudoToken + 1);
+ while (resolvedTokens.Count <= index)
+ {
+ resolvedTokens.Add(0);
+ }
+ resolvedTokens[index] = realToken;
+ }
+
+ internal bool IsPseudoToken(int token)
+ {
+ return token < 0;
+ }
+
+ internal int ResolvePseudoToken(int pseudoToken)
+ {
+ int index = -(pseudoToken + 1);
+ return resolvedTokens[index];
+ }
+
+ internal void FixupMethodBodyTokens()
+ {
+ int methodToken = 0x06000001;
+ int fieldToken = 0x04000001;
+ int parameterToken = 0x08000001;
+ foreach (TypeBuilder type in types)
+ {
+ type.ResolveMethodAndFieldTokens(ref methodToken, ref fieldToken, ref parameterToken);
+ }
+ foreach (int offset in tokenFixupOffsets)
+ {
+ methodBodies.Position = offset;
+ int pseudoToken = methodBodies.GetInt32AtCurrentPosition();
+ methodBodies.Write(ResolvePseudoToken(pseudoToken));
+ }
+ }
+
+ private int GetHeaderLength()
+ {
+ return
+ 4 + // Signature
+ 2 + // MajorVersion
+ 2 + // MinorVersion
+ 4 + // Reserved
+ 4 + // ImageRuntimeVersion Length
+ StringToPaddedUTF8Length(asm.ImageRuntimeVersion) +
+ 2 + // Flags
+ 2 + // Streams
+ 4 + // #~ Offset
+ 4 + // #~ Size
+ 4 + // StringToPaddedUTF8Length("#~")
+ 4 + // #Strings Offset
+ 4 + // #Strings Size
+ 12 + // StringToPaddedUTF8Length("#Strings")
+ 4 + // #US Offset
+ 4 + // #US Size
+ 4 + // StringToPaddedUTF8Length("#US")
+ 4 + // #GUID Offset
+ 4 + // #GUID Size
+ 8 + // StringToPaddedUTF8Length("#GUID")
+ (Blobs.IsEmpty ? 0 :
+ (
+ 4 + // #Blob Offset
+ 4 + // #Blob Size
+ 8 // StringToPaddedUTF8Length("#Blob")
+ ));
+ }
+
+ internal int MetadataLength
+ {
+ get
+ {
+ return GetHeaderLength() + (Blobs.IsEmpty ? 0 : Blobs.Length) + Tables.Length + Strings.Length + UserStrings.Length + Guids.Length;
+ }
+ }
+
+ internal void WriteMetadata(MetadataWriter mw)
+ {
+ mw.Write(0x424A5342); // Signature ("BSJB")
+ mw.Write((ushort)1); // MajorVersion
+ mw.Write((ushort)1); // MinorVersion
+ mw.Write(0); // Reserved
+ byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
+ mw.Write(version.Length); // Length
+ mw.Write(version);
+ mw.Write((ushort)0); // Flags
+ // #Blob is the only optional heap
+ if (Blobs.IsEmpty)
+ {
+ mw.Write((ushort)4); // Streams
+ }
+ else
+ {
+ mw.Write((ushort)5); // Streams
+ }
+
+ int offset = GetHeaderLength();
+
+ // Streams
+ mw.Write(offset); // Offset
+ mw.Write(Tables.Length); // Size
+ mw.Write(StringToPaddedUTF8("#~"));
+ offset += Tables.Length;
+
+ mw.Write(offset); // Offset
+ mw.Write(Strings.Length); // Size
+ mw.Write(StringToPaddedUTF8("#Strings"));
+ offset += Strings.Length;
+
+ mw.Write(offset); // Offset
+ mw.Write(UserStrings.Length); // Size
+ mw.Write(StringToPaddedUTF8("#US"));
+ offset += UserStrings.Length;
+
+ mw.Write(offset); // Offset
+ mw.Write(Guids.Length); // Size
+ mw.Write(StringToPaddedUTF8("#GUID"));
+ offset += Guids.Length;
+
+ if (!Blobs.IsEmpty)
+ {
+ mw.Write(offset); // Offset
+ mw.Write(Blobs.Length); // Size
+ mw.Write(StringToPaddedUTF8("#Blob"));
+ }
+
+ Tables.Write(mw);
+ Strings.Write(mw);
+ UserStrings.Write(mw);
+ Guids.Write(mw);
+ if (!Blobs.IsEmpty)
+ {
+ Blobs.Write(mw);
+ }
+ }
+
+ private static int StringToPaddedUTF8Length(string str)
+ {
+ return (System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3;
+ }
+
+ private static byte[] StringToPaddedUTF8(string str)
+ {
+ byte[] buf = new byte[(System.Text.Encoding.UTF8.GetByteCount(str) + 4) & ~3];
+ System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0);
+ return buf;
+ }
+
+ internal override void ExportTypes(int fileToken, ModuleBuilder manifestModule)
+ {
+ manifestModule.ExportTypes(types.ToArray(), fileToken);
+ }
+
+ internal void ExportTypes(Type[] types, int fileToken)
+ {
+ Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
+ foreach (Type type in types)
+ {
+ if (!type.IsModulePseudoType && IsVisible(type))
+ {
+ ExportedTypeTable.Record rec = new ExportedTypeTable.Record();
+ rec.Flags = (int)type.Attributes;
+ rec.TypeDefId = type.MetadataToken & 0xFFFFFF;
+ rec.TypeName = this.Strings.Add(TypeNameParser.Unescape(type.Name));
+ string ns = type.Namespace;
+ rec.TypeNamespace = ns == null ? 0 : this.Strings.Add(TypeNameParser.Unescape(ns));
+ if (type.IsNested)
+ {
+ rec.Implementation = declaringTypes[type.DeclaringType];
+ }
+ else
+ {
+ rec.Implementation = fileToken;
+ }
+ int exportTypeToken = 0x27000000 | this.ExportedType.AddRecord(rec);
+ declaringTypes.Add(type, exportTypeToken);
+ }
+ }
+ }
+
+ private static bool IsVisible(Type type)
+ {
+ // NOTE this is not the same as Type.IsVisible, because that doesn't take into account family access
+ return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
+ }
+
+ internal void AddConstant(int parentToken, object defaultValue)
+ {
+ ConstantTable.Record rec = new ConstantTable.Record();
+ rec.Parent = parentToken;
+ ByteBuffer val = new ByteBuffer(16);
+ if (defaultValue == null)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_CLASS;
+ val.Write((int)0);
+ }
+ else if (defaultValue is bool)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_BOOLEAN;
+ val.Write((bool)defaultValue ? (byte)1 : (byte)0);
+ }
+ else if (defaultValue is char)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_CHAR;
+ val.Write((char)defaultValue);
+ }
+ else if (defaultValue is sbyte)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_I1;
+ val.Write((sbyte)defaultValue);
+ }
+ else if (defaultValue is byte)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_U1;
+ val.Write((byte)defaultValue);
+ }
+ else if (defaultValue is short)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_I2;
+ val.Write((short)defaultValue);
+ }
+ else if (defaultValue is ushort)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_U2;
+ val.Write((ushort)defaultValue);
+ }
+ else if (defaultValue is int)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_I4;
+ val.Write((int)defaultValue);
+ }
+ else if (defaultValue is uint)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_U4;
+ val.Write((uint)defaultValue);
+ }
+ else if (defaultValue is long)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_I8;
+ val.Write((long)defaultValue);
+ }
+ else if (defaultValue is ulong)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_U8;
+ val.Write((ulong)defaultValue);
+ }
+ else if (defaultValue is float)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_R4;
+ val.Write((float)defaultValue);
+ }
+ else if (defaultValue is double)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_R8;
+ val.Write((double)defaultValue);
+ }
+ else if (defaultValue is string)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_STRING;
+ foreach (char c in (string)defaultValue)
+ {
+ val.Write(c);
+ }
+ }
+ else if (defaultValue is DateTime)
+ {
+ rec.Type = Signature.ELEMENT_TYPE_I8;
+ val.Write(((DateTime)defaultValue).Ticks);
+ }
+ else
+ {
+ throw new ArgumentException();
+ }
+ rec.Value = this.Blobs.Add(val);
+ this.Constant.AddRecord(rec);
+ }
+
+ ModuleBuilder ITypeOwner.ModuleBuilder
+ {
+ get { return this; }
+ }
+
+ public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ if (genericTypeArguments != null || genericMethodArguments != null)
+ {
+ throw new NotImplementedException();
+ }
+ return types[(metadataToken & 0xFFFFFF) - 1];
+ }
+
+ public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ if (genericTypeArguments != null || genericMethodArguments != null)
+ {
+ throw new NotImplementedException();
+ }
+ // this method is inefficient, but since it isn't used we don't care
+ if ((metadataToken >> 24) == MemberRefTable.Index)
+ {
+ foreach (KeyValuePair<MemberInfo, int> kv in importedMembers)
+ {
+ if (kv.Value == metadataToken)
+ {
+ return (MethodBase)kv.Key;
+ }
+ }
+ }
+ // HACK if we're given a SymbolToken, we need to convert back
+ if ((metadataToken & 0xFF000000) == 0x06000000)
+ {
+ metadataToken = -(metadataToken & 0x00FFFFFF);
+ }
+ foreach (Type type in types)
+ {
+ MethodBase method = ((TypeBuilder)type).LookupMethod(metadataToken);
+ if (method != null)
+ {
+ return method;
+ }
+ }
+ return ((TypeBuilder)moduleType).LookupMethod(metadataToken);
+ }
+
+ public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ResolveString(int metadataToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string FullyQualifiedName
+ {
+ get { return Path.GetFullPath(Path.Combine(asm.dir, fileName)); }
+ }
+
+ public override string Name
+ {
+ get { return fileName; }
+ }
+
+ public override Guid ModuleVersionId
+ {
+ get { return mvid; }
+ }
+
+ public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ScopeName
+ {
+ get { return moduleName; }
+ }
+
+ public ISymbolWriter GetSymWriter()
+ {
+ return symbolWriter;
+ }
+
+ public void DefineUnmanagedResource(string resourceFileName)
+ {
+ // This method reads the specified resource file (Win32 .res file) and converts it into the appropriate format and embeds it in the .rsrc section,
+ // also setting the Resource Directory entry.
+ unmanagedResources = new ResourceSection();
+ unmanagedResources.ExtractResources(System.IO.File.ReadAllBytes(resourceFileName));
+ }
+
+ public bool IsTransient()
+ {
+ return false;
+ }
+
+ public void SetUserEntryPoint(MethodInfo entryPoint)
+ {
+ int token = entryPoint.MetadataToken;
+ if (token < 0)
+ {
+ token = -token | 0x06000000;
+ }
+ if (symbolWriter != null)
+ {
+ symbolWriter.SetUserEntryPoint(new SymbolToken(token));
+ }
+ }
+
+ public StringToken GetStringConstant(string str)
+ {
+ return new StringToken(this.UserStrings.Add(str) | (0x70 << 24));
+ }
+
+ public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
+ {
+ return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(sigHelper.GetSignature(this))) | (StandAloneSigTable.Index << 24));
+ }
+
+ public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
+ {
+ return new SignatureToken(this.StandAloneSig.FindOrAddRecord(this.Blobs.Add(ByteBuffer.Wrap(sigBytes, sigLength))) | (StandAloneSigTable.Index << 24));
+ }
+
+ public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
+ }
+
+ public MethodToken GetArrayMethodToken(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return GetMethodToken(GetArrayMethod(arrayClass, methodName, callingConvention, returnType, parameterTypes));
+ }
+
+ internal override Type GetModuleType()
+ {
+ return moduleType;
+ }
+
+ internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+ {
+ return Blobs.GetBlob(blobIndex);
+ }
+
+ internal int GetSignatureBlobIndex(Signature sig)
+ {
+ ByteBuffer bb = new ByteBuffer(16);
+ sig.WriteSig(this, bb);
+ return this.Blobs.Add(bb);
+ }
+
+ // non-standard API
+ public long __ImageBase
+ {
+ get { return imageBaseAddress; }
+ set { imageBaseAddress = value; }
+ }
+
+ public override int MDStreamVersion
+ {
+ get { return asm.mdStreamVersion; }
+ }
+
+ private int AddTypeRefByName(int resolutionScope, string ns, string name)
+ {
+ TypeRefTable.Record rec = new TypeRefTable.Record();
+ rec.ResolutionScope = resolutionScope;
+ rec.TypeName = this.Strings.Add(name);
+ rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
+ return 0x01000000 | this.TypeRef.AddRecord(rec);
+ }
+
+ public void __Save(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+ {
+ PopulatePropertyAndEventTables();
+ IList<CustomAttributeData> attributes = asm.GetCustomAttributesData(null);
+ if (attributes.Count > 0)
+ {
+ int mscorlib = ImportAssemblyRef(universe.Mscorlib);
+ int[] placeholderTokens = new int[4];
+ string[] placeholderTypeNames = new string[] { "AssemblyAttributesGoHere", "AssemblyAttributesGoHereM", "AssemblyAttributesGoHereS", "AssemblyAttributesGoHereSM" };
+ foreach (CustomAttributeData cad in attributes)
+ {
+ int index;
+ if (cad.Constructor.DeclaringType.BaseType == universe.System_Security_Permissions_CodeAccessSecurityAttribute)
+ {
+ if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
+ {
+ index = 3;
+ }
+ else
+ {
+ index = 2;
+ }
+ }
+ else if (cad.Constructor.DeclaringType.IsAllowMultipleCustomAttribute)
+ {
+ index = 1;
+ }
+ else
+ {
+ index = 0;
+ }
+ if (placeholderTokens[index] == 0)
+ {
+ // we manually add a TypeRef without looking it up in mscorlib, because Mono and Silverlight's mscorlib don't have these types
+ placeholderTokens[index] = AddTypeRefByName(mscorlib, "System.Runtime.CompilerServices", placeholderTypeNames[index]);
+ }
+ SetCustomAttribute(placeholderTokens[index], cad.__ToBuilder());
+ }
+ }
+ FillAssemblyRefTable();
+ ModuleWriter.WriteModule(null, null, this, PEFileKinds.Dll, portableExecutableKind, imageFileMachine, unmanagedResources, 0);
+ }
+
+ public void __AddAssemblyReference(AssemblyName assemblyName)
+ {
+ if (referencedAssemblyNames == null)
+ {
+ referencedAssemblyNames = new List<AssemblyName>();
+ }
+ FindOrAddAssemblyRef(assemblyName);
+ referencedAssemblyNames.Add((AssemblyName)assemblyName.Clone());
+ }
+
+ public override AssemblyName[] __GetReferencedAssemblies()
+ {
+ List<AssemblyName> list = new List<AssemblyName>();
+ if (referencedAssemblyNames != null)
+ {
+ foreach (AssemblyName name in referencedAssemblyNames)
+ {
+ if (!list.Contains(name))
+ {
+ list.Add(name);
+ }
+ }
+ }
+ foreach (Assembly asm in referencedAssemblies.Keys)
+ {
+ AssemblyName name = asm.GetName();
+ if (!list.Contains(name))
+ {
+ list.Add(name);
+ }
+ }
+ return list.ToArray();
+ }
+ }
+
+ class ArrayMethod : MethodInfo
+ {
+ private readonly Module module;
+ private readonly Type arrayClass;
+ private readonly string methodName;
+ private readonly CallingConventions callingConvention;
+ private readonly Type returnType;
+ protected readonly Type[] parameterTypes;
+ private MethodSignature methodSignature;
+
+ internal ArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ this.module = module;
+ this.arrayClass = arrayClass;
+ this.methodName = methodName;
+ this.callingConvention = callingConvention;
+ this.returnType = returnType ?? module.universe.System_Void;
+ this.parameterTypes = Util.Copy(parameterTypes);
+ }
+
+ public override MethodBody GetMethodBody()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ throw new NotSupportedException();
+ }
+
+ internal override int ImportTo(ModuleBuilder module)
+ {
+ return module.ImportMethodOrField(arrayClass, methodName, MethodSignature);
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get { return callingConvention; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return arrayClass; }
+ }
+
+ internal override MethodSignature MethodSignature
+ {
+ get
+ {
+ if (methodSignature == null)
+ {
+ methodSignature = MethodSignature.MakeFromBuilder(returnType, parameterTypes, null, callingConvention, 0);
+ }
+ return methodSignature;
+ }
+ }
+
+ public override Module Module
+ {
+ // like .NET, we return the module that GetArrayMethod was called on, not the module associated with the array type
+ get { return module; }
+ }
+
+ public override string Name
+ {
+ get { return methodName; }
+ }
+
+ internal override int ParameterCount
+ {
+ get { return parameterTypes.Length; }
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public override Type ReturnType
+ {
+ get { return returnType; }
+ }
+
+ internal override bool HasThis
+ {
+ get { return (callingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008, 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Diagnostics;
+
+namespace IKVM.Reflection.Emit
+{
+ public struct OpCode
+ {
+ private const int ValueCount = 1024;
+ private const int OperandTypeCount = 19;
+ private const int FlowControlCount = 9;
+ private const int StackDiffCount = 5;
+ private const int OpCodeTypeCount = 6;
+ private const int StackBehaviourPopCount = 20;
+ private const int StackBehaviourPushCount = 9;
+ private static readonly StackBehaviour[] pop = {
+ StackBehaviour.Pop0,
+ StackBehaviour.Pop1,
+ StackBehaviour.Pop1_pop1,
+ StackBehaviour.Popi,
+ StackBehaviour.Popi_pop1,
+ StackBehaviour.Popi_popi,
+ StackBehaviour.Popi_popi8,
+ StackBehaviour.Popi_popi_popi,
+ StackBehaviour.Popi_popr4,
+ StackBehaviour.Popi_popr8,
+ StackBehaviour.Popref,
+ StackBehaviour.Popref_pop1,
+ StackBehaviour.Popref_popi,
+ StackBehaviour.Popref_popi_popi,
+ StackBehaviour.Popref_popi_popi8,
+ StackBehaviour.Popref_popi_popr4,
+ StackBehaviour.Popref_popi_popr8,
+ StackBehaviour.Popref_popi_popref,
+ StackBehaviour.Varpop,
+ StackBehaviour.Popref_popi_pop1
+ };
+ private static readonly StackBehaviour[] push = {
+ StackBehaviour.Push0,
+ StackBehaviour.Push1,
+ StackBehaviour.Push1_push1,
+ StackBehaviour.Pushi,
+ StackBehaviour.Pushi8,
+ StackBehaviour.Pushr4,
+ StackBehaviour.Pushr8,
+ StackBehaviour.Pushref,
+ StackBehaviour.Varpush
+ };
+ private readonly int value;
+
+ internal OpCode(int value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return this == obj as OpCode?;
+ }
+
+ public override int GetHashCode()
+ {
+ return value;
+ }
+
+ public bool Equals(OpCode other)
+ {
+ return this == other;
+ }
+
+ public static bool operator ==(OpCode a, OpCode b)
+ {
+ return a.value == b.value;
+ }
+
+ public static bool operator !=(OpCode a, OpCode b)
+ {
+ return !(a == b);
+ }
+
+ public short Value
+ {
+ get { return (short)(value >> 22); }
+ }
+
+ public int Size
+ {
+ get { return value < 0 ? 2 : 1; }
+ }
+
+#if !GENERATOR
+ public string Name
+ {
+ get { return OpCodes.GetName(this.Value); }
+ }
+#endif
+
+ public OperandType OperandType
+ {
+ get { return (OperandType)((value & 0x3FFFFF) % OperandTypeCount); }
+ }
+
+ public FlowControl FlowControl
+ {
+ get { return (FlowControl)(((value & 0x3FFFFF) / OperandTypeCount) % FlowControlCount); }
+ }
+
+ internal int StackDiff
+ {
+ get { return ((((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount)) % StackDiffCount) - 3); }
+ }
+
+ public OpCodeType OpCodeType
+ {
+ get { return (OpCodeType)(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount)) % OpCodeTypeCount); }
+ }
+
+ public StackBehaviour StackBehaviourPop
+ {
+ get { return pop[(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount * OpCodeTypeCount)) % StackBehaviourPopCount)]; }
+ }
+
+ public StackBehaviour StackBehaviourPush
+ {
+ get { return push[(((value & 0x3FFFFF) / (OperandTypeCount * FlowControlCount * StackDiffCount * OpCodeTypeCount * StackBehaviourPopCount)) % StackBehaviourPushCount)]; }
+ }
+
+#if GENERATOR
+ static void Main(string[] args)
+ {
+ Debug.Assert(pop.Length == StackBehaviourPopCount);
+ Debug.Assert(push.Length == StackBehaviourPushCount);
+ CheckEnumRange(typeof(FlowControl), FlowControlCount);
+ CheckEnumRange(typeof(OpCodeType), OpCodeTypeCount);
+ CheckEnumRange(typeof(OperandType), OperandTypeCount);
+ foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+ {
+ System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null);
+ IKVM.Reflection.Emit.OpCode opc2 = new IKVM.Reflection.Emit.OpCode(Pack(opc1));
+ Debug.Assert(opc1.Value == opc2.Value);
+ Debug.Assert(opc1.Size == opc2.Size);
+ Debug.Assert((int)opc1.FlowControl == (int)opc2.FlowControl);
+ Debug.Assert((int)opc1.OpCodeType == (int)opc2.OpCodeType);
+ Debug.Assert((int)opc1.OperandType == (int)opc2.OperandType);
+ Debug.Assert((int)opc1.StackBehaviourPop == (int)opc2.StackBehaviourPop);
+ Debug.Assert((int)opc1.StackBehaviourPush == (int)opc2.StackBehaviourPush);
+ Console.WriteLine("\t\tpublic static readonly OpCode {0} = new OpCode({1});", field.Name, Pack(opc1));
+ }
+ Console.WriteLine();
+ Console.WriteLine("\t\tinternal static string GetName(int value)");
+ Console.WriteLine("\t\t{");
+ Console.WriteLine("\t\t\tswitch (value)");
+ Console.WriteLine("\t\t\t{");
+ foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+ {
+ System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null);
+ Console.WriteLine("\t\t\t\tcase {0}:", opc1.Value);
+ Console.WriteLine("\t\t\t\t\treturn \"{0}\";", opc1.Name);
+ }
+ Console.WriteLine("\t\t\t}");
+ Console.WriteLine("\t\t\tthrow new ArgumentOutOfRangeException();");
+ Console.WriteLine("\t\t}");
+ Console.WriteLine();
+ Console.WriteLine("\t\tpublic static bool TakesSingleByteArgument(OpCode inst)");
+ Console.WriteLine("\t\t{");
+ Console.WriteLine("\t\t\tswitch (inst.Value)");
+ Console.WriteLine("\t\t\t{");
+ foreach (var field in typeof(System.Reflection.Emit.OpCodes).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+ {
+ System.Reflection.Emit.OpCode opc1 = (System.Reflection.Emit.OpCode)field.GetValue(null);
+ if (System.Reflection.Emit.OpCodes.TakesSingleByteArgument(opc1))
+ {
+ Console.WriteLine("\t\t\t\tcase {0}:", opc1.Value);
+ }
+ }
+ Console.WriteLine("\t\t\t\t\treturn true;");
+ Console.WriteLine("\t\t\t\tdefault:");
+ Console.WriteLine("\t\t\t\t\treturn false;");
+ Console.WriteLine("\t\t\t}");
+ Console.WriteLine("\t\t}");
+ }
+
+ private static void CheckEnumRange(System.Type type, int count)
+ {
+ foreach (var field in type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static))
+ {
+ int value = (int)field.GetValue(null);
+ Debug.Assert(value >= 0 && value < count);
+ }
+ }
+
+ static int Pack(System.Reflection.Emit.OpCode opcode)
+ {
+ int value = 0;
+ value *= StackBehaviourPushCount;
+ value += Map(push, opcode.StackBehaviourPush);
+ value *= StackBehaviourPopCount;
+ value += Map(pop, opcode.StackBehaviourPop);
+ value *= OpCodeTypeCount;
+ value += (int)opcode.OpCodeType;
+ value *= StackDiffCount;
+ value += 3 + GetStackDiff(opcode.StackBehaviourPush) + GetStackDiff(opcode.StackBehaviourPop);
+ value *= FlowControlCount;
+ value += (int)opcode.FlowControl;
+ value *= OperandTypeCount;
+ value += (int)opcode.OperandType;
+ return (opcode.Value << 22) | value;
+ }
+
+ private static int Map(StackBehaviour[] array, System.Reflection.Emit.StackBehaviour stackBehaviour)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ if ((int)array[i] == (int)stackBehaviour)
+ {
+ return i;
+ }
+ }
+ throw new InvalidOperationException();
+ }
+
+ static int GetStackDiff(System.Reflection.Emit.StackBehaviour sb)
+ {
+ switch (sb)
+ {
+ case System.Reflection.Emit.StackBehaviour.Pop0:
+ case System.Reflection.Emit.StackBehaviour.Push0:
+ case System.Reflection.Emit.StackBehaviour.Varpop:
+ case System.Reflection.Emit.StackBehaviour.Varpush:
+ return 0;
+ case System.Reflection.Emit.StackBehaviour.Pop1:
+ case System.Reflection.Emit.StackBehaviour.Popi:
+ case System.Reflection.Emit.StackBehaviour.Popref:
+ return -1;
+ case System.Reflection.Emit.StackBehaviour.Pop1_pop1:
+ case System.Reflection.Emit.StackBehaviour.Popi_pop1:
+ case System.Reflection.Emit.StackBehaviour.Popi_popi:
+ case System.Reflection.Emit.StackBehaviour.Popi_popi8:
+ case System.Reflection.Emit.StackBehaviour.Popi_popr4:
+ case System.Reflection.Emit.StackBehaviour.Popi_popr8:
+ case System.Reflection.Emit.StackBehaviour.Popref_pop1:
+ case System.Reflection.Emit.StackBehaviour.Popref_popi:
+ return -2;
+ case System.Reflection.Emit.StackBehaviour.Popi_popi_popi:
+ case System.Reflection.Emit.StackBehaviour.Popref_popi_pop1:
+ case System.Reflection.Emit.StackBehaviour.Popref_popi_popi:
+ case System.Reflection.Emit.StackBehaviour.Popref_popi_popi8:
+ case System.Reflection.Emit.StackBehaviour.Popref_popi_popr4:
+ case System.Reflection.Emit.StackBehaviour.Popref_popi_popr8:
+ case System.Reflection.Emit.StackBehaviour.Popref_popi_popref:
+ return -3;
+ case System.Reflection.Emit.StackBehaviour.Push1:
+ case System.Reflection.Emit.StackBehaviour.Pushi:
+ case System.Reflection.Emit.StackBehaviour.Pushi8:
+ case System.Reflection.Emit.StackBehaviour.Pushr4:
+ case System.Reflection.Emit.StackBehaviour.Pushr8:
+ case System.Reflection.Emit.StackBehaviour.Pushref:
+ return 1;
+ case System.Reflection.Emit.StackBehaviour.Push1_push1:
+ return 2;
+ }
+ throw new InvalidOperationException();
+ }
+#endif // GENERATOR
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection.Emit
+{
+ public class OpCodes
+ {
+ public static readonly OpCode Nop = new OpCode(4888);
+ public static readonly OpCode Break = new OpCode(4199116);
+ public static readonly OpCode Ldarg_0 = new OpCode(8492847);
+ public static readonly OpCode Ldarg_1 = new OpCode(12687151);
+ public static readonly OpCode Ldarg_2 = new OpCode(16881455);
+ public static readonly OpCode Ldarg_3 = new OpCode(21075759);
+ public static readonly OpCode Ldloc_0 = new OpCode(25270063);
+ public static readonly OpCode Ldloc_1 = new OpCode(29464367);
+ public static readonly OpCode Ldloc_2 = new OpCode(33658671);
+ public static readonly OpCode Ldloc_3 = new OpCode(37852975);
+ public static readonly OpCode Stloc_0 = new OpCode(41949467);
+ public static readonly OpCode Stloc_1 = new OpCode(46143771);
+ public static readonly OpCode Stloc_2 = new OpCode(50338075);
+ public static readonly OpCode Stloc_3 = new OpCode(54532379);
+ public static readonly OpCode Ldarg_S = new OpCode(58824508);
+ public static readonly OpCode Ldarga_S = new OpCode(63224012);
+ public static readonly OpCode Starg_S = new OpCode(67115304);
+ public static readonly OpCode Ldloc_S = new OpCode(71407420);
+ public static readonly OpCode Ldloca_S = new OpCode(75806924);
+ public static readonly OpCode Stloc_S = new OpCode(79698216);
+ public static readonly OpCode Ldnull = new OpCode(84609339);
+ public static readonly OpCode Ldc_I4_M1 = new OpCode(88389823);
+ public static readonly OpCode Ldc_I4_0 = new OpCode(92584127);
+ public static readonly OpCode Ldc_I4_1 = new OpCode(96778431);
+ public static readonly OpCode Ldc_I4_2 = new OpCode(100972735);
+ public static readonly OpCode Ldc_I4_3 = new OpCode(105167039);
+ public static readonly OpCode Ldc_I4_4 = new OpCode(109361343);
+ public static readonly OpCode Ldc_I4_5 = new OpCode(113555647);
+ public static readonly OpCode Ldc_I4_6 = new OpCode(117749951);
+ public static readonly OpCode Ldc_I4_7 = new OpCode(121944255);
+ public static readonly OpCode Ldc_I4_8 = new OpCode(126138559);
+ public static readonly OpCode Ldc_I4_S = new OpCode(130332874);
+ public static readonly OpCode Ldc_I4 = new OpCode(134530584);
+ public static readonly OpCode Ldc_I8 = new OpCode(138827489);
+ public static readonly OpCode Ldc_R4 = new OpCode(143124407);
+ public static readonly OpCode Ldc_R8 = new OpCode(147421301);
+ public static readonly OpCode Dup = new OpCode(155404637);
+ public static readonly OpCode Pop = new OpCode(159393399);
+ public static readonly OpCode Jmp = new OpCode(163582686);
+ public static readonly OpCode Call = new OpCode(168690130);
+ public static readonly OpCode Calli = new OpCode(172884439);
+ public static readonly OpCode Ret = new OpCode(176258034);
+ public static readonly OpCode Br_S = new OpCode(180356455);
+ public static readonly OpCode Brfalse_S = new OpCode(184566035);
+ public static readonly OpCode Brtrue_S = new OpCode(188760339);
+ public static readonly OpCode Beq_S = new OpCode(192949342);
+ public static readonly OpCode Bge_S = new OpCode(197143646);
+ public static readonly OpCode Bgt_S = new OpCode(201337950);
+ public static readonly OpCode Ble_S = new OpCode(205532254);
+ public static readonly OpCode Blt_S = new OpCode(209726558);
+ public static readonly OpCode Bne_Un_S = new OpCode(213920862);
+ public static readonly OpCode Bge_Un_S = new OpCode(218115166);
+ public static readonly OpCode Bgt_Un_S = new OpCode(222309470);
+ public static readonly OpCode Ble_Un_S = new OpCode(226503774);
+ public static readonly OpCode Blt_Un_S = new OpCode(230698078);
+ public static readonly OpCode Br = new OpCode(234885812);
+ public static readonly OpCode Brfalse = new OpCode(239095392);
+ public static readonly OpCode Brtrue = new OpCode(243289696);
+ public static readonly OpCode Beq = new OpCode(247475279);
+ public static readonly OpCode Bge = new OpCode(251669583);
+ public static readonly OpCode Bgt = new OpCode(255863887);
+ public static readonly OpCode Ble = new OpCode(260058191);
+ public static readonly OpCode Blt = new OpCode(264252495);
+ public static readonly OpCode Bne_Un = new OpCode(268446799);
+ public static readonly OpCode Bge_Un = new OpCode(272641103);
+ public static readonly OpCode Bgt_Un = new OpCode(276835407);
+ public static readonly OpCode Ble_Un = new OpCode(281029711);
+ public static readonly OpCode Blt_Un = new OpCode(285224015);
+ public static readonly OpCode Switch = new OpCode(289427051);
+ public static readonly OpCode Ldind_I1 = new OpCode(293929358);
+ public static readonly OpCode Ldind_U1 = new OpCode(298123662);
+ public static readonly OpCode Ldind_I2 = new OpCode(302317966);
+ public static readonly OpCode Ldind_U2 = new OpCode(306512270);
+ public static readonly OpCode Ldind_I4 = new OpCode(310706574);
+ public static readonly OpCode Ldind_U4 = new OpCode(314900878);
+ public static readonly OpCode Ldind_I8 = new OpCode(319197782);
+ public static readonly OpCode Ldind_I = new OpCode(323289486);
+ public static readonly OpCode Ldind_R4 = new OpCode(327688990);
+ public static readonly OpCode Ldind_R8 = new OpCode(331985894);
+ public static readonly OpCode Ldind_Ref = new OpCode(336282798);
+ public static readonly OpCode Stind_Ref = new OpCode(339768820);
+ public static readonly OpCode Stind_I1 = new OpCode(343963124);
+ public static readonly OpCode Stind_I2 = new OpCode(348157428);
+ public static readonly OpCode Stind_I4 = new OpCode(352351732);
+ public static readonly OpCode Stind_I8 = new OpCode(356551166);
+ public static readonly OpCode Stind_R4 = new OpCode(360755730);
+ public static readonly OpCode Stind_R8 = new OpCode(364955164);
+ public static readonly OpCode Add = new OpCode(369216329);
+ public static readonly OpCode Sub = new OpCode(373410633);
+ public static readonly OpCode Mul = new OpCode(377604937);
+ public static readonly OpCode Div = new OpCode(381799241);
+ public static readonly OpCode Div_Un = new OpCode(385993545);
+ public static readonly OpCode Rem = new OpCode(390187849);
+ public static readonly OpCode Rem_Un = new OpCode(394382153);
+ public static readonly OpCode And = new OpCode(398576457);
+ public static readonly OpCode Or = new OpCode(402770761);
+ public static readonly OpCode Xor = new OpCode(406965065);
+ public static readonly OpCode Shl = new OpCode(411159369);
+ public static readonly OpCode Shr = new OpCode(415353673);
+ public static readonly OpCode Shr_Un = new OpCode(419547977);
+ public static readonly OpCode Neg = new OpCode(423737322);
+ public static readonly OpCode Not = new OpCode(427931626);
+ public static readonly OpCode Conv_I1 = new OpCode(432331130);
+ public static readonly OpCode Conv_I2 = new OpCode(436525434);
+ public static readonly OpCode Conv_I4 = new OpCode(440719738);
+ public static readonly OpCode Conv_I8 = new OpCode(445016642);
+ public static readonly OpCode Conv_R4 = new OpCode(449313546);
+ public static readonly OpCode Conv_R8 = new OpCode(453610450);
+ public static readonly OpCode Conv_U4 = new OpCode(457496954);
+ public static readonly OpCode Conv_U8 = new OpCode(461793858);
+ public static readonly OpCode Callvirt = new OpCode(466484004);
+ public static readonly OpCode Cpobj = new OpCode(469790542);
+ public static readonly OpCode Ldobj = new OpCode(474077528);
+ public static readonly OpCode Ldstr = new OpCode(478872210);
+ public static readonly OpCode Newobj = new OpCode(483158791);
+ public static readonly OpCode Castclass = new OpCode(487311950);
+ public static readonly OpCode Isinst = new OpCode(491095854);
+ public static readonly OpCode Conv_R_Un = new OpCode(495553490);
+ public static readonly OpCode Unbox = new OpCode(507874780);
+ public static readonly OpCode Throw = new OpCode(511759452);
+ public static readonly OpCode Ldfld = new OpCode(516056466);
+ public static readonly OpCode Ldflda = new OpCode(520455970);
+ public static readonly OpCode Stfld = new OpCode(524347262);
+ public static readonly OpCode Ldsfld = new OpCode(528588249);
+ public static readonly OpCode Ldsflda = new OpCode(532987753);
+ public static readonly OpCode Stsfld = new OpCode(536879045);
+ public static readonly OpCode Stobj = new OpCode(541090290);
+ public static readonly OpCode Conv_Ovf_I1_Un = new OpCode(545577338);
+ public static readonly OpCode Conv_Ovf_I2_Un = new OpCode(549771642);
+ public static readonly OpCode Conv_Ovf_I4_Un = new OpCode(553965946);
+ public static readonly OpCode Conv_Ovf_I8_Un = new OpCode(558262850);
+ public static readonly OpCode Conv_Ovf_U1_Un = new OpCode(562354554);
+ public static readonly OpCode Conv_Ovf_U2_Un = new OpCode(566548858);
+ public static readonly OpCode Conv_Ovf_U4_Un = new OpCode(570743162);
+ public static readonly OpCode Conv_Ovf_U8_Un = new OpCode(575040066);
+ public static readonly OpCode Conv_Ovf_I_Un = new OpCode(579131770);
+ public static readonly OpCode Conv_Ovf_U_Un = new OpCode(583326074);
+ public static readonly OpCode Box = new OpCode(587930786);
+ public static readonly OpCode Newarr = new OpCode(592133640);
+ public static readonly OpCode Ldlen = new OpCode(595953446);
+ public static readonly OpCode Ldelema = new OpCode(600157847);
+ public static readonly OpCode Ldelem_I1 = new OpCode(604352143);
+ public static readonly OpCode Ldelem_U1 = new OpCode(608546447);
+ public static readonly OpCode Ldelem_I2 = new OpCode(612740751);
+ public static readonly OpCode Ldelem_U2 = new OpCode(616935055);
+ public static readonly OpCode Ldelem_I4 = new OpCode(621129359);
+ public static readonly OpCode Ldelem_U4 = new OpCode(625323663);
+ public static readonly OpCode Ldelem_I8 = new OpCode(629620567);
+ public static readonly OpCode Ldelem_I = new OpCode(633712271);
+ public static readonly OpCode Ldelem_R4 = new OpCode(638111775);
+ public static readonly OpCode Ldelem_R8 = new OpCode(642408679);
+ public static readonly OpCode Ldelem_Ref = new OpCode(646705583);
+ public static readonly OpCode Stelem_I = new OpCode(650186475);
+ public static readonly OpCode Stelem_I1 = new OpCode(654380779);
+ public static readonly OpCode Stelem_I2 = new OpCode(658575083);
+ public static readonly OpCode Stelem_I4 = new OpCode(662769387);
+ public static readonly OpCode Stelem_I8 = new OpCode(666968821);
+ public static readonly OpCode Stelem_R4 = new OpCode(671168255);
+ public static readonly OpCode Stelem_R8 = new OpCode(675367689);
+ public static readonly OpCode Stelem_Ref = new OpCode(679567123);
+ public static readonly OpCode Ldelem = new OpCode(683838727);
+ public static readonly OpCode Stelem = new OpCode(687965999);
+ public static readonly OpCode Unbox_Any = new OpCode(692217246);
+ public static readonly OpCode Conv_Ovf_I1 = new OpCode(751098234);
+ public static readonly OpCode Conv_Ovf_U1 = new OpCode(755292538);
+ public static readonly OpCode Conv_Ovf_I2 = new OpCode(759486842);
+ public static readonly OpCode Conv_Ovf_U2 = new OpCode(763681146);
+ public static readonly OpCode Conv_Ovf_I4 = new OpCode(767875450);
+ public static readonly OpCode Conv_Ovf_U4 = new OpCode(772069754);
+ public static readonly OpCode Conv_Ovf_I8 = new OpCode(776366658);
+ public static readonly OpCode Conv_Ovf_U8 = new OpCode(780560962);
+ public static readonly OpCode Refanyval = new OpCode(814012802);
+ public static readonly OpCode Ckfinite = new OpCode(818514898);
+ public static readonly OpCode Mkrefany = new OpCode(830595078);
+ public static readonly OpCode Ldtoken = new OpCode(872728098);
+ public static readonly OpCode Conv_U2 = new OpCode(876927354);
+ public static readonly OpCode Conv_U1 = new OpCode(881121658);
+ public static readonly OpCode Conv_I = new OpCode(885315962);
+ public static readonly OpCode Conv_Ovf_I = new OpCode(889510266);
+ public static readonly OpCode Conv_Ovf_U = new OpCode(893704570);
+ public static readonly OpCode Add_Ovf = new OpCode(897698633);
+ public static readonly OpCode Add_Ovf_Un = new OpCode(901892937);
+ public static readonly OpCode Mul_Ovf = new OpCode(906087241);
+ public static readonly OpCode Mul_Ovf_Un = new OpCode(910281545);
+ public static readonly OpCode Sub_Ovf = new OpCode(914475849);
+ public static readonly OpCode Sub_Ovf_Un = new OpCode(918670153);
+ public static readonly OpCode Endfinally = new OpCode(922751806);
+ public static readonly OpCode Leave = new OpCode(926945972);
+ public static readonly OpCode Leave_S = new OpCode(931140291);
+ public static readonly OpCode Stind_I = new OpCode(935359988);
+ public static readonly OpCode Conv_U = new OpCode(939841914);
+ public static readonly OpCode Prefix7 = new OpCode(1040189696);
+ public static readonly OpCode Prefix6 = new OpCode(1044384000);
+ public static readonly OpCode Prefix5 = new OpCode(1048578304);
+ public static readonly OpCode Prefix4 = new OpCode(1052772608);
+ public static readonly OpCode Prefix3 = new OpCode(1056966912);
+ public static readonly OpCode Prefix2 = new OpCode(1061161216);
+ public static readonly OpCode Prefix1 = new OpCode(1065355520);
+ public static readonly OpCode Prefixref = new OpCode(1069549824);
+ public static readonly OpCode Arglist = new OpCode(-2147170789);
+ public static readonly OpCode Ceq = new OpCode(-2142966567);
+ public static readonly OpCode Cgt = new OpCode(-2138772263);
+ public static readonly OpCode Cgt_Un = new OpCode(-2134577959);
+ public static readonly OpCode Clt = new OpCode(-2130383655);
+ public static readonly OpCode Clt_Un = new OpCode(-2126189351);
+ public static readonly OpCode Ldftn = new OpCode(-2122004966);
+ public static readonly OpCode Ldvirtftn = new OpCode(-2117759533);
+ public static readonly OpCode Ldarg = new OpCode(-2109627244);
+ public static readonly OpCode Ldarga = new OpCode(-2105227740);
+ public static readonly OpCode Starg = new OpCode(-2101336448);
+ public static readonly OpCode Ldloc = new OpCode(-2097044332);
+ public static readonly OpCode Ldloca = new OpCode(-2092644828);
+ public static readonly OpCode Stloc = new OpCode(-2088753536);
+ public static readonly OpCode Localloc = new OpCode(-2084241010);
+ public static readonly OpCode Endfilter = new OpCode(-2076160335);
+ public static readonly OpCode Unaligned = new OpCode(-2071982151);
+ public static readonly OpCode Volatile = new OpCode(-2067787858);
+ public static readonly OpCode Tailcall = new OpCode(-2063593554);
+ public static readonly OpCode Initobj = new OpCode(-2059384859);
+ public static readonly OpCode Constrained = new OpCode(-2055204938);
+ public static readonly OpCode Cpblk = new OpCode(-2050974371);
+ public static readonly OpCode Initblk = new OpCode(-2046780067);
+ public static readonly OpCode Rethrow = new OpCode(-2038428509);
+ public static readonly OpCode Sizeof = new OpCode(-2029730269);
+ public static readonly OpCode Refanytype = new OpCode(-2025531014);
+ public static readonly OpCode Readonly = new OpCode(-2021650514);
+
+ internal static string GetName(int value)
+ {
+ switch (value)
+ {
+ case 0:
+ return "nop";
+ case 1:
+ return "break";
+ case 2:
+ return "ldarg.0";
+ case 3:
+ return "ldarg.1";
+ case 4:
+ return "ldarg.2";
+ case 5:
+ return "ldarg.3";
+ case 6:
+ return "ldloc.0";
+ case 7:
+ return "ldloc.1";
+ case 8:
+ return "ldloc.2";
+ case 9:
+ return "ldloc.3";
+ case 10:
+ return "stloc.0";
+ case 11:
+ return "stloc.1";
+ case 12:
+ return "stloc.2";
+ case 13:
+ return "stloc.3";
+ case 14:
+ return "ldarg.s";
+ case 15:
+ return "ldarga.s";
+ case 16:
+ return "starg.s";
+ case 17:
+ return "ldloc.s";
+ case 18:
+ return "ldloca.s";
+ case 19:
+ return "stloc.s";
+ case 20:
+ return "ldnull";
+ case 21:
+ return "ldc.i4.m1";
+ case 22:
+ return "ldc.i4.0";
+ case 23:
+ return "ldc.i4.1";
+ case 24:
+ return "ldc.i4.2";
+ case 25:
+ return "ldc.i4.3";
+ case 26:
+ return "ldc.i4.4";
+ case 27:
+ return "ldc.i4.5";
+ case 28:
+ return "ldc.i4.6";
+ case 29:
+ return "ldc.i4.7";
+ case 30:
+ return "ldc.i4.8";
+ case 31:
+ return "ldc.i4.s";
+ case 32:
+ return "ldc.i4";
+ case 33:
+ return "ldc.i8";
+ case 34:
+ return "ldc.r4";
+ case 35:
+ return "ldc.r8";
+ case 37:
+ return "dup";
+ case 38:
+ return "pop";
+ case 39:
+ return "jmp";
+ case 40:
+ return "call";
+ case 41:
+ return "calli";
+ case 42:
+ return "ret";
+ case 43:
+ return "br.s";
+ case 44:
+ return "brfalse.s";
+ case 45:
+ return "brtrue.s";
+ case 46:
+ return "beq.s";
+ case 47:
+ return "bge.s";
+ case 48:
+ return "bgt.s";
+ case 49:
+ return "ble.s";
+ case 50:
+ return "blt.s";
+ case 51:
+ return "bne.un.s";
+ case 52:
+ return "bge.un.s";
+ case 53:
+ return "bgt.un.s";
+ case 54:
+ return "ble.un.s";
+ case 55:
+ return "blt.un.s";
+ case 56:
+ return "br";
+ case 57:
+ return "brfalse";
+ case 58:
+ return "brtrue";
+ case 59:
+ return "beq";
+ case 60:
+ return "bge";
+ case 61:
+ return "bgt";
+ case 62:
+ return "ble";
+ case 63:
+ return "blt";
+ case 64:
+ return "bne.un";
+ case 65:
+ return "bge.un";
+ case 66:
+ return "bgt.un";
+ case 67:
+ return "ble.un";
+ case 68:
+ return "blt.un";
+ case 69:
+ return "switch";
+ case 70:
+ return "ldind.i1";
+ case 71:
+ return "ldind.u1";
+ case 72:
+ return "ldind.i2";
+ case 73:
+ return "ldind.u2";
+ case 74:
+ return "ldind.i4";
+ case 75:
+ return "ldind.u4";
+ case 76:
+ return "ldind.i8";
+ case 77:
+ return "ldind.i";
+ case 78:
+ return "ldind.r4";
+ case 79:
+ return "ldind.r8";
+ case 80:
+ return "ldind.ref";
+ case 81:
+ return "stind.ref";
+ case 82:
+ return "stind.i1";
+ case 83:
+ return "stind.i2";
+ case 84:
+ return "stind.i4";
+ case 85:
+ return "stind.i8";
+ case 86:
+ return "stind.r4";
+ case 87:
+ return "stind.r8";
+ case 88:
+ return "add";
+ case 89:
+ return "sub";
+ case 90:
+ return "mul";
+ case 91:
+ return "div";
+ case 92:
+ return "div.un";
+ case 93:
+ return "rem";
+ case 94:
+ return "rem.un";
+ case 95:
+ return "and";
+ case 96:
+ return "or";
+ case 97:
+ return "xor";
+ case 98:
+ return "shl";
+ case 99:
+ return "shr";
+ case 100:
+ return "shr.un";
+ case 101:
+ return "neg";
+ case 102:
+ return "not";
+ case 103:
+ return "conv.i1";
+ case 104:
+ return "conv.i2";
+ case 105:
+ return "conv.i4";
+ case 106:
+ return "conv.i8";
+ case 107:
+ return "conv.r4";
+ case 108:
+ return "conv.r8";
+ case 109:
+ return "conv.u4";
+ case 110:
+ return "conv.u8";
+ case 111:
+ return "callvirt";
+ case 112:
+ return "cpobj";
+ case 113:
+ return "ldobj";
+ case 114:
+ return "ldstr";
+ case 115:
+ return "newobj";
+ case 116:
+ return "castclass";
+ case 117:
+ return "isinst";
+ case 118:
+ return "conv.r.un";
+ case 121:
+ return "unbox";
+ case 122:
+ return "throw";
+ case 123:
+ return "ldfld";
+ case 124:
+ return "ldflda";
+ case 125:
+ return "stfld";
+ case 126:
+ return "ldsfld";
+ case 127:
+ return "ldsflda";
+ case 128:
+ return "stsfld";
+ case 129:
+ return "stobj";
+ case 130:
+ return "conv.ovf.i1.un";
+ case 131:
+ return "conv.ovf.i2.un";
+ case 132:
+ return "conv.ovf.i4.un";
+ case 133:
+ return "conv.ovf.i8.un";
+ case 134:
+ return "conv.ovf.u1.un";
+ case 135:
+ return "conv.ovf.u2.un";
+ case 136:
+ return "conv.ovf.u4.un";
+ case 137:
+ return "conv.ovf.u8.un";
+ case 138:
+ return "conv.ovf.i.un";
+ case 139:
+ return "conv.ovf.u.un";
+ case 140:
+ return "box";
+ case 141:
+ return "newarr";
+ case 142:
+ return "ldlen";
+ case 143:
+ return "ldelema";
+ case 144:
+ return "ldelem.i1";
+ case 145:
+ return "ldelem.u1";
+ case 146:
+ return "ldelem.i2";
+ case 147:
+ return "ldelem.u2";
+ case 148:
+ return "ldelem.i4";
+ case 149:
+ return "ldelem.u4";
+ case 150:
+ return "ldelem.i8";
+ case 151:
+ return "ldelem.i";
+ case 152:
+ return "ldelem.r4";
+ case 153:
+ return "ldelem.r8";
+ case 154:
+ return "ldelem.ref";
+ case 155:
+ return "stelem.i";
+ case 156:
+ return "stelem.i1";
+ case 157:
+ return "stelem.i2";
+ case 158:
+ return "stelem.i4";
+ case 159:
+ return "stelem.i8";
+ case 160:
+ return "stelem.r4";
+ case 161:
+ return "stelem.r8";
+ case 162:
+ return "stelem.ref";
+ case 163:
+ return "ldelem";
+ case 164:
+ return "stelem";
+ case 165:
+ return "unbox.any";
+ case 179:
+ return "conv.ovf.i1";
+ case 180:
+ return "conv.ovf.u1";
+ case 181:
+ return "conv.ovf.i2";
+ case 182:
+ return "conv.ovf.u2";
+ case 183:
+ return "conv.ovf.i4";
+ case 184:
+ return "conv.ovf.u4";
+ case 185:
+ return "conv.ovf.i8";
+ case 186:
+ return "conv.ovf.u8";
+ case 194:
+ return "refanyval";
+ case 195:
+ return "ckfinite";
+ case 198:
+ return "mkrefany";
+ case 208:
+ return "ldtoken";
+ case 209:
+ return "conv.u2";
+ case 210:
+ return "conv.u1";
+ case 211:
+ return "conv.i";
+ case 212:
+ return "conv.ovf.i";
+ case 213:
+ return "conv.ovf.u";
+ case 214:
+ return "add.ovf";
+ case 215:
+ return "add.ovf.un";
+ case 216:
+ return "mul.ovf";
+ case 217:
+ return "mul.ovf.un";
+ case 218:
+ return "sub.ovf";
+ case 219:
+ return "sub.ovf.un";
+ case 220:
+ return "endfinally";
+ case 221:
+ return "leave";
+ case 222:
+ return "leave.s";
+ case 223:
+ return "stind.i";
+ case 224:
+ return "conv.u";
+ case 248:
+ return "prefix7";
+ case 249:
+ return "prefix6";
+ case 250:
+ return "prefix5";
+ case 251:
+ return "prefix4";
+ case 252:
+ return "prefix3";
+ case 253:
+ return "prefix2";
+ case 254:
+ return "prefix1";
+ case 255:
+ return "prefixref";
+ case -512:
+ return "arglist";
+ case -511:
+ return "ceq";
+ case -510:
+ return "cgt";
+ case -509:
+ return "cgt.un";
+ case -508:
+ return "clt";
+ case -507:
+ return "clt.un";
+ case -506:
+ return "ldftn";
+ case -505:
+ return "ldvirtftn";
+ case -503:
+ return "ldarg";
+ case -502:
+ return "ldarga";
+ case -501:
+ return "starg";
+ case -500:
+ return "ldloc";
+ case -499:
+ return "ldloca";
+ case -498:
+ return "stloc";
+ case -497:
+ return "localloc";
+ case -495:
+ return "endfilter";
+ case -494:
+ return "unaligned.";
+ case -493:
+ return "volatile.";
+ case -492:
+ return "tail.";
+ case -491:
+ return "initobj";
+ case -490:
+ return "constrained.";
+ case -489:
+ return "cpblk";
+ case -488:
+ return "initblk";
+ case -486:
+ return "rethrow";
+ case -484:
+ return "sizeof";
+ case -483:
+ return "refanytype";
+ case -482:
+ return "readonly.";
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+
+ public static bool TakesSingleByteArgument(OpCode inst)
+ {
+ switch (inst.Value)
+ {
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 31:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 222:
+ case -494:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class ParameterBuilder
+ {
+ private readonly ModuleBuilder moduleBuilder;
+ private short flags;
+ private readonly short sequence;
+ private readonly int nameIndex;
+ private readonly string name;
+ private int lazyPseudoToken;
+
+ internal ParameterBuilder(ModuleBuilder moduleBuilder, int sequence, ParameterAttributes attribs, string name)
+ {
+ this.moduleBuilder = moduleBuilder;
+ this.flags = (short)attribs;
+ this.sequence = (short)sequence;
+ this.nameIndex = name == null ? 0 : moduleBuilder.Strings.Add(name);
+ this.name = name;
+ }
+
+ internal int PseudoToken
+ {
+ get
+ {
+ if (lazyPseudoToken == 0)
+ {
+ // we lazily create the token, because if we don't need it we don't want the token fixup cost
+ lazyPseudoToken = moduleBuilder.AllocPseudoToken();
+ }
+ return lazyPseudoToken;
+ }
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public int Position
+ {
+ get { return sequence - 1; }
+ }
+
+ public int Attributes
+ {
+ get { return flags; }
+ }
+
+ public bool IsIn
+ {
+ get { return (flags & (short)ParameterAttributes.In) != 0; }
+ }
+
+ public bool IsOut
+ {
+ get { return (flags & (short)ParameterAttributes.Out) != 0; }
+ }
+
+ public bool IsOptional
+ {
+ get { return (flags & (short)ParameterAttributes.Optional) != 0; }
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customAttributeBuilder)
+ {
+ Universe u = moduleBuilder.universe;
+ if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_InAttribute)
+ {
+ flags |= (short)ParameterAttributes.In;
+ }
+ else if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_OutAttribute)
+ {
+ flags |= (short)ParameterAttributes.Out;
+ }
+ else if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_OptionalAttribute)
+ {
+ flags |= (short)ParameterAttributes.Optional;
+ }
+ else if (customAttributeBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_MarshalAsAttribute)
+ {
+ MarshalSpec.SetMarshalAsAttribute(moduleBuilder, PseudoToken, customAttributeBuilder);
+ flags |= (short)ParameterAttributes.HasFieldMarshal;
+ }
+ else
+ {
+ moduleBuilder.SetCustomAttribute(PseudoToken, customAttributeBuilder);
+ }
+ }
+
+ public void SetConstant(object defaultValue)
+ {
+ flags |= (short)ParameterAttributes.HasDefault;
+ moduleBuilder.AddConstant(PseudoToken, defaultValue);
+ }
+
+ internal void WriteParamRecord(MetadataWriter mw)
+ {
+ mw.Write(flags);
+ mw.Write(sequence);
+ mw.WriteStringIndex(nameIndex);
+ }
+
+ internal void FixupToken(int parameterToken)
+ {
+ if (lazyPseudoToken != 0)
+ {
+ moduleBuilder.RegisterTokenFixup(lazyPseudoToken, parameterToken);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class PropertyBuilder : PropertyInfo
+ {
+ private readonly TypeBuilder typeBuilder;
+ private readonly string name;
+ private PropertyAttributes attributes;
+ private PropertySignature sig;
+ private MethodBuilder getter;
+ private MethodBuilder setter;
+ private List<MethodBuilder> otherMethods;
+ private int lazyPseudoToken;
+ private bool patchCallingConvention;
+
+ internal PropertyBuilder(TypeBuilder typeBuilder, string name, PropertyAttributes attributes, PropertySignature sig, bool patchCallingConvention)
+ {
+ this.typeBuilder = typeBuilder;
+ this.name = name;
+ this.attributes = attributes;
+ this.sig = sig;
+ this.patchCallingConvention = patchCallingConvention;
+ }
+
+ internal override PropertySignature PropertySignature
+ {
+ get { return sig; }
+ }
+
+ private void PatchCallingConvention(MethodBuilder mdBuilder)
+ {
+ if (patchCallingConvention && !mdBuilder.IsStatic)
+ {
+ sig.HasThis = true;
+ }
+ }
+
+ public void SetGetMethod(MethodBuilder mdBuilder)
+ {
+ PatchCallingConvention(mdBuilder);
+ getter = mdBuilder;
+ }
+
+ public void SetSetMethod(MethodBuilder mdBuilder)
+ {
+ PatchCallingConvention(mdBuilder);
+ setter = mdBuilder;
+ }
+
+ public void AddOtherMethod(MethodBuilder mdBuilder)
+ {
+ PatchCallingConvention(mdBuilder);
+ if (otherMethods == null)
+ {
+ otherMethods = new List<MethodBuilder>();
+ }
+ otherMethods.Add(mdBuilder);
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ Universe u = typeBuilder.ModuleBuilder.universe;
+ if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+ {
+ attributes |= PropertyAttributes.SpecialName;
+ }
+ else
+ {
+ if (lazyPseudoToken == 0)
+ {
+ lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+ }
+ typeBuilder.ModuleBuilder.SetCustomAttribute(lazyPseudoToken, customBuilder);
+ }
+ }
+
+ public override object GetRawConstantValue()
+ {
+ if (lazyPseudoToken != 0)
+ {
+ return typeBuilder.ModuleBuilder.Constant.GetRawConstantValue(typeBuilder.ModuleBuilder, lazyPseudoToken);
+ }
+ throw new InvalidOperationException();
+ }
+
+ public override PropertyAttributes Attributes
+ {
+ get { return attributes; }
+ }
+
+ public override bool CanRead
+ {
+ get { return getter != null; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return setter != null; }
+ }
+
+ public override MethodInfo GetGetMethod(bool nonPublic)
+ {
+ return nonPublic || (getter != null && getter.IsPublic) ? getter : null;
+ }
+
+ public override MethodInfo GetSetMethod(bool nonPublic)
+ {
+ return nonPublic || (setter != null && setter.IsPublic) ? setter : null;
+ }
+
+ public override MethodInfo[] GetAccessors(bool nonPublic)
+ {
+ List<MethodInfo> list = new List<MethodInfo>();
+ AddAccessor(list, nonPublic, getter);
+ AddAccessor(list, nonPublic, setter);
+ if (otherMethods != null)
+ {
+ foreach (MethodInfo method in otherMethods)
+ {
+ AddAccessor(list, nonPublic, method);
+ }
+ }
+ return list.ToArray();
+ }
+
+ private static void AddAccessor(List<MethodInfo> list, bool nonPublic, MethodInfo method)
+ {
+ if (method != null && (nonPublic || method.IsPublic))
+ {
+ list.Add(method);
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeBuilder; }
+ }
+
+ public override string Name
+ {
+ get { return name; }
+ }
+
+ public override Module Module
+ {
+ get { return typeBuilder.Module; }
+ }
+
+ public void SetConstant(object defaultValue)
+ {
+ if (lazyPseudoToken == 0)
+ {
+ lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
+ }
+ attributes |= PropertyAttributes.HasDefault;
+ typeBuilder.ModuleBuilder.AddConstant(lazyPseudoToken, defaultValue);
+ }
+
+ internal void Bake()
+ {
+ PropertyTable.Record rec = new PropertyTable.Record();
+ rec.Flags = (short)attributes;
+ rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name);
+ rec.Type = typeBuilder.ModuleBuilder.GetSignatureBlobIndex(sig);
+ int token = 0x17000000 | typeBuilder.ModuleBuilder.Property.AddRecord(rec);
+
+ if (lazyPseudoToken != 0)
+ {
+ typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token);
+ }
+
+ if (getter != null)
+ {
+ AddMethodSemantics(MethodSemanticsTable.Getter, getter.MetadataToken, token);
+ }
+ if (setter != null)
+ {
+ AddMethodSemantics(MethodSemanticsTable.Setter, setter.MetadataToken, token);
+ }
+ if (otherMethods != null)
+ {
+ foreach (MethodBuilder method in otherMethods)
+ {
+ AddMethodSemantics(MethodSemanticsTable.Other, method.MetadataToken, token);
+ }
+ }
+ }
+
+ private void AddMethodSemantics(short semantics, int methodToken, int propertyToken)
+ {
+ MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record();
+ rec.Semantics = semantics;
+ rec.Method = methodToken;
+ rec.Association = propertyToken;
+ typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec);
+ }
+
+ internal override bool IsPublic
+ {
+ get
+ {
+ if ((getter != null && getter.IsPublic) || (setter != null && setter.IsPublic))
+ {
+ return true;
+ }
+ if (otherMethods != null)
+ {
+ foreach (MethodBuilder method in otherMethods)
+ {
+ if (method.IsPublic)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ internal override bool IsStatic
+ {
+ get
+ {
+ if ((getter != null && getter.IsStatic) || (setter != null && setter.IsStatic))
+ {
+ return true;
+ }
+ if (otherMethods != null)
+ {
+ foreach (MethodBuilder method in otherMethods)
+ {
+ if (method.IsStatic)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008, 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using IKVM.Reflection;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class SignatureHelper
+ {
+ private readonly ModuleBuilder module;
+ private readonly byte type;
+ private readonly List<Type> args = new List<Type>();
+ private readonly List<LocalBuilder> locals = new List<LocalBuilder>();
+ private readonly List<Type[]> requiredCustomModifiers = new List<Type[]>();
+ private readonly List<Type[]> optionalCustomModifiers = new List<Type[]>();
+ private readonly List<Type> optionalArgs = new List<Type>();
+ private Type returnType;
+ private Type[] returnTypeRequiredCustomModifiers;
+ private Type[] returnTypeOptionalCustomModifiers;
+ private CallingConventions callingConvention;
+ private CallingConvention unmanagedCallConv;
+ private bool unmanaged;
+ private bool optional;
+
+ private SignatureHelper(ModuleBuilder module, byte type)
+ {
+ this.module = module;
+ this.type = type;
+ }
+
+ internal bool HasThis
+ {
+ get { return (callingConvention & CallingConventions.HasThis) != 0; }
+ }
+
+ internal Type ReturnType
+ {
+ get { return returnType; }
+ }
+
+ internal int ParameterCount
+ {
+ get { return args.Count + optionalArgs.Count; }
+ }
+
+ public static SignatureHelper GetFieldSigHelper(Module mod)
+ {
+ return new SignatureHelper(mod as ModuleBuilder, Signature.FIELD);
+ }
+
+ public static SignatureHelper GetLocalVarSigHelper()
+ {
+ return new SignatureHelper(null, Signature.LOCAL_SIG);
+ }
+
+ public static SignatureHelper GetLocalVarSigHelper(Module mod)
+ {
+ return new SignatureHelper(mod as ModuleBuilder, Signature.LOCAL_SIG);
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
+ {
+ SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, Signature.PROPERTY);
+ sig.returnType = returnType;
+ sig.returnTypeOptionalCustomModifiers = Type.EmptyTypes;
+ sig.returnTypeRequiredCustomModifiers = Type.EmptyTypes;
+ foreach (Type type in parameterTypes)
+ {
+ sig.AddArgument(type);
+ }
+ return sig;
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ return GetPropertySigHelper(mod, CallingConventions.Standard, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, Signature.PROPERTY);
+ sig.callingConvention = callingConvention;
+ sig.returnType = returnType;
+ sig.returnTypeOptionalCustomModifiers = requiredReturnTypeCustomModifiers;
+ sig.returnTypeRequiredCustomModifiers = optionalReturnTypeCustomModifiers;
+ sig.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+ return sig;
+ }
+
+ public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType)
+ {
+ return GetMethodSigHelper(null, unmanagedCallingConvention, returnType);
+ }
+
+ public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType)
+ {
+ return GetMethodSigHelper(null, callingConvention, returnType);
+ }
+
+ public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)
+ {
+ SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
+ sig.returnType = returnType;
+ sig.unmanaged = true;
+ sig.unmanagedCallConv = unmanagedCallConv;
+ return sig;
+ }
+
+ public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
+ {
+ SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
+ sig.returnType = returnType;
+ sig.callingConvention = callingConvention;
+ return sig;
+ }
+
+ public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
+ {
+ SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
+ sig.returnType = returnType;
+ sig.callingConvention = CallingConventions.Standard;
+ foreach (Type type in parameterTypes)
+ {
+ sig.AddArgument(type);
+ }
+ return sig;
+ }
+
+ public byte[] GetSignature()
+ {
+ if (module == null)
+ {
+ throw new NotSupportedException();
+ }
+ return GetSignature(module).ToArray();
+ }
+
+ internal ByteBuffer GetSignature(ModuleBuilder module)
+ {
+ ByteBuffer bb = new ByteBuffer(16);
+ switch (type)
+ {
+ case 0:
+ if (unmanaged)
+ {
+ Signature.WriteStandAloneMethodSig(module, bb, unmanagedCallConv, returnType, args.ToArray());
+ }
+ else
+ {
+ Signature.WriteStandAloneMethodSig(module, bb, callingConvention, returnType, args.ToArray(), optionalArgs.ToArray());
+ }
+ break;
+ case Signature.FIELD:
+ FieldSignature.Create(args[0], optionalCustomModifiers[0], requiredCustomModifiers[0]).WriteSig(module, bb);
+ break;
+ case Signature.PROPERTY:
+ Signature.WritePropertySig(module, bb, callingConvention, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, args.ToArray(), requiredCustomModifiers.ToArray(), optionalCustomModifiers.ToArray());
+ break;
+ case Signature.LOCAL_SIG:
+ Signature.WriteLocalVarSig(module, bb, locals);
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ return bb;
+ }
+
+ public void AddSentinel()
+ {
+ optional = true;
+ callingConvention |= CallingConventions.VarArgs;
+ }
+
+ public void AddArgument(Type clsArgument)
+ {
+ AddArgument(clsArgument, false);
+ }
+
+ public void AddArgument(Type argument, bool pinned)
+ {
+ AddArgument(argument, pinned, Type.EmptyTypes, Type.EmptyTypes);
+ }
+
+ public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ AddArgument(argument, false, requiredCustomModifiers, optionalCustomModifiers);
+ }
+
+ private void AddArgument(Type argument, bool pinned, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ if (type == Signature.LOCAL_SIG)
+ {
+ locals.Add(new LocalBuilder(argument, 0, pinned));
+ }
+ else if (optional)
+ {
+ this.optionalArgs.Add(argument);
+ }
+ else
+ {
+ this.args.Add(argument);
+ this.requiredCustomModifiers.Add(requiredCustomModifiers);
+ this.optionalCustomModifiers.Add(optionalCustomModifiers);
+ }
+ }
+
+ public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ for (int i = 0; i < arguments.Length; i++)
+ {
+ AddArgument(arguments[i], false, requiredCustomModifiers[i], optionalCustomModifiers[i]);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+
+namespace IKVM.Reflection.Emit
+{
+ public struct EventToken
+ {
+ public static readonly EventToken Empty;
+ private readonly int token;
+
+ internal EventToken(int token)
+ {
+ this.token = token;
+ }
+
+ public int Token
+ {
+ get { return token; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj as EventToken? == this;
+ }
+
+ public override int GetHashCode()
+ {
+ return token;
+ }
+
+ public bool Equals(EventToken other)
+ {
+ return this == other;
+ }
+
+ public static bool operator ==(EventToken et1, EventToken et2)
+ {
+ return et1.token == et2.token;
+ }
+
+ public static bool operator !=(EventToken et1, EventToken et2)
+ {
+ return et1.token != et2.token;
+ }
+ }
+
+ public struct FieldToken
+ {
+ public static readonly FieldToken Empty;
+ private readonly int token;
+
+ internal FieldToken(int token)
+ {
+ this.token = token;
+ }
+
+ internal bool IsPseudoToken
+ {
+ get { return token < 0; }
+ }
+
+ public int Token
+ {
+ get { return token; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj as FieldToken? == this;
+ }
+
+ public override int GetHashCode()
+ {
+ return token;
+ }
+
+ public bool Equals(FieldToken other)
+ {
+ return this == other;
+ }
+
+ public static bool operator ==(FieldToken ft1, FieldToken ft2)
+ {
+ return ft1.token == ft2.token;
+ }
+
+ public static bool operator !=(FieldToken ft1, FieldToken ft2)
+ {
+ return ft1.token != ft2.token;
+ }
+ }
+
+ public struct MethodToken
+ {
+ public static readonly MethodToken Empty;
+ private readonly int token;
+
+ internal MethodToken(int token)
+ {
+ this.token = token;
+ }
+
+ internal bool IsPseudoToken
+ {
+ get { return token < 0; }
+ }
+
+ public int Token
+ {
+ get { return token; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj as MethodToken? == this;
+ }
+
+ public override int GetHashCode()
+ {
+ return token;
+ }
+
+ public bool Equals(MethodToken other)
+ {
+ return this == other;
+ }
+
+ public static bool operator ==(MethodToken mt1, MethodToken mt2)
+ {
+ return mt1.token == mt2.token;
+ }
+
+ public static bool operator !=(MethodToken mt1, MethodToken mt2)
+ {
+ return mt1.token != mt2.token;
+ }
+ }
+
+ public struct SignatureToken
+ {
+ public static readonly SignatureToken Empty;
+ private readonly int token;
+
+ internal SignatureToken(int token)
+ {
+ this.token = token;
+ }
+
+ public int Token
+ {
+ get { return token; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj as SignatureToken? == this;
+ }
+
+ public override int GetHashCode()
+ {
+ return token;
+ }
+
+ public bool Equals(SignatureToken other)
+ {
+ return this == other;
+ }
+
+ public static bool operator ==(SignatureToken st1, SignatureToken st2)
+ {
+ return st1.token == st2.token;
+ }
+
+ public static bool operator !=(SignatureToken st1, SignatureToken st2)
+ {
+ return st1.token != st2.token;
+ }
+ }
+
+ public struct StringToken
+ {
+ private readonly int token;
+
+ internal StringToken(int token)
+ {
+ this.token = token;
+ }
+
+ public int Token
+ {
+ get { return token; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj as StringToken? == this;
+ }
+
+ public override int GetHashCode()
+ {
+ return token;
+ }
+
+ public bool Equals(StringToken other)
+ {
+ return this == other;
+ }
+
+ public static bool operator ==(StringToken st1, StringToken st2)
+ {
+ return st1.token == st2.token;
+ }
+
+ public static bool operator !=(StringToken st1, StringToken st2)
+ {
+ return st1.token != st2.token;
+ }
+ }
+
+ public struct TypeToken
+ {
+ public static readonly TypeToken Empty;
+ private readonly int token;
+
+ internal TypeToken(int token)
+ {
+ this.token = token;
+ }
+
+ public int Token
+ {
+ get { return token; }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj as TypeToken? == this;
+ }
+
+ public override int GetHashCode()
+ {
+ return token;
+ }
+
+ public bool Equals(TypeToken other)
+ {
+ return this == other;
+ }
+
+ public static bool operator ==(TypeToken tt1, TypeToken tt2)
+ {
+ return tt1.token == tt2.token;
+ }
+
+ public static bool operator !=(TypeToken tt1, TypeToken tt2)
+ {
+ return tt1.token != tt2.token;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Writer;
+
+namespace IKVM.Reflection.Emit
+{
+ public sealed class GenericTypeParameterBuilder : Type
+ {
+ private readonly string name;
+ private readonly TypeBuilder type;
+ private readonly MethodBuilder method;
+ private readonly int paramPseudoIndex;
+ private readonly int position;
+ private int typeToken;
+ private Type baseType;
+ private GenericParameterAttributes attr;
+
+ internal GenericTypeParameterBuilder(string name, TypeBuilder type, MethodBuilder method, int position)
+ {
+ this.name = name;
+ this.type = type;
+ this.method = method;
+ this.position = position;
+ GenericParamTable.Record rec = new GenericParamTable.Record();
+ rec.Number = (short)position;
+ rec.Flags = 0;
+ rec.Owner = type != null ? type.MetadataToken : method.MetadataToken;
+ rec.Name = this.ModuleBuilder.Strings.Add(name);
+ this.paramPseudoIndex = this.ModuleBuilder.GenericParam.AddRecord(rec);
+ }
+
+ public override string AssemblyQualifiedName
+ {
+ get { return null; }
+ }
+
+ public override bool IsValueType
+ {
+ get { return (this.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; }
+ }
+
+ public override Type BaseType
+ {
+ get { return baseType; }
+ }
+
+ public override Type[] __GetDeclaredInterfaces()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return TypeAttributes.Public; }
+ }
+
+ public override string Namespace
+ {
+ get { return DeclaringType.Namespace; }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get { return this; }
+ }
+
+ public override string Name
+ {
+ get { return name; }
+ }
+
+ public override string FullName
+ {
+ get { return null; }
+ }
+
+ public override string ToString()
+ {
+ return this.Name;
+ }
+
+ private ModuleBuilder ModuleBuilder
+ {
+ get { return type != null ? type.ModuleBuilder : method.ModuleBuilder; }
+ }
+
+ public override Module Module
+ {
+ get { return ModuleBuilder; }
+ }
+
+ public override bool IsGenericParameter
+ {
+ get { return true; }
+ }
+
+ public override int GenericParameterPosition
+ {
+ get { return position; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return type; }
+ }
+
+ public override MethodBase DeclaringMethod
+ {
+ get { return method; }
+ }
+
+ public override Type[] GetGenericParameterConstraints()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ get
+ {
+ if (type != null)
+ {
+ type.CheckBaked();
+ }
+ else
+ {
+ method.CheckBaked();
+ }
+ return attr;
+ }
+ }
+
+ private void AddConstraint(Type type)
+ {
+ GenericParamConstraintTable.Record rec = new GenericParamConstraintTable.Record();
+ rec.Owner = paramPseudoIndex;
+ rec.Constraint = this.ModuleBuilder.GetTypeTokenForMemberRef(type);
+ this.ModuleBuilder.GenericParamConstraint.AddRecord(rec);
+ }
+
+ public void SetBaseTypeConstraint(Type baseTypeConstraint)
+ {
+ this.baseType = baseTypeConstraint;
+ AddConstraint(baseTypeConstraint);
+ }
+
+ public void SetInterfaceConstraints(params Type[] interfaceConstraints)
+ {
+ foreach (Type type in interfaceConstraints)
+ {
+ AddConstraint(type);
+ }
+ }
+
+ public void SetGenericParameterAttributes(GenericParameterAttributes genericParameterAttributes)
+ {
+ this.attr = genericParameterAttributes;
+ // for now we'll back patch the table
+ this.ModuleBuilder.GenericParam.PatchAttribute(paramPseudoIndex, genericParameterAttributes);
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ this.ModuleBuilder.SetCustomAttribute((GenericParamTable.Index << 24) | paramPseudoIndex, customBuilder);
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ internal override int GetModuleBuilderToken()
+ {
+ if (typeToken == 0)
+ {
+ ByteBuffer spec = new ByteBuffer(5);
+ Signature.WriteTypeSpec(this.ModuleBuilder, spec, this);
+ typeToken = 0x1B000000 | this.ModuleBuilder.TypeSpec.AddRecord(this.ModuleBuilder.Blobs.Add(spec));
+ }
+ return typeToken;
+ }
+
+ internal override Type BindTypeParameters(IGenericBinder binder)
+ {
+ if (type != null)
+ {
+ return binder.BindTypeParameter(this);
+ }
+ else
+ {
+ return binder.BindMethodParameter(this);
+ }
+ }
+ }
+
+ public sealed class TypeBuilder : Type, ITypeOwner
+ {
+ public const int UnspecifiedTypeSize = 0;
+ private readonly ITypeOwner owner;
+ private readonly int token;
+ private int extends;
+ private Type baseType;
+ private readonly int typeName;
+ private readonly int typeNameSpace;
+ private readonly string nameOrFullName;
+ private readonly List<MethodBuilder> methods = new List<MethodBuilder>();
+ private readonly List<FieldBuilder> fields = new List<FieldBuilder>();
+ private List<PropertyBuilder> properties;
+ private List<EventBuilder> events;
+ private TypeAttributes attribs;
+ private TypeFlags typeFlags;
+ private GenericTypeParameterBuilder[] gtpb;
+ private List<CustomAttributeBuilder> declarativeSecurity;
+ private List<Type> interfaces;
+
+ [Flags]
+ private enum TypeFlags
+ {
+ IsGenericTypeDefinition = 1,
+ HasNestedTypes = 2,
+ Baked = 4,
+ }
+
+ internal TypeBuilder(ITypeOwner owner, string name, Type baseType, TypeAttributes attribs)
+ {
+ this.owner = owner;
+ this.token = this.ModuleBuilder.TypeDef.AllocToken();
+ this.nameOrFullName = TypeNameParser.Escape(name);
+ SetParent(baseType);
+ this.attribs = attribs;
+ if (!this.IsNested)
+ {
+ int lastdot = name.LastIndexOf('.');
+ if (lastdot > 0)
+ {
+ this.typeNameSpace = this.ModuleBuilder.Strings.Add(name.Substring(0, lastdot));
+ name = name.Substring(lastdot + 1);
+ }
+ }
+ this.typeName = this.ModuleBuilder.Strings.Add(name);
+ }
+
+ public ConstructorBuilder DefineDefaultConstructor(MethodAttributes attributes)
+ {
+ ConstructorBuilder cb = DefineConstructor(attributes, CallingConventions.Standard, Type.EmptyTypes);
+ ILGenerator ilgen = cb.GetILGenerator();
+ ilgen.Emit(OpCodes.Ldarg_0);
+ ilgen.Emit(OpCodes.Call, baseType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
+ ilgen.Emit(OpCodes.Ret);
+ return cb;
+ }
+
+ public ConstructorBuilder DefineConstructor(MethodAttributes attribs, CallingConventions callConv, Type[] parameterTypes)
+ {
+ return DefineConstructor(attribs, callConv, parameterTypes, null, null);
+ }
+
+ public ConstructorBuilder DefineConstructor(MethodAttributes attribs, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ attribs |= MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
+ string name = (attribs & MethodAttributes.Static) == 0 ? ConstructorInfo.ConstructorName : ConstructorInfo.TypeConstructorName;
+ MethodBuilder mb = DefineMethod(name, attribs, callingConvention, null, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
+ return new ConstructorBuilder(mb);
+ }
+
+ public ConstructorBuilder DefineTypeInitializer()
+ {
+ MethodBuilder mb = DefineMethod(ConstructorInfo.TypeConstructorName, MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, null, Type.EmptyTypes);
+ return new ConstructorBuilder(mb);
+ }
+
+ private MethodBuilder CreateMethodBuilder(string name, MethodAttributes attributes, CallingConventions callingConvention)
+ {
+ this.ModuleBuilder.MethodDef.AddVirtualRecord();
+ MethodBuilder mb = new MethodBuilder(this, name, attributes, callingConvention);
+ methods.Add(mb);
+ return mb;
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attribs)
+ {
+ return DefineMethod(name, attribs, CallingConventions.Standard);
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attribs, CallingConventions callingConvention)
+ {
+ return CreateMethodBuilder(name, attribs, callingConvention);
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attribs, Type returnType, Type[] parameterTypes)
+ {
+ return DefineMethod(name, attribs, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null);
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return DefineMethod(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null);
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ MethodBuilder mb = CreateMethodBuilder(name, attributes, callingConvention);
+ mb.SetSignature(returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+ return mb;
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return DefinePInvokeMethod(name, dllName, null, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, nativeCallConv, nativeCharSet);
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, nativeCallConv, nativeCharSet);
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers,
+ CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ MethodBuilder mb = DefineMethod(name, attributes | MethodAttributes.PinvokeImpl, callingConvention,
+ returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+ mb.SetDllImportPseudoCustomAttribute(dllName, entryName, nativeCallConv, nativeCharSet, null, null, null, null, null);
+ return mb;
+ }
+
+ public void DefineMethodOverride(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
+ {
+ MethodImplTable.Record rec = new MethodImplTable.Record();
+ rec.Class = token;
+ rec.MethodBody = this.ModuleBuilder.GetMethodToken(methodInfoBody).Token;
+ rec.MethodDeclaration = this.ModuleBuilder.GetMethodToken(methodInfoDeclaration).Token;
+ this.ModuleBuilder.MethodImpl.AddRecord(rec);
+ }
+
+ public FieldBuilder DefineField(string name, Type fieldType, FieldAttributes attribs)
+ {
+ return DefineField(name, fieldType, null, null, attribs);
+ }
+
+ public FieldBuilder DefineField(string fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
+ {
+ FieldBuilder fb = new FieldBuilder(this, fieldName, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
+ fields.Add(fb);
+ return fb;
+ }
+
+ public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ return DefineProperty(name, attributes, returnType, null, null, parameterTypes, null, null);
+ }
+
+ public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ return DefinePropertyImpl(name, attributes, CallingConventions.Standard, true, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+ }
+
+ public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ return DefinePropertyImpl(name, attributes, callingConvention, false, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+ }
+
+ private PropertyBuilder DefinePropertyImpl(string name, PropertyAttributes attributes, CallingConventions callingConvention, bool patchCallingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ if (properties == null)
+ {
+ properties = new List<PropertyBuilder>();
+ }
+ PropertySignature sig = PropertySignature.Create(callingConvention, returnType, returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers,
+ parameterTypes, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers);
+ PropertyBuilder pb = new PropertyBuilder(this, name, attributes, sig, patchCallingConvention);
+ properties.Add(pb);
+ return pb;
+ }
+
+ public EventBuilder DefineEvent(string name, EventAttributes attributes, Type eventtype)
+ {
+ if (events == null)
+ {
+ events = new List<EventBuilder>();
+ }
+ EventBuilder eb = new EventBuilder(this, name, attributes, eventtype);
+ events.Add(eb);
+ return eb;
+ }
+
+ public TypeBuilder DefineNestedType(string name)
+ {
+ return DefineNestedType(name, TypeAttributes.Class | TypeAttributes.NestedPrivate);
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attribs)
+ {
+ return DefineNestedType(name, attribs, null);
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
+ {
+ TypeBuilder tb = DefineNestedType(name, attr, parent);
+ foreach (Type iface in interfaces)
+ {
+ tb.AddInterfaceImplementation(iface);
+ }
+ return tb;
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent)
+ {
+ this.typeFlags |= TypeFlags.HasNestedTypes;
+ return this.ModuleBuilder.DefineNestedTypeHelper(this, name, attr, parent, PackingSize.Unspecified, 0);
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, int typeSize)
+ {
+ this.typeFlags |= TypeFlags.HasNestedTypes;
+ return this.ModuleBuilder.DefineNestedTypeHelper(this, name, attr, parent, PackingSize.Unspecified, typeSize);
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, PackingSize packSize)
+ {
+ this.typeFlags |= TypeFlags.HasNestedTypes;
+ return this.ModuleBuilder.DefineNestedTypeHelper(this, name, attr, parent, packSize, 0);
+ }
+
+ public void SetParent(Type parent)
+ {
+ baseType = parent;
+ }
+
+ public void AddInterfaceImplementation(Type interfaceType)
+ {
+ if (interfaces == null)
+ {
+ interfaces = new List<Type>();
+ }
+ interfaces.Add(interfaceType);
+ }
+
+ public int Size
+ {
+ get
+ {
+ for (int i = 0; i < this.ModuleBuilder.ClassLayout.records.Length; i++)
+ {
+ if (this.ModuleBuilder.ClassLayout.records[i].Parent == token)
+ {
+ return this.ModuleBuilder.ClassLayout.records[i].ClassSize;
+ }
+ }
+ return 0;
+ }
+ }
+
+ public PackingSize PackingSize
+ {
+ get
+ {
+ for (int i = 0; i < this.ModuleBuilder.ClassLayout.records.Length; i++)
+ {
+ if (this.ModuleBuilder.ClassLayout.records[i].Parent == token)
+ {
+ return (PackingSize)this.ModuleBuilder.ClassLayout.records[i].PackingSize;
+ }
+ }
+ return PackingSize.Unspecified;
+ }
+ }
+
+ private void SetStructLayoutPseudoCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ object val = customBuilder.GetConstructorArgument(0);
+ LayoutKind layout;
+ if (val is short)
+ {
+ layout = (LayoutKind)(short)val;
+ }
+ else
+ {
+ layout = (LayoutKind)val;
+ }
+ int? pack = (int?)customBuilder.GetFieldValue("Pack");
+ int? size = (int?)customBuilder.GetFieldValue("Size");
+ if (pack.HasValue || size.HasValue)
+ {
+ ClassLayoutTable.Record rec = new ClassLayoutTable.Record();
+ rec.PackingSize = (short)(pack ?? 0);
+ rec.ClassSize = size ?? 0;
+ rec.Parent = token;
+ this.ModuleBuilder.ClassLayout.AddRecord(rec);
+ }
+ attribs &= ~TypeAttributes.LayoutMask;
+ switch (layout)
+ {
+ case LayoutKind.Auto:
+ attribs |= TypeAttributes.AutoLayout;
+ break;
+ case LayoutKind.Explicit:
+ attribs |= TypeAttributes.ExplicitLayout;
+ break;
+ case LayoutKind.Sequential:
+ attribs |= TypeAttributes.SequentialLayout;
+ break;
+ }
+ CharSet? charSet = customBuilder.GetFieldValue<CharSet>("CharSet");
+ attribs &= ~TypeAttributes.StringFormatMask;
+ switch (charSet ?? CharSet.None)
+ {
+ case CharSet.None:
+ case CharSet.Ansi:
+ attribs |= TypeAttributes.AnsiClass;
+ break;
+ case CharSet.Auto:
+ attribs |= TypeAttributes.AutoClass;
+ break;
+ case CharSet.Unicode:
+ attribs |= TypeAttributes.UnicodeClass;
+ break;
+ }
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ Universe u = this.ModuleBuilder.universe;
+ Type type = customBuilder.Constructor.DeclaringType;
+ if (type == u.System_Runtime_InteropServices_StructLayoutAttribute)
+ {
+ SetStructLayoutPseudoCustomAttribute(customBuilder.DecodeBlob(this.Assembly));
+ }
+ else if (type == u.System_SerializableAttribute)
+ {
+ attribs |= TypeAttributes.Serializable;
+ }
+ else if (type == u.System_Runtime_InteropServices_ComImportAttribute)
+ {
+ attribs |= TypeAttributes.Import;
+ }
+ else if (type == u.System_Runtime_CompilerServices_SpecialNameAttribute)
+ {
+ attribs |= TypeAttributes.SpecialName;
+ }
+ else
+ {
+ if (type == u.System_Security_SuppressUnmanagedCodeSecurityAttribute)
+ {
+ attribs |= TypeAttributes.HasSecurity;
+ }
+ this.ModuleBuilder.SetCustomAttribute(token, customBuilder);
+ }
+ }
+
+ public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
+ {
+ attribs |= TypeAttributes.HasSecurity;
+ if (declarativeSecurity == null)
+ {
+ declarativeSecurity = new List<CustomAttributeBuilder>();
+ }
+ declarativeSecurity.Add(customBuilder);
+ }
+
+ public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
+ {
+ this.ModuleBuilder.AddDeclarativeSecurity(token, securityAction, permissionSet);
+ this.attribs |= TypeAttributes.HasSecurity;
+ }
+
+ public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
+ {
+ typeFlags |= TypeFlags.IsGenericTypeDefinition;
+ gtpb = new GenericTypeParameterBuilder[names.Length];
+ for (int i = 0; i < names.Length; i++)
+ {
+ gtpb[i] = new GenericTypeParameterBuilder(names[i], this, null, i);
+ }
+ return (GenericTypeParameterBuilder[])gtpb.Clone();
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ return Util.Copy(gtpb);
+ }
+
+ public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+ {
+ return gtpb == null ? Empty<Type[]>.Array : Util.Copy(new Type[gtpb.Length][]);
+ }
+
+ public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+ {
+ return gtpb == null ? Empty<Type[]>.Array : Util.Copy(new Type[gtpb.Length][]);
+ }
+
+ internal override Type GetGenericTypeArgument(int index)
+ {
+ return gtpb[index];
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get { return gtpb != null; }
+ }
+
+ public override Type GetGenericTypeDefinition()
+ {
+ return this;
+ }
+
+ public Type CreateType()
+ {
+ if ((typeFlags & TypeFlags.Baked) != 0)
+ {
+ // .NET allows multiple invocations (subsequent invocations return the same baked type)
+ throw new NotImplementedException();
+ }
+ typeFlags |= TypeFlags.Baked;
+ foreach (MethodBuilder mb in methods)
+ {
+ mb.Bake();
+ }
+ if (declarativeSecurity != null)
+ {
+ this.ModuleBuilder.AddDeclarativeSecurity(token, declarativeSecurity);
+ }
+ if (baseType != null)
+ {
+ extends = this.ModuleBuilder.GetTypeToken(baseType).Token;
+ }
+ if (interfaces != null)
+ {
+ foreach (Type interfaceType in interfaces)
+ {
+ InterfaceImplTable.Record rec = new InterfaceImplTable.Record();
+ rec.Class = token;
+ rec.Interface = this.ModuleBuilder.GetTypeToken(interfaceType).Token;
+ this.ModuleBuilder.InterfaceImpl.AddRecord(rec);
+ }
+ }
+ return new BakedType(this);
+ }
+
+ internal void PopulatePropertyAndEventTables()
+ {
+ if (properties != null)
+ {
+ PropertyMapTable.Record rec = new PropertyMapTable.Record();
+ rec.Parent = token;
+ rec.PropertyList = this.ModuleBuilder.Property.RowCount + 1;
+ this.ModuleBuilder.PropertyMap.AddRecord(rec);
+ foreach (PropertyBuilder pb in properties)
+ {
+ pb.Bake();
+ }
+ }
+ if (events != null)
+ {
+ EventMapTable.Record rec = new EventMapTable.Record();
+ rec.Parent = token;
+ rec.EventList = this.ModuleBuilder.Event.RowCount + 1;
+ this.ModuleBuilder.EventMap.AddRecord(rec);
+ foreach (EventBuilder eb in events)
+ {
+ eb.Bake();
+ }
+ }
+ }
+
+ public override Type BaseType
+ {
+ get { return baseType; }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ if (this.IsNested)
+ {
+ return this.DeclaringType.FullName + "+" + nameOrFullName;
+ }
+ else
+ {
+ return nameOrFullName;
+ }
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ if (this.IsNested)
+ {
+ return nameOrFullName;
+ }
+ else
+ {
+ return base.Name;
+ }
+ }
+ }
+
+ public override string Namespace
+ {
+ get
+ {
+ // for some reason, TypeBuilder doesn't return null (and mcs depends on this)
+ return base.Namespace ?? "";
+ }
+ }
+
+ internal string GetBakedNamespace()
+ {
+ // if you refer to the TypeBuilder via its baked Type, Namespace will return null
+ // for the empty namespace (instead of "" like TypeBuilder.Namespace above does)
+ return base.Namespace;
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return attribs; }
+ }
+
+ public void __SetAttributes(TypeAttributes attributes)
+ {
+ this.attribs = attributes;
+ }
+
+ public override Type[] __GetDeclaredInterfaces()
+ {
+ return Util.ToArray(interfaces, Type.EmptyTypes);
+ }
+
+ public override MethodBase[] __GetDeclaredMethods()
+ {
+ MethodBase[] methods = new MethodBase[this.methods.Count];
+ for (int i = 0; i < methods.Length; i++)
+ {
+ MethodBuilder mb = this.methods[i];
+ if (mb.IsConstructor)
+ {
+ methods[i] = new ConstructorInfoImpl(mb);
+ }
+ else
+ {
+ methods[i] = mb;
+ }
+ }
+ return methods;
+ }
+
+ public override StructLayoutAttribute StructLayoutAttribute
+ {
+ get
+ {
+ StructLayoutAttribute attr;
+ if ((attribs & TypeAttributes.ExplicitLayout) != 0)
+ {
+ attr = new StructLayoutAttribute(LayoutKind.Explicit);
+ attr.Pack = 8;
+ attr.Size = 0;
+ this.ModuleBuilder.ClassLayout.GetLayout(token, ref attr.Pack, ref attr.Size);
+ }
+ else
+ {
+ attr = new StructLayoutAttribute((attribs & TypeAttributes.SequentialLayout) != 0 ? LayoutKind.Sequential : LayoutKind.Auto);
+ attr.Pack = 8;
+ attr.Size = 0;
+ }
+ switch (attribs & TypeAttributes.StringFormatMask)
+ {
+ case TypeAttributes.AutoClass:
+ attr.CharSet = CharSet.Auto;
+ break;
+ case TypeAttributes.UnicodeClass:
+ attr.CharSet = CharSet.Unicode;
+ break;
+ case TypeAttributes.AnsiClass:
+ attr.CharSet = CharSet.Ansi;
+ break;
+ }
+ return attr;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return owner as TypeBuilder; }
+ }
+
+ public override bool IsGenericType
+ {
+ get { return IsGenericTypeDefinition; }
+ }
+
+ public override bool IsGenericTypeDefinition
+ {
+ get { return (typeFlags & TypeFlags.IsGenericTypeDefinition) != 0; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return token; }
+ }
+
+ public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
+ {
+ return DefineInitializedData(name, new byte[size], attributes);
+ }
+
+ public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
+ {
+ Type fieldType = this.ModuleBuilder.GetType("$ArrayType$" + data.Length);
+ if (fieldType == null)
+ {
+ TypeBuilder tb = this.ModuleBuilder.DefineType("$ArrayType$" + data.Length, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.ExplicitLayout, this.Module.universe.System_ValueType, PackingSize.Size1, data.Length);
+ tb.CreateType();
+ fieldType = tb;
+ }
+ FieldBuilder fb = DefineField(name, fieldType, attributes | FieldAttributes.Static);
+ fb.__SetDataAndRVA(data);
+ return fb;
+ }
+
+ public static MethodInfo GetMethod(Type type, MethodInfo method)
+ {
+ return new GenericMethodInstance(type, method, null);
+ }
+
+ public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor)
+ {
+ return new ConstructorInfoImpl(GetMethod(type, constructor.GetMethodInfo()));
+ }
+
+ public static FieldInfo GetField(Type type, FieldInfo field)
+ {
+ return new GenericFieldInstance(type, field);
+ }
+
+ public override Module Module
+ {
+ get { return owner.ModuleBuilder; }
+ }
+
+ public TypeToken TypeToken
+ {
+ get { return new TypeToken(token); }
+ }
+
+ internal void WriteTypeDefRecord(MetadataWriter mw, ref int fieldList, ref int methodList)
+ {
+ mw.Write((int)attribs);
+ mw.WriteStringIndex(typeName);
+ mw.WriteStringIndex(typeNameSpace);
+ mw.WriteTypeDefOrRef(extends);
+ mw.WriteField(fieldList);
+ mw.WriteMethodDef(methodList);
+ methodList += methods.Count;
+ fieldList += fields.Count;
+ }
+
+ internal void WriteMethodDefRecords(int baseRVA, MetadataWriter mw, ref int paramList)
+ {
+ foreach (MethodBuilder mb in methods)
+ {
+ mb.WriteMethodDefRecord(baseRVA, mw, ref paramList);
+ }
+ }
+
+ internal void ResolveMethodAndFieldTokens(ref int methodToken, ref int fieldToken, ref int parameterToken)
+ {
+ foreach (MethodBuilder method in methods)
+ {
+ method.FixupToken(methodToken++, ref parameterToken);
+ }
+ foreach (FieldBuilder field in fields)
+ {
+ field.FixupToken(fieldToken++);
+ }
+ }
+
+ internal void WriteParamRecords(MetadataWriter mw)
+ {
+ foreach (MethodBuilder mb in methods)
+ {
+ mb.WriteParamRecords(mw);
+ }
+ }
+
+ internal void WriteFieldRecords(MetadataWriter mw)
+ {
+ foreach (FieldBuilder fb in fields)
+ {
+ fb.WriteFieldRecords(mw);
+ }
+ }
+
+ internal ModuleBuilder ModuleBuilder
+ {
+ get { return owner.ModuleBuilder; }
+ }
+
+ ModuleBuilder ITypeOwner.ModuleBuilder
+ {
+ get { return owner.ModuleBuilder; }
+ }
+
+ internal override int GetModuleBuilderToken()
+ {
+ return token;
+ }
+
+ internal bool HasNestedTypes
+ {
+ get { return (typeFlags & TypeFlags.HasNestedTypes) != 0; }
+ }
+
+ // helper for ModuleBuilder.ResolveMethod()
+ internal MethodBase LookupMethod(int token)
+ {
+ foreach (MethodBuilder method in methods)
+ {
+ if (method.MetadataToken == token)
+ {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ public bool IsCreated()
+ {
+ return (typeFlags & TypeFlags.Baked) != 0;
+ }
+
+ internal override void CheckBaked()
+ {
+ if ((typeFlags & TypeFlags.Baked) == 0)
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ public override Type[] __GetDeclaredTypes()
+ {
+ if (this.HasNestedTypes)
+ {
+ List<Type> types = new List<Type>();
+ List<int> classes = this.ModuleBuilder.NestedClass.GetNestedClasses(token);
+ foreach (int nestedClass in classes)
+ {
+ types.Add(this.ModuleBuilder.ResolveType(nestedClass));
+ }
+ return types.ToArray();
+ }
+ else
+ {
+ return Type.EmptyTypes;
+ }
+ }
+
+ public override FieldInfo[] __GetDeclaredFields()
+ {
+ return Util.ToArray(fields, Empty<FieldInfo>.Array);
+ }
+
+ public override EventInfo[] __GetDeclaredEvents()
+ {
+ return Util.ToArray(events, Empty<EventInfo>.Array);
+ }
+
+ public override PropertyInfo[] __GetDeclaredProperties()
+ {
+ return Util.ToArray(properties, Empty<PropertyInfo>.Array);
+ }
+
+ internal override bool IsModulePseudoType
+ {
+ get { return token == 0x02000001; }
+ }
+ }
+
+ sealed class BakedType : Type
+ {
+ private readonly TypeBuilder typeBuilder;
+
+ internal BakedType(TypeBuilder typeBuilder)
+ {
+ this.typeBuilder = typeBuilder;
+ }
+
+ public override string AssemblyQualifiedName
+ {
+ get { return typeBuilder.AssemblyQualifiedName; }
+ }
+
+ public override Type BaseType
+ {
+ get { return typeBuilder.BaseType; }
+ }
+
+ public override string Name
+ {
+ get { return typeBuilder.Name; }
+ }
+
+ public override string Namespace
+ {
+ get { return typeBuilder.GetBakedNamespace(); }
+ }
+
+ public override string FullName
+ {
+ get { return typeBuilder.FullName; }
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return typeBuilder.Attributes; }
+ }
+
+ public override Type[] __GetDeclaredInterfaces()
+ {
+ return typeBuilder.__GetDeclaredInterfaces();
+ }
+
+ public override MethodBase[] __GetDeclaredMethods()
+ {
+ return typeBuilder.__GetDeclaredMethods();
+ }
+
+ public override __MethodImplMap __GetMethodImplMap()
+ {
+ return typeBuilder.__GetMethodImplMap();
+ }
+
+ public override FieldInfo[] __GetDeclaredFields()
+ {
+ return typeBuilder.__GetDeclaredFields();
+ }
+
+ public override EventInfo[] __GetDeclaredEvents()
+ {
+ return typeBuilder.__GetDeclaredEvents();
+ }
+
+ public override PropertyInfo[] __GetDeclaredProperties()
+ {
+ return typeBuilder.__GetDeclaredProperties();
+ }
+
+ public override Type[] __GetDeclaredTypes()
+ {
+ return typeBuilder.__GetDeclaredTypes();
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeBuilder.DeclaringType; }
+ }
+
+ public override StructLayoutAttribute StructLayoutAttribute
+ {
+ get { return typeBuilder.StructLayoutAttribute; }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ // Type.Equals/GetHashCode relies on this
+ get { return typeBuilder; }
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ return typeBuilder.GetGenericArguments();
+ }
+
+ internal override Type GetGenericTypeArgument(int index)
+ {
+ return typeBuilder.GetGenericTypeArgument(index);
+ }
+
+ public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+ {
+ return typeBuilder.__GetGenericArgumentsOptionalCustomModifiers();
+ }
+
+ public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+ {
+ return typeBuilder.__GetGenericArgumentsRequiredCustomModifiers();
+ }
+
+ public override bool IsGenericType
+ {
+ get { return typeBuilder.IsGenericType; }
+ }
+
+ public override bool IsGenericTypeDefinition
+ {
+ get { return typeBuilder.IsGenericTypeDefinition; }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get { return typeBuilder.ContainsGenericParameters; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return typeBuilder.MetadataToken; }
+ }
+
+ public override Module Module
+ {
+ get { return typeBuilder.Module; }
+ }
+
+ internal override int GetModuleBuilderToken()
+ {
+ return typeBuilder.GetModuleBuilderToken();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+ [Flags]
+ public enum AssemblyNameFlags
+ {
+ None = 0,
+ PublicKey = 1,
+ Retargetable = 256,
+ EnableJITcompileOptimizer = 16384,
+ EnableJITcompileTracking = 32768,
+ }
+
+ [Flags]
+ public enum BindingFlags
+ {
+ Default = 0,
+ DeclaredOnly = 2,
+ Instance = 4,
+ Static = 8,
+ Public = 16,
+ NonPublic = 32,
+ FlattenHierarchy = 64,
+ }
+
+ [Flags]
+ public enum CallingConventions
+ {
+ Standard = 1,
+ VarArgs = 2,
+ Any = 3,
+ HasThis = 32,
+ ExplicitThis = 64,
+ }
+
+ [Flags]
+ public enum EventAttributes
+ {
+ None = 0,
+ SpecialName = 512,
+ RTSpecialName = 1024,
+ ReservedMask = 1024,
+ }
+
+ [Flags]
+ public enum FieldAttributes
+ {
+ PrivateScope = 0,
+ Private = 1,
+ FamANDAssem = 2,
+ Assembly = 3,
+ Family = 4,
+ FamORAssem = 5,
+ Public = 6,
+ FieldAccessMask = 7,
+ Static = 16,
+ InitOnly = 32,
+ Literal = 64,
+ NotSerialized = 128,
+ HasFieldRVA = 256,
+ SpecialName = 512,
+ RTSpecialName = 1024,
+ HasFieldMarshal = 4096,
+ PinvokeImpl = 8192,
+ HasDefault = 32768,
+ ReservedMask = 38144,
+ }
+
+ [Flags]
+ public enum GenericParameterAttributes
+ {
+ None = 0,
+ Covariant = 1,
+ Contravariant = 2,
+ VarianceMask = 3,
+ ReferenceTypeConstraint = 4,
+ NotNullableValueTypeConstraint = 8,
+ DefaultConstructorConstraint = 16,
+ SpecialConstraintMask = 28,
+ }
+
+ public enum ImageFileMachine
+ {
+ I386 = 332,
+ IA64 = 512,
+ AMD64 = 34404,
+ }
+
+ [FlagsAttribute]
+ public enum MemberTypes
+ {
+ Constructor = 0x01,
+ Event = 0x02,
+ Field = 0x04,
+ Method = 0x08,
+ Property = 0x10,
+ TypeInfo = 0x20,
+ Custom = 0x40,
+ NestedType = 0x80,
+ All = Constructor | Event | Field | Method | Property | TypeInfo | NestedType
+ }
+
+ [Flags]
+ public enum MethodAttributes
+ {
+ MemberAccessMask = 0x0007,
+ PrivateScope = 0x0000,
+ Private = 0x0001,
+ FamANDAssem = 0x0002,
+ Assembly = 0x0003,
+ Family = 0x0004,
+ FamORAssem = 0x0005,
+ Public = 0x0006,
+ Static = 0x0010,
+ Final = 0x0020,
+ Virtual = 0x0040,
+ HideBySig = 0x0080,
+ VtableLayoutMask = 0x0100,
+ ReuseSlot = 0x0000,
+ NewSlot = 0x0100,
+ CheckAccessOnOverride = 0x0200,
+ Abstract = 0x0400,
+ SpecialName = 0x0800,
+
+ PinvokeImpl = 0x2000,
+ UnmanagedExport = 0x0008,
+
+ RTSpecialName = 0x1000,
+ HasSecurity = 0x4000,
+ RequireSecObject = 0x8000,
+
+ ReservedMask = 0xd000,
+ }
+
+ [Flags]
+ public enum MethodImplAttributes
+ {
+ CodeTypeMask = 0x0003,
+ IL = 0x0000,
+ Native = 0x0001,
+ OPTIL = 0x0002,
+ Runtime = 0x0003,
+ ManagedMask = 0x0004,
+ Unmanaged = 0x0004,
+ Managed = 0x0000,
+
+ ForwardRef = 0x0010,
+ PreserveSig = 0x0080,
+ InternalCall = 0x1000,
+ Synchronized = 0x0020,
+ NoInlining = 0x0008,
+ NoOptimization = 0x0040,
+
+ MaxMethodImplVal = 0xffff,
+ }
+
+ [Flags]
+ public enum ParameterAttributes
+ {
+ None = 0,
+ In = 1,
+ Out = 2,
+ Lcid = 4,
+ Retval = 8,
+ Optional = 16,
+ HasDefault = 4096,
+ HasFieldMarshal = 8192,
+ Reserved3 = 16384,
+ Reserved4 = 32768,
+ ReservedMask = 61440,
+ }
+
+ [Flags]
+ public enum PortableExecutableKinds
+ {
+ NotAPortableExecutableImage = 0,
+ ILOnly = 1,
+ Required32Bit = 2,
+ PE32Plus = 4,
+ Unmanaged32Bit = 8,
+ }
+
+ public enum ProcessorArchitecture
+ {
+ None = 0,
+ MSIL = 1,
+ X86 = 2,
+ IA64 = 3,
+ Amd64 = 4,
+ }
+
+ [Flags]
+ public enum PropertyAttributes
+ {
+ None = 0,
+ SpecialName = 512,
+ RTSpecialName = 1024,
+ HasDefault = 4096,
+ }
+
+ [Flags]
+ public enum ResourceAttributes
+ {
+ Public = 1,
+ Private = 2,
+ }
+
+ public enum ResourceLocation
+ {
+ Embedded = 1,
+ ContainedInAnotherAssembly = 2,
+ ContainedInManifestFile = 4,
+ }
+
+ [Flags]
+ public enum TypeAttributes
+ {
+ AnsiClass = 0,
+ Class = 0,
+ AutoLayout = 0,
+ NotPublic = 0,
+ Public = 1,
+ NestedPublic = 2,
+ NestedPrivate = 3,
+ NestedFamily = 4,
+ NestedAssembly = 5,
+ NestedFamANDAssem = 6,
+ VisibilityMask = 7,
+ NestedFamORAssem = 7,
+ SequentialLayout = 8,
+ ExplicitLayout = 16,
+ LayoutMask = 24,
+ ClassSemanticsMask = 32,
+ Interface = 32,
+ Abstract = 128,
+ Sealed = 256,
+ SpecialName = 1024,
+ RTSpecialName = 2048,
+ Import = 4096,
+ Serializable = 8192,
+ UnicodeClass = 65536,
+ AutoClass = 131072,
+ CustomFormatClass = 196608,
+ StringFormatMask = 196608,
+ HasSecurity = 262144,
+ ReservedMask = 264192,
+ BeforeFieldInit = 1048576,
+ CustomFormatMask = 12582912,
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+
+namespace IKVM.Reflection
+{
+ public abstract class EventInfo : MemberInfo
+ {
+ public sealed override MemberTypes MemberType
+ {
+ get { return MemberTypes.Event; }
+ }
+
+ public abstract EventAttributes Attributes { get; }
+ public abstract MethodInfo GetAddMethod(bool nonPublic);
+ public abstract MethodInfo GetRaiseMethod(bool nonPublic);
+ public abstract MethodInfo GetRemoveMethod(bool nonPublic);
+ public abstract MethodInfo[] GetOtherMethods(bool nonPublic);
+ public abstract Type EventHandlerType { get; }
+ internal abstract bool IsPublic { get; }
+ internal abstract bool IsStatic { get; }
+
+ public bool IsSpecialName
+ {
+ get { return (Attributes & EventAttributes.SpecialName) != 0; }
+ }
+
+ public MethodInfo GetAddMethod()
+ {
+ return GetAddMethod(false);
+ }
+
+ public MethodInfo GetRaiseMethod()
+ {
+ return GetRaiseMethod(false);
+ }
+
+ public MethodInfo GetRemoveMethod()
+ {
+ return GetRemoveMethod(false);
+ }
+
+ public MethodInfo[] GetOtherMethods()
+ {
+ return GetOtherMethods(false);
+ }
+
+ internal virtual EventInfo BindTypeParameters(Type type)
+ {
+ return new GenericEventInfo(this.DeclaringType.BindTypeParameters(type), this);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+ public enum ExceptionHandlingClauseOptions
+ {
+ Clause = 0x0000,
+ Filter = 0x0001,
+ Finally = 0x0002,
+ Fault = 0x0004,
+ }
+
+ public sealed class ExceptionHandlingClause
+ {
+ private readonly int flags;
+ private readonly int tryOffset;
+ private readonly int tryLength;
+ private readonly int handlerOffset;
+ private readonly int handlerLength;
+ private readonly Type catchType;
+ private readonly int filterOffset;
+
+ internal ExceptionHandlingClause(ModuleReader module, int flags, int tryOffset, int tryLength, int handlerOffset, int handlerLength, int classTokenOrfilterOffset, IGenericContext context)
+ {
+ this.flags = flags;
+ this.tryOffset = tryOffset;
+ this.tryLength = tryLength;
+ this.handlerOffset = handlerOffset;
+ this.handlerLength = handlerLength;
+ this.catchType = flags == (int)ExceptionHandlingClauseOptions.Clause && classTokenOrfilterOffset != 0 ? module.ResolveType(classTokenOrfilterOffset, context) : null;
+ this.filterOffset = flags == (int)ExceptionHandlingClauseOptions.Filter ? classTokenOrfilterOffset : 0;
+ }
+
+ public Type CatchType
+ {
+ get { return catchType; }
+ }
+
+ public int FilterOffset
+ {
+ get { return filterOffset; }
+ }
+
+ public ExceptionHandlingClauseOptions Flags
+ {
+ get { return (ExceptionHandlingClauseOptions)flags; }
+ }
+
+ public int HandlerLength
+ {
+ get { return handlerLength; }
+ }
+
+ public int HandlerOffset
+ {
+ get { return handlerOffset; }
+ }
+
+ public int TryLength
+ {
+ get { return tryLength; }
+ }
+
+ public int TryOffset
+ {
+ get { return tryOffset; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+ public abstract class FieldInfo : MemberInfo
+ {
+ public sealed override MemberTypes MemberType
+ {
+ get { return MemberTypes.Field; }
+ }
+
+ public abstract FieldAttributes Attributes { get; }
+ public abstract void __GetDataFromRVA(byte[] data, int offset, int length);
+ public abstract Object GetRawConstantValue();
+ internal abstract FieldSignature FieldSignature { get; }
+
+ public Type FieldType
+ {
+ get { return this.FieldSignature.FieldType; }
+ }
+
+ public Type[] GetOptionalCustomModifiers()
+ {
+ return this.FieldSignature.GetOptionalCustomModifiers();
+ }
+
+ public Type[] GetRequiredCustomModifiers()
+ {
+ return this.FieldSignature.GetRequiredCustomModifiers();
+ }
+
+ public bool IsStatic
+ {
+ get { return (Attributes & FieldAttributes.Static) != 0; }
+ }
+
+ public bool IsLiteral
+ {
+ get { return (Attributes & FieldAttributes.Literal) != 0; }
+ }
+
+ public bool IsInitOnly
+ {
+ get { return (Attributes & FieldAttributes.InitOnly) != 0; }
+ }
+
+ public bool IsNotSerialized
+ {
+ get { return (Attributes & FieldAttributes.NotSerialized) != 0; }
+ }
+
+ public bool IsSpecialName
+ {
+ get { return (Attributes & FieldAttributes.SpecialName) != 0; }
+ }
+
+ public bool IsPublic
+ {
+ get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; }
+ }
+
+ public bool IsPrivate
+ {
+ get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private; }
+ }
+
+ public bool IsFamily
+ {
+ get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; }
+ }
+
+ public bool IsFamilyOrAssembly
+ {
+ get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem; }
+ }
+
+ public bool IsAssembly
+ {
+ get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; }
+ }
+
+ public bool IsFamilyAndAssembly
+ {
+ get { return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem; }
+ }
+
+ public bool IsPinvokeImpl
+ {
+ get { return (Attributes & FieldAttributes.PinvokeImpl) != 0; }
+ }
+
+ internal abstract int ImportTo(Emit.ModuleBuilder module);
+
+ internal virtual FieldInfo BindTypeParameters(Type type)
+ {
+ return new GenericFieldInstance(this.DeclaringType.BindTypeParameters(type), this);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+ sealed class FieldSignature : Signature
+ {
+ private readonly Type fieldType;
+ private readonly Type[] optionalCustomModifiers;
+ private readonly Type[] requiredCustomModifiers;
+
+ internal static FieldSignature Create(Type fieldType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers)
+ {
+ return new FieldSignature(fieldType, Util.Copy(optionalCustomModifiers), Util.Copy(requiredCustomModifiers));
+ }
+
+ private FieldSignature(Type fieldType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers)
+ {
+ this.fieldType = fieldType;
+ this.optionalCustomModifiers = optionalCustomModifiers;
+ this.requiredCustomModifiers = requiredCustomModifiers;
+ }
+
+ public override bool Equals(object obj)
+ {
+ FieldSignature other = obj as FieldSignature;
+ return other != null
+ && other.fieldType.Equals(fieldType)
+ && Util.ArrayEquals(other.optionalCustomModifiers, optionalCustomModifiers)
+ && Util.ArrayEquals(other.requiredCustomModifiers, requiredCustomModifiers);
+ }
+
+ public override int GetHashCode()
+ {
+ return fieldType.GetHashCode() ^ Util.GetHashCode(optionalCustomModifiers) ^ Util.GetHashCode(requiredCustomModifiers);
+ }
+
+ internal Type FieldType
+ {
+ get { return fieldType; }
+ }
+
+ internal Type[] GetOptionalCustomModifiers()
+ {
+ return Util.Copy(optionalCustomModifiers);
+ }
+
+ internal Type[] GetRequiredCustomModifiers()
+ {
+ return Util.Copy(requiredCustomModifiers);
+ }
+
+ internal FieldSignature ExpandTypeParameters(Type declaringType)
+ {
+ return new FieldSignature(
+ fieldType.BindTypeParameters(declaringType),
+ BindTypeParameters(declaringType, optionalCustomModifiers),
+ BindTypeParameters(declaringType, requiredCustomModifiers));
+ }
+
+ internal static FieldSignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ if (br.ReadByte() != FIELD)
+ {
+ throw new BadImageFormatException();
+ }
+ Type fieldType;
+ Type[] optionalCustomModifiers;
+ Type[] requiredCustomModifiers;
+ ReadCustomModifiers(module, br, context, out requiredCustomModifiers, out optionalCustomModifiers);
+ fieldType = ReadType(module, br, context);
+ return new FieldSignature(fieldType, optionalCustomModifiers, requiredCustomModifiers);
+ }
+
+ internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
+ {
+ bb.Write(FIELD);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers);
+ WriteType(module, bb, fieldType);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ struct ParsedAssemblyName
+ {
+ internal string Name;
+ internal Version Version;
+ internal string Culture;
+ internal string PublicKeyToken;
+ }
+
+ static class Fusion
+ {
+ private static readonly bool UseNativeFusion = Environment.OSVersion.Platform == PlatformID.Win32NT && System.Type.GetType("Mono.Runtime") == null && Environment.GetEnvironmentVariable("IKVM_DISABLE_FUSION") == null;
+
+ internal static bool CompareAssemblyIdentity(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
+ {
+ if (UseNativeFusion)
+ {
+ bool equivalent;
+ Marshal.ThrowExceptionForHR(CompareAssemblyIdentity(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out equivalent, out result));
+ return equivalent;
+ }
+ else
+ {
+ return CompareAssemblyIdentityPure(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out result);
+ }
+ }
+
+ [DllImport("fusion", CharSet = CharSet.Unicode)]
+ private static extern int CompareAssemblyIdentity(string pwzAssemblyIdentity1, bool fUnified1, string pwzAssemblyIdentity2, bool fUnified2, out bool pfEquivalent, out AssemblyComparisonResult pResult);
+
+ private static bool CompareAssemblyIdentityPure(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
+ {
+ ParsedAssemblyName name1;
+ ParsedAssemblyName name2;
+
+ if (!ParseAssemblyName(assemblyIdentity1, out name1)
+ || !ParseAssemblyName(assemblyIdentity2, out name2))
+ {
+ result = AssemblyComparisonResult.NonEquivalent;
+ throw new ArgumentException();
+ }
+
+ bool partial = IsPartial(name1);
+
+ if ((partial && unified1) || IsPartial(name2))
+ {
+ result = AssemblyComparisonResult.NonEquivalent;
+ throw new ArgumentException();
+ }
+ if (!name1.Name.Equals(name2.Name, StringComparison.InvariantCultureIgnoreCase))
+ {
+ result = AssemblyComparisonResult.NonEquivalent;
+ return false;
+ }
+ if (name1.Name.Equals("mscorlib", StringComparison.InvariantCultureIgnoreCase))
+ {
+ result = AssemblyComparisonResult.EquivalentFullMatch;
+ return true;
+ }
+ if (partial && name1.Culture == null)
+ {
+ }
+ else if (!name1.Culture.Equals(name2.Culture, StringComparison.InvariantCultureIgnoreCase))
+ {
+ result = AssemblyComparisonResult.NonEquivalent;
+ return false;
+ }
+ if (IsStrongNamed(name2))
+ {
+ if (partial && name1.PublicKeyToken == null)
+ {
+ }
+ else if (name1.PublicKeyToken != name2.PublicKeyToken)
+ {
+ result = AssemblyComparisonResult.NonEquivalent;
+ return false;
+ }
+ if (partial && name1.Version == null)
+ {
+ result = AssemblyComparisonResult.EquivalentPartialMatch;
+ return true;
+ }
+ else if (name1.Version < name2.Version)
+ {
+ if (unified2)
+ {
+ result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified;
+ return true;
+ }
+ else
+ {
+ result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion;
+ return false;
+ }
+ }
+ else if (name1.Version > name2.Version)
+ {
+ if (unified1)
+ {
+ result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified;
+ return true;
+ }
+ else
+ {
+ result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion;
+ return false;
+ }
+ }
+ else
+ {
+ result = partial ? AssemblyComparisonResult.EquivalentPartialMatch : AssemblyComparisonResult.EquivalentFullMatch;
+ return true;
+ }
+ }
+ else
+ {
+ result = partial ? AssemblyComparisonResult.EquivalentPartialWeakNamed : AssemblyComparisonResult.EquivalentWeakNamed;
+ return true;
+ }
+ }
+
+ // note that this is the fusion specific parser, it is not the same as System.Reflection.AssemblyName
+ private static bool ParseAssemblyName(string fullName, out ParsedAssemblyName parsedName)
+ {
+ parsedName = new ParsedAssemblyName();
+ StringBuilder sb = new StringBuilder();
+ int pos = 0;
+ while (pos < fullName.Length)
+ {
+ char ch = fullName[pos++];
+ if (ch == '\\')
+ {
+ if (pos == fullName.Length)
+ {
+ return false;
+ }
+ ch = fullName[pos++];
+ }
+ else if (ch == ',')
+ {
+ break;
+ }
+ sb.Append(ch);
+ }
+ parsedName.Name = sb.ToString().Trim();
+ if (pos < fullName.Length)
+ {
+ string[] parts = fullName.Substring(pos).Split(',');
+ for (int i = 0; i < parts.Length; i++)
+ {
+ string[] kv = parts[i].Split('=');
+ if (kv.Length != 2)
+ {
+ return false;
+ }
+ switch (kv[0].Trim().ToLowerInvariant())
+ {
+ case "version":
+ if (parsedName.Version != null)
+ {
+ return false;
+ }
+ if (!ParseVersion(kv[1].Trim(), out parsedName.Version))
+ {
+ return false;
+ }
+ break;
+ case "culture":
+ if (parsedName.Culture != null)
+ {
+ return false;
+ }
+ if (!ParseCulture(kv[1].Trim(), out parsedName.Culture))
+ {
+ return false;
+ }
+ break;
+ case "publickeytoken":
+ if (parsedName.PublicKeyToken != null)
+ {
+ return false;
+ }
+ if (!ParsePublicKeyToken(kv[1].Trim(), out parsedName.PublicKeyToken))
+ {
+ return false;
+ }
+ break;
+ case "publickey":
+ if (parsedName.PublicKeyToken != null)
+ {
+ return false;
+ }
+ if (!ParsePublicKey(kv[1].Trim(), out parsedName.PublicKeyToken))
+ {
+ return false;
+ }
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static bool ParseVersion(string str, out Version version)
+ {
+ string[] parts = str.Split('.');
+ if (parts.Length == 4)
+ {
+ ushort major, minor, build, revision;
+ if (ushort.TryParse(parts[0], System.Globalization.NumberStyles.Integer, null, out major)
+ && ushort.TryParse(parts[1], System.Globalization.NumberStyles.Integer, null, out minor)
+ && ushort.TryParse(parts[2], System.Globalization.NumberStyles.Integer, null, out build)
+ && ushort.TryParse(parts[3], System.Globalization.NumberStyles.Integer, null, out revision))
+ {
+ version = new Version(major, minor, build, revision);
+ return true;
+ }
+ }
+ version = null;
+ return false;
+ }
+
+ private static bool ParseCulture(string str, out string culture)
+ {
+ if (str == null)
+ {
+ culture = null;
+ return false;
+ }
+ culture = str;
+ return true;
+ }
+
+ private static bool ParsePublicKeyToken(string str, out string publicKeyToken)
+ {
+ if (str == null)
+ {
+ publicKeyToken = null;
+ return false;
+ }
+ publicKeyToken = str.ToLowerInvariant();
+ return true;
+ }
+
+ private static bool ParsePublicKey(string str, out string publicKeyToken)
+ {
+ if (str == null)
+ {
+ publicKeyToken = null;
+ return false;
+ }
+ // HACK use AssemblyName to convert PublicKey to PublicKeyToken
+ byte[] token = new AssemblyName("Foo, PublicKey=" + str).GetPublicKeyToken();
+ StringBuilder sb = new StringBuilder(token.Length * 2);
+ for (int i = 0; i < token.Length; i++)
+ {
+ sb.AppendFormat("{0:x2}", token[i]);
+ }
+ publicKeyToken = sb.ToString();
+ return true;
+ }
+
+ private static bool IsPartial(ParsedAssemblyName name)
+ {
+ return name.Version == null || name.Culture == null || name.PublicKeyToken == null;
+ }
+
+ private static bool IsStrongNamed(ParsedAssemblyName name)
+ {
+ return name.PublicKeyToken != null && name.PublicKeyToken != "null";
+ }
+
+ private static bool IsEqual(byte[] b1, byte[] b2)
+ {
+ if (b1.Length != b2.Length)
+ {
+ return false;
+ }
+ for (int i = 0; i < b1.Length; i++)
+ {
+ if (b1[i] != b2[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009, 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ // this represents both generic method instantiations and non-generic methods on generic type instantations
+ // (this means that it can be a generic method declaration as well as a generic method instance)
+ sealed class GenericMethodInstance : MethodInfo
+ {
+ private readonly Type declaringType;
+ private readonly MethodInfo method;
+ private readonly Type[] methodArgs;
+ private MethodSignature lazyMethodSignature;
+
+ internal GenericMethodInstance(Type declaringType, MethodInfo method, Type[] methodArgs)
+ {
+ System.Diagnostics.Debug.Assert(!(method is GenericMethodInstance));
+ this.declaringType = declaringType;
+ this.method = method;
+ this.methodArgs = methodArgs;
+ }
+
+ public override bool Equals(object obj)
+ {
+ GenericMethodInstance other = obj as GenericMethodInstance;
+ return other != null
+ && other.method.Equals(method)
+ && other.declaringType.Equals(declaringType)
+ && Util.ArrayEquals(other.methodArgs, methodArgs);
+ }
+
+ public override int GetHashCode()
+ {
+ return declaringType.GetHashCode() * 33 ^ method.GetHashCode() ^ Util.GetHashCode(methodArgs);
+ }
+
+ public override Type ReturnType
+ {
+ get { return method.ReturnType.BindTypeParameters(this); }
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get { return new GenericParameterInfoImpl(this, method.ReturnParameter); }
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ ParameterInfo[] parameters = method.GetParameters();
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = new GenericParameterInfoImpl(this, parameters[i]);
+ }
+ return parameters;
+ }
+
+ internal override int ParameterCount
+ {
+ get { return method.ParameterCount; }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get { return method.CallingConvention; }
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return method.Attributes; }
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return method.GetMethodImplementationFlags();
+ }
+
+ public override string Name
+ {
+ get { return method.Name; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return declaringType.IsModulePseudoType ? null : declaringType; }
+ }
+
+ public override Module Module
+ {
+ get { return method.Module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return method.MetadataToken; }
+ }
+
+ public override MethodBody GetMethodBody()
+ {
+ IKVM.Reflection.Reader.MethodDefImpl md = method as IKVM.Reflection.Reader.MethodDefImpl;
+ if (md != null)
+ {
+ return md.GetMethodBody(this);
+ }
+ throw new NotSupportedException();
+ }
+
+ public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ return new GenericMethodInstance(declaringType, method, typeArguments);
+ }
+
+ public override bool IsGenericMethod
+ {
+ get { return method.IsGenericMethod; }
+ }
+
+ public override bool IsGenericMethodDefinition
+ {
+ get { return method.IsGenericMethodDefinition && methodArgs == null; }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ if (declaringType.ContainsGenericParameters)
+ {
+ return true;
+ }
+ if (methodArgs != null)
+ {
+ foreach (Type type in methodArgs)
+ {
+ if (type.ContainsGenericParameters)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ public override MethodInfo GetGenericMethodDefinition()
+ {
+ if (this.IsGenericMethod)
+ {
+ if (this.IsGenericMethodDefinition)
+ {
+ return this;
+ }
+ else if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
+ {
+ return new GenericMethodInstance(declaringType, method, null);
+ }
+ else
+ {
+ return method;
+ }
+ }
+ throw new InvalidOperationException();
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ if (methodArgs == null)
+ {
+ return method.GetGenericArguments();
+ }
+ else
+ {
+ return (Type[])methodArgs.Clone();
+ }
+ }
+
+ internal override Type GetGenericMethodArgument(int index)
+ {
+ if (methodArgs == null)
+ {
+ return method.GetGenericMethodArgument(index);
+ }
+ else
+ {
+ return methodArgs[index];
+ }
+ }
+
+ internal override int GetGenericMethodArgumentCount()
+ {
+ return method.GetGenericMethodArgumentCount();
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return method.GetCustomAttributesData(attributeType);
+ }
+
+ internal override MethodInfo GetMethodOnTypeDefinition()
+ {
+ return method.GetMethodOnTypeDefinition();
+ }
+
+ internal override int ImportTo(Emit.ModuleBuilder module)
+ {
+ if (methodArgs == null)
+ {
+ return module.ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
+ }
+ else
+ {
+ Writer.ByteBuffer spec = new Writer.ByteBuffer(10);
+ Signature.WriteMethodSpec(module, spec, methodArgs);
+ Metadata.MethodSpecTable.Record rec = new Metadata.MethodSpecTable.Record();
+ Emit.MethodBuilder mb = method as Emit.MethodBuilder;
+ if (mb != null && mb.ModuleBuilder == module && !declaringType.IsGenericType)
+ {
+ rec.Method = mb.MetadataToken;
+ }
+ else
+ {
+ rec.Method = module.ImportMember(GetGenericMethodDefinition());
+ }
+ rec.Instantiation = module.Blobs.Add(spec);
+ return 0x2B000000 | module.MethodSpec.FindOrAddRecord(rec);
+ }
+ }
+
+ internal override MethodSignature MethodSignature
+ {
+ get { return lazyMethodSignature ?? (lazyMethodSignature = method.MethodSignature.Bind(declaringType, methodArgs)); }
+ }
+
+ internal override MethodBase BindTypeParameters(Type type)
+ {
+ System.Diagnostics.Debug.Assert(methodArgs == null);
+ return new GenericMethodInstance(declaringType.BindTypeParameters(type), method, null);
+ }
+ }
+
+ sealed class GenericFieldInstance : FieldInfo
+ {
+ private readonly Type declaringType;
+ private readonly FieldInfo field;
+
+ internal GenericFieldInstance(Type declaringType, FieldInfo field)
+ {
+ this.declaringType = declaringType;
+ this.field = field;
+ }
+
+ public override bool Equals(object obj)
+ {
+ GenericFieldInstance other = obj as GenericFieldInstance;
+ return other != null && other.declaringType.Equals(declaringType) && other.field.Equals(field);
+ }
+
+ public override int GetHashCode()
+ {
+ return declaringType.GetHashCode() * 3 ^ field.GetHashCode();
+ }
+
+ public override FieldAttributes Attributes
+ {
+ get { return field.Attributes; }
+ }
+
+ public override string Name
+ {
+ get { return field.Name; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return declaringType; }
+ }
+
+ public override Module Module
+ {
+ get { return declaringType.Module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return field.MetadataToken; }
+ }
+
+ public override object GetRawConstantValue()
+ {
+ return field.GetRawConstantValue();
+ }
+
+ public override void __GetDataFromRVA(byte[] data, int offset, int length)
+ {
+ field.__GetDataFromRVA(data, offset, length);
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return field.GetCustomAttributesData(attributeType);
+ }
+
+ internal override FieldSignature FieldSignature
+ {
+ get { return field.FieldSignature.ExpandTypeParameters(declaringType); }
+ }
+
+ internal override int ImportTo(Emit.ModuleBuilder module)
+ {
+ return module.ImportMethodOrField(declaringType, field.Name, field.FieldSignature);
+ }
+
+ internal override FieldInfo BindTypeParameters(Type type)
+ {
+ return new GenericFieldInstance(declaringType.BindTypeParameters(type), field);
+ }
+ }
+
+ sealed class GenericParameterInfoImpl : ParameterInfo
+ {
+ private readonly GenericMethodInstance method;
+ private readonly ParameterInfo parameterInfo;
+
+ internal GenericParameterInfoImpl(GenericMethodInstance method, ParameterInfo parameterInfo)
+ {
+ this.method = method;
+ this.parameterInfo = parameterInfo;
+ }
+
+ public override string Name
+ {
+ get { return parameterInfo.Name; }
+ }
+
+ public override Type ParameterType
+ {
+ get { return parameterInfo.ParameterType.BindTypeParameters(method); }
+ }
+
+ public override ParameterAttributes Attributes
+ {
+ get { return parameterInfo.Attributes; }
+ }
+
+ public override int Position
+ {
+ get { return parameterInfo.Position; }
+ }
+
+ public override object RawDefaultValue
+ {
+ get { return parameterInfo.RawDefaultValue; }
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ Type[] modifiers = parameterInfo.GetOptionalCustomModifiers();
+ Type.InplaceBindTypeParameters(method, modifiers);
+ return modifiers;
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ Type[] modifiers = parameterInfo.GetRequiredCustomModifiers();
+ Type.InplaceBindTypeParameters(method, modifiers);
+ return modifiers;
+ }
+
+ public override MemberInfo Member
+ {
+ get { return method; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return parameterInfo.MetadataToken; }
+ }
+
+ internal override Module Module
+ {
+ get { return method.Module; }
+ }
+ }
+
+ sealed class GenericPropertyInfo : PropertyInfo
+ {
+ private readonly Type typeInstance;
+ private readonly PropertyInfo property;
+
+ internal GenericPropertyInfo(Type typeInstance, PropertyInfo property)
+ {
+ this.typeInstance = typeInstance;
+ this.property = property;
+ }
+
+ public override bool Equals(object obj)
+ {
+ GenericPropertyInfo other = obj as GenericPropertyInfo;
+ return other != null && other.typeInstance == typeInstance && other.property == property;
+ }
+
+ public override int GetHashCode()
+ {
+ return typeInstance.GetHashCode() * 537 + property.GetHashCode();
+ }
+
+ public override PropertyAttributes Attributes
+ {
+ get { return property.Attributes; }
+ }
+
+ public override bool CanRead
+ {
+ get { return property.CanRead; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return property.CanWrite; }
+ }
+
+ private MethodInfo Wrap(MethodInfo method)
+ {
+ if (method == null)
+ {
+ return null;
+ }
+ return new GenericMethodInstance(typeInstance, method, null);
+ }
+
+ public override MethodInfo GetGetMethod(bool nonPublic)
+ {
+ return Wrap(property.GetGetMethod(nonPublic));
+ }
+
+ public override MethodInfo GetSetMethod(bool nonPublic)
+ {
+ return Wrap(property.GetSetMethod(nonPublic));
+ }
+
+ public override MethodInfo[] GetAccessors(bool nonPublic)
+ {
+ MethodInfo[] accessors = property.GetAccessors(nonPublic);
+ for (int i = 0; i < accessors.Length; i++)
+ {
+ accessors[i] = Wrap(accessors[i]);
+ }
+ return accessors;
+ }
+
+ public override object GetRawConstantValue()
+ {
+ return property.GetRawConstantValue();
+ }
+
+ internal override bool IsPublic
+ {
+ get { return property.IsPublic; }
+ }
+
+ internal override bool IsStatic
+ {
+ get { return property.IsStatic; }
+ }
+
+ internal override PropertySignature PropertySignature
+ {
+ get { return property.PropertySignature.ExpandTypeParameters(typeInstance); }
+ }
+
+ public override string Name
+ {
+ get { return property.Name; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeInstance; }
+ }
+
+ public override Module Module
+ {
+ get { return typeInstance.Module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return property.MetadataToken; }
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return property.GetCustomAttributesData(attributeType);
+ }
+
+ internal override PropertyInfo BindTypeParameters(Type type)
+ {
+ return new GenericPropertyInfo(typeInstance.BindTypeParameters(type), property);
+ }
+ }
+
+ sealed class GenericEventInfo : EventInfo
+ {
+ private readonly Type typeInstance;
+ private readonly EventInfo eventInfo;
+
+ internal GenericEventInfo(Type typeInstance, EventInfo eventInfo)
+ {
+ this.typeInstance = typeInstance;
+ this.eventInfo = eventInfo;
+ }
+
+ public override bool Equals(object obj)
+ {
+ GenericEventInfo other = obj as GenericEventInfo;
+ return other != null && other.typeInstance == typeInstance && other.eventInfo == eventInfo;
+ }
+
+ public override int GetHashCode()
+ {
+ return typeInstance.GetHashCode() * 777 + eventInfo.GetHashCode();
+ }
+
+ public override EventAttributes Attributes
+ {
+ get { return eventInfo.Attributes; }
+ }
+
+ private MethodInfo Wrap(MethodInfo method)
+ {
+ if (method == null)
+ {
+ return null;
+ }
+ return new GenericMethodInstance(typeInstance, method, null);
+ }
+
+ public override MethodInfo GetAddMethod(bool nonPublic)
+ {
+ return Wrap(eventInfo.GetAddMethod(nonPublic));
+ }
+
+ public override MethodInfo GetRaiseMethod(bool nonPublic)
+ {
+ return Wrap(eventInfo.GetRaiseMethod(nonPublic));
+ }
+
+ public override MethodInfo GetRemoveMethod(bool nonPublic)
+ {
+ return Wrap(eventInfo.GetRemoveMethod(nonPublic));
+ }
+
+ public override MethodInfo[] GetOtherMethods(bool nonPublic)
+ {
+ MethodInfo[] others = eventInfo.GetOtherMethods(nonPublic);
+ for (int i = 0; i < others.Length; i++)
+ {
+ others[i] = Wrap(others[i]);
+ }
+ return others;
+ }
+
+ public override Type EventHandlerType
+ {
+ get { return eventInfo.EventHandlerType.BindTypeParameters(typeInstance); }
+ }
+
+ public override string Name
+ {
+ get { return eventInfo.Name; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeInstance; }
+ }
+
+ public override Module Module
+ {
+ get { return eventInfo.Module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return eventInfo.MetadataToken; }
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return eventInfo.GetCustomAttributesData(attributeType);
+ }
+
+ internal override EventInfo BindTypeParameters(Type type)
+ {
+ return new GenericEventInfo(typeInstance.BindTypeParameters(type), eventInfo);
+ }
+
+ internal override bool IsPublic
+ {
+ get { return eventInfo.IsPublic; }
+ }
+
+ internal override bool IsStatic
+ {
+ get { return eventInfo.IsStatic; }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>IKVM.Reflection</RootNamespace>
+ <AssemblyName>IKVM.Reflection</AssemblyName>
+ <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkSubset>
+ </TargetFrameworkSubset>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="AmbiguousMatchException.cs" />
+ <Compile Include="Assembly.cs" />
+ <Compile Include="AssemblyName.cs" />
+ <Compile Include="BadImageFormatException.cs" />
+ <Compile Include="Binder.cs" />
+ <Compile Include="ConstructorInfo.cs" />
+ <Compile Include="CustomAttributeData.cs" />
+ <Compile Include="CustomAttributeNamedArgument.cs" />
+ <Compile Include="CustomAttributeTypedArgument.cs" />
+ <Compile Include="Emit\AssemblyBuilder.cs" />
+ <Compile Include="Emit\ConstructorBuilder.cs" />
+ <Compile Include="Emit\CustomAttributeBuilder.cs" />
+ <Compile Include="Emit\EnumBuilder.cs" />
+ <Compile Include="Emit\Enums.cs" />
+ <Compile Include="Emit\EventBuilder.cs" />
+ <Compile Include="Emit\FieldBuilder.cs" />
+ <Compile Include="Emit\ILGenerator.cs" />
+ <Compile Include="Emit\MethodBuilder.cs" />
+ <Compile Include="Emit\ModuleBuilder.cs" />
+ <Compile Include="Emit\OpCode.cs" />
+ <Compile Include="Emit\OpCodes.cs" />
+ <Compile Include="Emit\ParameterBuilder.cs" />
+ <Compile Include="Emit\PropertyBuilder.cs" />
+ <Compile Include="Emit\SignatureHelper.cs" />
+ <Compile Include="Emit\Tokens.cs" />
+ <Compile Include="Emit\TypeBuilder.cs" />
+ <Compile Include="Enums.cs" />
+ <Compile Include="EventInfo.cs" />
+ <Compile Include="ExceptionHandlingClause.cs" />
+ <Compile Include="FieldInfo.cs" />
+ <Compile Include="FieldSignature.cs" />
+ <Compile Include="Fusion.cs" />
+ <Compile Include="GenericWrappers.cs" />
+ <Compile Include="Impl\CryptoConvert.cs" />
+ <Compile Include="Impl\CryptoHack.cs" />
+ <Compile Include="Impl\ITypeOwner.cs" />
+ <Compile Include="Impl\MdbWriter.cs" />
+ <Compile Include="Impl\PdbWriter.cs" />
+ <Compile Include="Impl\SymbolSupport.cs" />
+ <Compile Include="InterfaceMapping.cs" />
+ <Compile Include="LocalVariableInfo.cs" />
+ <Compile Include="ManifestResourceInfo.cs" />
+ <Compile Include="MarshalSpec.cs" />
+ <Compile Include="MemberInfo.cs" />
+ <Compile Include="Metadata\CliHeader.cs" />
+ <Compile Include="Metadata\MetadataRW.cs" />
+ <Compile Include="Metadata\Tables.cs" />
+ <Compile Include="MethodBase.cs" />
+ <Compile Include="MethodBody.cs" />
+ <Compile Include="MethodImplMap.cs" />
+ <Compile Include="MethodInfo.cs" />
+ <Compile Include="MethodSignature.cs" />
+ <Compile Include="Module.cs" />
+ <Compile Include="ParameterInfo.cs" />
+ <Compile Include="ParameterModifier.cs" />
+ <Compile Include="PropertyInfo.cs" />
+ <Compile Include="PropertySignature.cs" />
+ <Compile Include="Reader\AssemblyReader.cs" />
+ <Compile Include="Reader\ByteReader.cs" />
+ <Compile Include="Reader\EventInfoImpl.cs" />
+ <Compile Include="Reader\Field.cs" />
+ <Compile Include="Reader\GenericTypeParameter.cs" />
+ <Compile Include="Reader\MetadataReader.cs" />
+ <Compile Include="Reader\Method.cs" />
+ <Compile Include="Reader\ModuleReader.cs" />
+ <Compile Include="Reader\PEReader.cs" />
+ <Compile Include="Reader\PropertyInfoImpl.cs" />
+ <Compile Include="Reader\ResourceModule.cs" />
+ <Compile Include="Reader\TypeDefImpl.cs" />
+ <Compile Include="Signature.cs" />
+ <Compile Include="StandAloneMethodSig.cs" />
+ <Compile Include="StrongNameKeyPair.cs" />
+ <Compile Include="Type.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TypeNameParser.cs" />
+ <Compile Include="Universe.cs" />
+ <Compile Include="Util.cs" />
+ <Compile Include="Writer\ByteBuffer.cs" />
+ <Compile Include="Writer\Heaps.cs" />
+ <Compile Include="Writer\MetadataWriter.cs" />
+ <Compile Include="Writer\ModuleWriter.cs" />
+ <Compile Include="Writer\PEWriter.cs" />
+ <Compile Include="Writer\ResourceSection.cs" />
+ <Compile Include="Writer\TextSection.cs" />
+ <Compile Include="Writer\VersionInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
--- /dev/null
+//
+// CryptoConvert.cs - Crypto Convertion Routines
+//
+// Author:
+// Sebastien Pouliot <sebastien@ximian.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// [JF-20081013] begin modifications for IKVM
+#define INSIDE_CORLIB
+// end modifications for IKVM
+
+using System;
+using System.Globalization;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Mono.Security.Cryptography {
+
+#if INSIDE_CORLIB
+ internal
+#else
+ public
+#endif
+ sealed class CryptoConvert {
+
+ private CryptoConvert ()
+ {
+ }
+
+ static private int ToInt32LE (byte [] bytes, int offset)
+ {
+ return (bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset];
+ }
+
+ static private uint ToUInt32LE (byte [] bytes, int offset)
+ {
+ return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]);
+ }
+
+ static private byte [] GetBytesLE (int val)
+ {
+ return new byte [] {
+ (byte) (val & 0xff),
+ (byte) ((val >> 8) & 0xff),
+ (byte) ((val >> 16) & 0xff),
+ (byte) ((val >> 24) & 0xff)
+ };
+ }
+
+ static private byte[] Trim (byte[] array)
+ {
+ for (int i=0; i < array.Length; i++) {
+ if (array [i] != 0x00) {
+ byte[] result = new byte [array.Length - i];
+ Buffer.BlockCopy (array, i, result, 0, result.Length);
+ return result;
+ }
+ }
+ return null;
+ }
+
+ // convert the key from PRIVATEKEYBLOB to RSA
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/Security/private_key_blobs.asp
+ // e.g. SNK files, PVK files
+ static public RSA FromCapiPrivateKeyBlob (byte[] blob)
+ {
+ return FromCapiPrivateKeyBlob (blob, 0);
+ }
+
+ static public RSA FromCapiPrivateKeyBlob (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ RSAParameters rsap = new RSAParameters ();
+ try {
+ if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07)
+ (blob [offset+1] != 0x02) || // Version (0x02)
+ (blob [offset+2] != 0x00) || // Reserved (word)
+ (blob [offset+3] != 0x00) ||
+ (ToUInt32LE (blob, offset+8) != 0x32415352)) // DWORD magic = RSA2
+ throw new CryptographicException ("Invalid blob header");
+
+ // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+ // int algId = ToInt32LE (blob, offset+4);
+
+ // DWORD bitlen
+ int bitLen = ToInt32LE (blob, offset+12);
+
+ // DWORD public exponent
+ byte[] exp = new byte [4];
+ Buffer.BlockCopy (blob, offset+16, exp, 0, 4);
+ Array.Reverse (exp);
+ rsap.Exponent = Trim (exp);
+
+ int pos = offset+20;
+ // BYTE modulus[rsapubkey.bitlen/8];
+ int byteLen = (bitLen >> 3);
+ rsap.Modulus = new byte [byteLen];
+ Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
+ Array.Reverse (rsap.Modulus);
+ pos += byteLen;
+
+ // BYTE prime1[rsapubkey.bitlen/16];
+ int byteHalfLen = (byteLen >> 1);
+ rsap.P = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen);
+ Array.Reverse (rsap.P);
+ pos += byteHalfLen;
+
+ // BYTE prime2[rsapubkey.bitlen/16];
+ rsap.Q = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen);
+ Array.Reverse (rsap.Q);
+ pos += byteHalfLen;
+
+ // BYTE exponent1[rsapubkey.bitlen/16];
+ rsap.DP = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen);
+ Array.Reverse (rsap.DP);
+ pos += byteHalfLen;
+
+ // BYTE exponent2[rsapubkey.bitlen/16];
+ rsap.DQ = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen);
+ Array.Reverse (rsap.DQ);
+ pos += byteHalfLen;
+
+ // BYTE coefficient[rsapubkey.bitlen/16];
+ rsap.InverseQ = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen);
+ Array.Reverse (rsap.InverseQ);
+ pos += byteHalfLen;
+
+ // ok, this is hackish but CryptoAPI support it so...
+ // note: only works because CRT is used by default
+ // http://bugzilla.ximian.com/show_bug.cgi?id=57941
+ rsap.D = new byte [byteLen]; // must be allocated
+ if (pos + byteLen + offset <= blob.Length) {
+ // BYTE privateExponent[rsapubkey.bitlen/8];
+ Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen);
+ Array.Reverse (rsap.D);
+ }
+ }
+ catch (Exception e) {
+ throw new CryptographicException ("Invalid blob.", e);
+ }
+
+ RSA rsa = null;
+ try {
+ rsa = RSA.Create ();
+ rsa.ImportParameters (rsap);
+ }
+ catch (CryptographicException ce) {
+ // this may cause problem when this code is run under
+ // the SYSTEM identity on Windows (e.g. ASP.NET). See
+ // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+ try {
+ CspParameters csp = new CspParameters ();
+ csp.Flags = CspProviderFlags.UseMachineKeyStore;
+ rsa = new RSACryptoServiceProvider (csp);
+ rsa.ImportParameters (rsap);
+ }
+ catch {
+ // rethrow original, not the later, exception if this fails
+ throw ce;
+ }
+ }
+ return rsa;
+ }
+
+ static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob)
+ {
+ return FromCapiPrivateKeyBlobDSA (blob, 0);
+ }
+
+ static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ DSAParameters dsap = new DSAParameters ();
+ try {
+ if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07)
+ (blob [offset + 1] != 0x02) || // Version (0x02)
+ (blob [offset + 2] != 0x00) || // Reserved (word)
+ (blob [offset + 3] != 0x00) ||
+ (ToUInt32LE (blob, offset + 8) != 0x32535344)) // DWORD magic
+ throw new CryptographicException ("Invalid blob header");
+
+ int bitlen = ToInt32LE (blob, offset + 12);
+ int bytelen = bitlen >> 3;
+ int pos = offset + 16;
+
+ dsap.P = new byte [bytelen];
+ Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen);
+ Array.Reverse (dsap.P);
+ pos += bytelen;
+
+ dsap.Q = new byte [20];
+ Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20);
+ Array.Reverse (dsap.Q);
+ pos += 20;
+
+ dsap.G = new byte [bytelen];
+ Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen);
+ Array.Reverse (dsap.G);
+ pos += bytelen;
+
+ dsap.X = new byte [20];
+ Buffer.BlockCopy (blob, pos, dsap.X, 0, 20);
+ Array.Reverse (dsap.X);
+ pos += 20;
+
+ dsap.Counter = ToInt32LE (blob, pos);
+ pos += 4;
+
+ dsap.Seed = new byte [20];
+ Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20);
+ Array.Reverse (dsap.Seed);
+ pos += 20;
+ }
+ catch (Exception e) {
+ throw new CryptographicException ("Invalid blob.", e);
+ }
+
+ DSA dsa = null;
+ try {
+ dsa = (DSA)DSA.Create ();
+ dsa.ImportParameters (dsap);
+ }
+ catch (CryptographicException ce) {
+ // this may cause problem when this code is run under
+ // the SYSTEM identity on Windows (e.g. ASP.NET). See
+ // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+ try {
+ CspParameters csp = new CspParameters ();
+ csp.Flags = CspProviderFlags.UseMachineKeyStore;
+ dsa = new DSACryptoServiceProvider (csp);
+ dsa.ImportParameters (dsap);
+ }
+ catch {
+ // rethrow original, not the later, exception if this fails
+ throw ce;
+ }
+ }
+ return dsa;
+ }
+
+ static public byte[] ToCapiPrivateKeyBlob (RSA rsa)
+ {
+ RSAParameters p = rsa.ExportParameters (true);
+ int keyLength = p.Modulus.Length; // in bytes
+ byte[] blob = new byte [20 + (keyLength << 2) + (keyLength >> 1)];
+
+ blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07)
+ blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
+ // [2], [3] // RESERVED - Always 0
+ blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
+ blob [8] = 0x52; // Magic - RSA2 (ASCII in hex)
+ blob [9] = 0x53;
+ blob [10] = 0x41;
+ blob [11] = 0x32;
+
+ byte[] bitlen = GetBytesLE (keyLength << 3);
+ blob [12] = bitlen [0]; // bitlen
+ blob [13] = bitlen [1];
+ blob [14] = bitlen [2];
+ blob [15] = bitlen [3];
+
+ // public exponent (DWORD)
+ int pos = 16;
+ int n = p.Exponent.Length;
+ while (n > 0)
+ blob [pos++] = p.Exponent [--n];
+ // modulus
+ pos = 20;
+ byte[] part = p.Modulus;
+ int len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+ // private key
+ part = p.P;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.Q;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.DP;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.DQ;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.InverseQ;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.D;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+
+ return blob;
+ }
+
+ static public byte[] ToCapiPrivateKeyBlob (DSA dsa)
+ {
+ DSAParameters p = dsa.ExportParameters (true);
+ int keyLength = p.P.Length; // in bytes
+
+ // header + P + Q + G + X + count + seed
+ byte[] blob = new byte [16 + keyLength + 20 + keyLength + 20 + 4 + 20];
+
+ blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07)
+ blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
+ // [2], [3] // RESERVED - Always 0
+ blob [5] = 0x22; // ALGID
+ blob [8] = 0x44; // Magic
+ blob [9] = 0x53;
+ blob [10] = 0x53;
+ blob [11] = 0x32;
+
+ byte[] bitlen = GetBytesLE (keyLength << 3);
+ blob [12] = bitlen [0];
+ blob [13] = bitlen [1];
+ blob [14] = bitlen [2];
+ blob [15] = bitlen [3];
+
+ int pos = 16;
+ byte[] part = p.P;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+ pos += keyLength;
+
+ part = p.Q;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, 20);
+ pos += 20;
+
+ part = p.G;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+ pos += keyLength;
+
+ part = p.X;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, 20);
+ pos += 20;
+
+ Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4);
+ pos += 4;
+
+ part = p.Seed;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, 20);
+
+ return blob;
+ }
+
+ static public RSA FromCapiPublicKeyBlob (byte[] blob)
+ {
+ return FromCapiPublicKeyBlob (blob, 0);
+ }
+
+ static public RSA FromCapiPublicKeyBlob (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ try {
+ if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06)
+ (blob [offset+1] != 0x02) || // Version (0x02)
+ (blob [offset+2] != 0x00) || // Reserved (word)
+ (blob [offset+3] != 0x00) ||
+ (ToUInt32LE (blob, offset+8) != 0x31415352)) // DWORD magic = RSA1
+ throw new CryptographicException ("Invalid blob header");
+
+ // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+ // int algId = ToInt32LE (blob, offset+4);
+
+ // DWORD bitlen
+ int bitLen = ToInt32LE (blob, offset+12);
+
+ // DWORD public exponent
+ RSAParameters rsap = new RSAParameters ();
+ rsap.Exponent = new byte [3];
+ rsap.Exponent [0] = blob [offset+18];
+ rsap.Exponent [1] = blob [offset+17];
+ rsap.Exponent [2] = blob [offset+16];
+
+ int pos = offset+20;
+ // BYTE modulus[rsapubkey.bitlen/8];
+ int byteLen = (bitLen >> 3);
+ rsap.Modulus = new byte [byteLen];
+ Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
+ Array.Reverse (rsap.Modulus);
+
+ RSA rsa = null;
+ try {
+ rsa = RSA.Create ();
+ rsa.ImportParameters (rsap);
+ }
+ catch (CryptographicException) {
+ // this may cause problem when this code is run under
+ // the SYSTEM identity on Windows (e.g. ASP.NET). See
+ // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+ CspParameters csp = new CspParameters ();
+ csp.Flags = CspProviderFlags.UseMachineKeyStore;
+ rsa = new RSACryptoServiceProvider (csp);
+ rsa.ImportParameters (rsap);
+ }
+ return rsa;
+ }
+ catch (Exception e) {
+ throw new CryptographicException ("Invalid blob.", e);
+ }
+ }
+
+ static public DSA FromCapiPublicKeyBlobDSA (byte[] blob)
+ {
+ return FromCapiPublicKeyBlobDSA (blob, 0);
+ }
+
+ static public DSA FromCapiPublicKeyBlobDSA (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ try {
+ if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06)
+ (blob [offset + 1] != 0x02) || // Version (0x02)
+ (blob [offset + 2] != 0x00) || // Reserved (word)
+ (blob [offset + 3] != 0x00) ||
+ (ToUInt32LE (blob, offset + 8) != 0x31535344)) // DWORD magic
+ throw new CryptographicException ("Invalid blob header");
+
+ int bitlen = ToInt32LE (blob, offset + 12);
+ DSAParameters dsap = new DSAParameters ();
+ int bytelen = bitlen >> 3;
+ int pos = offset + 16;
+
+ dsap.P = new byte [bytelen];
+ Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen);
+ Array.Reverse (dsap.P);
+ pos += bytelen;
+
+ dsap.Q = new byte [20];
+ Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20);
+ Array.Reverse (dsap.Q);
+ pos += 20;
+
+ dsap.G = new byte [bytelen];
+ Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen);
+ Array.Reverse (dsap.G);
+ pos += bytelen;
+
+ dsap.Y = new byte [bytelen];
+ Buffer.BlockCopy (blob, pos, dsap.Y, 0, bytelen);
+ Array.Reverse (dsap.Y);
+ pos += bytelen;
+
+ dsap.Counter = ToInt32LE (blob, pos);
+ pos += 4;
+
+ dsap.Seed = new byte [20];
+ Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20);
+ Array.Reverse (dsap.Seed);
+ pos += 20;
+
+ DSA dsa = (DSA)DSA.Create ();
+ dsa.ImportParameters (dsap);
+ return dsa;
+ }
+ catch (Exception e) {
+ throw new CryptographicException ("Invalid blob.", e);
+ }
+ }
+
+ static public byte[] ToCapiPublicKeyBlob (RSA rsa)
+ {
+ RSAParameters p = rsa.ExportParameters (false);
+ int keyLength = p.Modulus.Length; // in bytes
+ byte[] blob = new byte [20 + keyLength];
+
+ blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06)
+ blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
+ // [2], [3] // RESERVED - Always 0
+ blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
+ blob [8] = 0x52; // Magic - RSA1 (ASCII in hex)
+ blob [9] = 0x53;
+ blob [10] = 0x41;
+ blob [11] = 0x31;
+
+ byte[] bitlen = GetBytesLE (keyLength << 3);
+ blob [12] = bitlen [0]; // bitlen
+ blob [13] = bitlen [1];
+ blob [14] = bitlen [2];
+ blob [15] = bitlen [3];
+
+ // public exponent (DWORD)
+ int pos = 16;
+ int n = p.Exponent.Length;
+ while (n > 0)
+ blob [pos++] = p.Exponent [--n];
+ // modulus
+ pos = 20;
+ byte[] part = p.Modulus;
+ int len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+ return blob;
+ }
+
+ static public byte[] ToCapiPublicKeyBlob (DSA dsa)
+ {
+ DSAParameters p = dsa.ExportParameters (false);
+ int keyLength = p.P.Length; // in bytes
+
+ // header + P + Q + G + Y + count + seed
+ byte[] blob = new byte [16 + keyLength + 20 + keyLength + keyLength + 4 + 20];
+
+ blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06)
+ blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
+ // [2], [3] // RESERVED - Always 0
+ blob [5] = 0x22; // ALGID
+ blob [8] = 0x44; // Magic
+ blob [9] = 0x53;
+ blob [10] = 0x53;
+ blob [11] = 0x31;
+
+ byte[] bitlen = GetBytesLE (keyLength << 3);
+ blob [12] = bitlen [0];
+ blob [13] = bitlen [1];
+ blob [14] = bitlen [2];
+ blob [15] = bitlen [3];
+
+ int pos = 16;
+ byte[] part;
+
+ part = p.P;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+ pos += keyLength;
+
+ part = p.Q;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, 20);
+ pos += 20;
+
+ part = p.G;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+ pos += keyLength;
+
+ part = p.Y;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, keyLength);
+ pos += keyLength;
+
+ Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4);
+ pos += 4;
+
+ part = p.Seed;
+ Array.Reverse (part);
+ Buffer.BlockCopy (part, 0, blob, pos, 20);
+
+ return blob;
+ }
+
+ // PRIVATEKEYBLOB
+ // PUBLICKEYBLOB
+ static public RSA FromCapiKeyBlob (byte[] blob)
+ {
+ return FromCapiKeyBlob (blob, 0);
+ }
+
+ static public RSA FromCapiKeyBlob (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ switch (blob [offset]) {
+ case 0x00:
+ // this could be a public key inside an header
+ // like "sn -e" would produce
+ if (blob [offset + 12] == 0x06) {
+ return FromCapiPublicKeyBlob (blob, offset + 12);
+ }
+ break;
+ case 0x06:
+ return FromCapiPublicKeyBlob (blob, offset);
+ case 0x07:
+ return FromCapiPrivateKeyBlob (blob, offset);
+ }
+ throw new CryptographicException ("Unknown blob format.");
+ }
+
+ static public DSA FromCapiKeyBlobDSA (byte[] blob)
+ {
+ return FromCapiKeyBlobDSA (blob, 0);
+ }
+
+ static public DSA FromCapiKeyBlobDSA (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ switch (blob [offset]) {
+ case 0x06:
+ return FromCapiPublicKeyBlobDSA (blob, offset);
+ case 0x07:
+ return FromCapiPrivateKeyBlobDSA (blob, offset);
+ }
+ throw new CryptographicException ("Unknown blob format.");
+ }
+
+ static public byte[] ToCapiKeyBlob (AsymmetricAlgorithm keypair, bool includePrivateKey)
+ {
+ if (keypair == null)
+ throw new ArgumentNullException ("keypair");
+
+ // check between RSA and DSA (and potentially others like DH)
+ if (keypair is RSA)
+ return ToCapiKeyBlob ((RSA)keypair, includePrivateKey);
+ else if (keypair is DSA)
+ return ToCapiKeyBlob ((DSA)keypair, includePrivateKey);
+ else
+ return null; // TODO
+ }
+
+ static public byte[] ToCapiKeyBlob (RSA rsa, bool includePrivateKey)
+ {
+ if (rsa == null)
+ throw new ArgumentNullException ("rsa");
+
+ if (includePrivateKey)
+ return ToCapiPrivateKeyBlob (rsa);
+ else
+ return ToCapiPublicKeyBlob (rsa);
+ }
+
+ static public byte[] ToCapiKeyBlob (DSA dsa, bool includePrivateKey)
+ {
+ if (dsa == null)
+ throw new ArgumentNullException ("dsa");
+
+ if (includePrivateKey)
+ return ToCapiPrivateKeyBlob (dsa);
+ else
+ return ToCapiPublicKeyBlob (dsa);
+ }
+
+ static public string ToHex (byte[] input)
+ {
+ if (input == null)
+ return null;
+
+ StringBuilder sb = new StringBuilder (input.Length * 2);
+ foreach (byte b in input) {
+ sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
+ }
+ return sb.ToString ();
+ }
+
+ static private byte FromHexChar (char c)
+ {
+ if ((c >= 'a') && (c <= 'f'))
+ return (byte) (c - 'a' + 10);
+ if ((c >= 'A') && (c <= 'F'))
+ return (byte) (c - 'A' + 10);
+ if ((c >= '0') && (c <= '9'))
+ return (byte) (c - '0');
+ throw new ArgumentException ("invalid hex char");
+ }
+
+ static public byte[] FromHex (string hex)
+ {
+ if (hex == null)
+ return null;
+ if ((hex.Length & 0x1) == 0x1)
+ throw new ArgumentException ("Length must be a multiple of 2");
+
+ byte[] result = new byte [hex.Length >> 1];
+ int n = 0;
+ int i = 0;
+ while (n < result.Length) {
+ result [n] = (byte) (FromHexChar (hex [i++]) << 4);
+ result [n++] += FromHexChar (hex [i++]);
+ }
+ return result;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Security.Cryptography;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection.Impl
+{
+ static class CryptoHack
+ {
+ internal static RSA CreateRSA(StrongNameKeyPair keyPair)
+ {
+ // HACK use serialization to get at the private key or key container name,
+ // this should be more future proof than using reflection to access the fields directly.
+ SerializationInfo ser = new SerializationInfo(typeof(StrongNameKeyPair), new FormatterConverter());
+ ((ISerializable)keyPair.keyPair).GetObjectData(ser, new StreamingContext());
+ byte[] key = (byte[])ser.GetValue("_keyPairArray", typeof(byte[]));
+ string keycontainer = ser.GetString("_keyPairContainer");
+ if (keycontainer != null)
+ {
+ CspParameters parm = new CspParameters();
+ parm.Flags = CspProviderFlags.UseMachineKeyStore;
+ parm.KeyContainerName = keycontainer;
+ parm.KeyNumber = 2; // Signature
+ return new RSACryptoServiceProvider(parm);
+ }
+ else
+ {
+ return Mono.Security.Cryptography.CryptoConvert.FromCapiKeyBlob(key);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+ interface ITypeOwner
+ {
+ ModuleBuilder ModuleBuilder { get; }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+#if MONO
+using System;
+using System.Collections.Generic;
+using Mono.CompilerServices.SymbolWriter;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+ sealed class Method : IMethodDef
+ {
+ internal int token;
+ internal string name;
+ internal SymbolDocumentWriter document;
+ internal int[] offsets;
+ internal int[] lines;
+ internal int[] columns;
+ internal List<string> variables = new List<string>();
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public int Token
+ {
+ get { return token; }
+ }
+ }
+
+ sealed class SymbolDocumentWriter : System.Diagnostics.SymbolStore.ISymbolDocumentWriter
+ {
+ internal readonly string url;
+ internal SourceFileEntry source;
+
+ internal SymbolDocumentWriter(string url)
+ {
+ this.url = url;
+ }
+
+ public void SetCheckSum(Guid algorithmId, byte[] checkSum)
+ {
+ }
+
+ public void SetSource(byte[] source)
+ {
+ }
+ }
+
+ sealed class MdbWriter : ISymbolWriterImpl
+ {
+ private readonly ModuleBuilder moduleBuilder;
+ private readonly Dictionary<int, Method> methods = new Dictionary<int, Method>();
+ private readonly Dictionary<string, SymbolDocumentWriter> documents = new Dictionary<string, SymbolDocumentWriter>();
+ private Method currentMethod;
+
+ internal MdbWriter(ModuleBuilder moduleBuilder)
+ {
+ this.moduleBuilder = moduleBuilder;
+ }
+
+ public byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd)
+ {
+ return Empty<byte>.Array;
+ }
+
+ public void RemapToken(int oldToken, int newToken)
+ {
+ if (methods.ContainsKey(oldToken))
+ {
+ methods[oldToken].token = newToken;
+ }
+ }
+
+ public void Close()
+ {
+ MonoSymbolWriter writer = new MonoSymbolWriter(moduleBuilder.FullyQualifiedName);
+
+ foreach (Method method in methods.Values)
+ {
+ if (method.document != null)
+ {
+ if (method.document.source == null)
+ {
+ method.document.source = new SourceFileEntry(writer.SymbolFile, method.document.url);
+ }
+ ICompileUnit file = new CompileUnitEntry(writer.SymbolFile, method.document.source);
+ SourceMethodBuilder smb = writer.OpenMethod(file, 0, method);
+ for (int i = 0; i < method.offsets.Length; i++)
+ {
+ smb.MarkSequencePoint(method.offsets[i], method.document.source, method.lines[i], method.columns[i], false);
+ }
+ for (int i = 0; i < method.variables.Count; i++)
+ {
+ writer.DefineLocalVariable(i, method.variables[i]);
+ }
+ writer.CloseMethod();
+ }
+ }
+
+ writer.WriteSymbolFile(moduleBuilder.ModuleVersionId);
+ }
+
+ public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
+ {
+ SymbolDocumentWriter writer;
+ if (!documents.TryGetValue(url, out writer))
+ {
+ writer = new SymbolDocumentWriter(url);
+ documents.Add(url, writer);
+ }
+ return writer;
+ }
+
+ public void OpenMethod(System.Diagnostics.SymbolStore.SymbolToken token)
+ {
+ Method method = new Method();
+ method.token = token.GetToken();
+ // name doesn't appear to be used. We can look it up, but ModuleBuilder.ResolveMethod() is inefficient,
+ // so if it isn't used, why bother?
+ method.name = null; // moduleBuilder.ResolveMethod(token.GetToken()).Name;
+ methods.Add(token.GetToken(), method);
+ currentMethod = method;
+ }
+
+ public void CloseMethod()
+ {
+ currentMethod = null;
+ }
+
+ public void DefineLocalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+ {
+ }
+
+ public void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+ {
+ currentMethod.variables.Add(name);
+ }
+
+ public void DefineSequencePoints(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)
+ {
+ currentMethod.document = (SymbolDocumentWriter)document;
+ currentMethod.offsets = offsets;
+ currentMethod.lines = lines;
+ currentMethod.columns = columns;
+ }
+
+ public void DefineParameter(string name, System.Reflection.ParameterAttributes attributes, int sequence, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3)
+ {
+ }
+
+ public void DefineField(System.Diagnostics.SymbolStore.SymbolToken parent, string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3)
+ {
+ }
+
+ public void DefineGlobalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, System.Diagnostics.SymbolStore.SymAddressKind addrKind, int addr1, int addr2, int addr3)
+ {
+ }
+
+ public void OpenNamespace(string name)
+ {
+ }
+
+ public void CloseNamespace()
+ {
+ }
+
+ public void UsingNamespace(string fullName)
+ {
+ }
+
+ public int OpenScope(int startOffset)
+ {
+ return 0;
+ }
+
+ public void CloseScope(int endOffset)
+ {
+ }
+
+ public void SetMethodSourceRange(System.Diagnostics.SymbolStore.ISymbolDocumentWriter startDoc, int startLine, int startColumn, System.Diagnostics.SymbolStore.ISymbolDocumentWriter endDoc, int endLine, int endColumn)
+ {
+ }
+
+ public void SetScopeRange(int scopeID, int startOffset, int endOffset)
+ {
+ }
+
+ public void SetSymAttribute(System.Diagnostics.SymbolStore.SymbolToken parent, string name, byte[] data)
+ {
+ }
+
+ public void SetUserEntryPoint(System.Diagnostics.SymbolStore.SymbolToken entryMethod)
+ {
+ }
+
+ public void SetUnderlyingWriter(IntPtr underlyingWriter)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public void Initialize(IntPtr emitter, string filename, bool fFullBuild)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+}
+#endif // MONO
--- /dev/null
+/*
+ Copyright (C) 2008-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Diagnostics.SymbolStore;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+ [Guid("7dac8207-d3ae-4c75-9b67-92801a497d44")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ interface IMetaDataImport
+ {
+ void PlaceHolder_CloseEnum();
+ void PlaceHolder_CountEnum();
+ void PlaceHolder_ResetEnum();
+ void PlaceHolder_EnumTypeDefs();
+ void PlaceHolder_EnumInterfaceImpls();
+ void PlaceHolder_EnumTypeRefs();
+ void PlaceHolder_FindTypeDefByName();
+ void PlaceHolder_GetScopeProps();
+ void PlaceHolder_GetModuleFromScope();
+
+ void GetTypeDefProps(
+ int td, // [IN] TypeDef token for inquiry.
+ IntPtr szTypeDef, // [OUT] Put name here.
+ int cchTypeDef, // [IN] size of name buffer in wide chars.
+ IntPtr pchTypeDef, // [OUT] put size of name (wide chars) here.
+ IntPtr pdwTypeDefFlags, // [OUT] Put flags here.
+ IntPtr ptkExtends); // [OUT] Put base class TypeDef/TypeRef here.
+
+ void PlaceHolder_GetInterfaceImplProps();
+ void PlaceHolder_GetTypeRefProps();
+ void PlaceHolder_ResolveTypeRef();
+ void PlaceHolder_EnumMembers();
+ void PlaceHolder_EnumMembersWithName();
+ void PlaceHolder_EnumMethods();
+ void PlaceHolder_EnumMethodsWithName();
+ void PlaceHolder_EnumFields();
+ void PlaceHolder_EnumFieldsWithName();
+ void PlaceHolder_EnumParams();
+ void PlaceHolder_EnumMemberRefs();
+ void PlaceHolder_EnumMethodImpls();
+ void PlaceHolder_EnumPermissionSets();
+ void PlaceHolder_FindMember();
+ void PlaceHolder_FindMethod();
+ void PlaceHolder_FindField();
+ void PlaceHolder_FindMemberRef();
+
+ void GetMethodProps(
+ int mb, // The method for which to get props.
+ IntPtr pClass, // Put method's class here.
+ IntPtr szMethod, // Put method's name here.
+ int cchMethod, // Size of szMethod buffer in wide chars.
+ IntPtr pchMethod, // Put actual size here
+ IntPtr pdwAttr, // Put flags here.
+ IntPtr ppvSigBlob, // [OUT] point to the blob value of meta data
+ IntPtr pcbSigBlob, // [OUT] actual size of signature blob
+ IntPtr pulCodeRVA, // [OUT] codeRVA
+ IntPtr pdwImplFlags); // [OUT] Impl. Flags
+
+ void PlaceHolder_GetMemberRefProps();
+ void PlaceHolder_EnumProperties();
+ void PlaceHolder_EnumEvents();
+ void PlaceHolder_GetEventProps();
+ void PlaceHolder_EnumMethodSemantics();
+ void PlaceHolder_GetMethodSemantics();
+ void PlaceHolder_GetClassLayout();
+ void PlaceHolder_GetFieldMarshal();
+ void PlaceHolder_GetRVA();
+ void PlaceHolder_GetPermissionSetProps();
+ void PlaceHolder_GetSigFromToken();
+ void PlaceHolder_GetModuleRefProps();
+ void PlaceHolder_EnumModuleRefs();
+ void PlaceHolder_GetTypeSpecFromToken();
+ void PlaceHolder_GetNameFromToken();
+ void PlaceHolder_EnumUnresolvedMethods();
+ void PlaceHolder_GetUserString();
+ void PlaceHolder_GetPinvokeMap();
+ void PlaceHolder_EnumSignatures();
+ void PlaceHolder_EnumTypeSpecs();
+ void PlaceHolder_EnumUserStrings();
+ void PlaceHolder_GetParamForMethodIndex();
+ void PlaceHolder_EnumCustomAttributes();
+ void PlaceHolder_GetCustomAttributeProps();
+ void PlaceHolder_FindTypeRef();
+ void PlaceHolder_GetMemberProps();
+ void PlaceHolder_GetFieldProps();
+ void PlaceHolder_GetPropertyProps();
+ void PlaceHolder_GetParamProps();
+ void PlaceHolder_GetCustomAttributeByName();
+ void PlaceHolder_IsValidToken();
+
+ void GetNestedClassProps(
+ int tdNestedClass, // [IN] NestedClass token.
+ IntPtr ptdEnclosingClass); // [OUT] EnclosingClass token.
+
+ void PlaceHolder_GetNativeCallConvFromSig();
+ void PlaceHolder_IsGlobal();
+ }
+
+ [Guid("ba3fee4c-ecb9-4e41-83b7-183fa41cd859")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ interface IMetaDataEmit
+ {
+ void PlaceHolder_SetModuleProps();
+ void PlaceHolder_Save();
+ void PlaceHolder_SaveToStream();
+ void PlaceHolder_GetSaveSize();
+ void PlaceHolder_DefineTypeDef();
+ void PlaceHolder_DefineNestedType();
+ void PlaceHolder_SetHandler();
+ void PlaceHolder_DefineMethod();
+ void PlaceHolder_DefineMethodImpl();
+ void PlaceHolder_DefineTypeRefByName();
+ void PlaceHolder_DefineImportType();
+ void PlaceHolder_DefineMemberRef();
+ void PlaceHolder_DefineImportMember();
+ void PlaceHolder_DefineEvent();
+ void PlaceHolder_SetClassLayout();
+ void PlaceHolder_DeleteClassLayout();
+ void PlaceHolder_SetFieldMarshal();
+ void PlaceHolder_DeleteFieldMarshal();
+ void PlaceHolder_DefinePermissionSet();
+ void PlaceHolder_SetRVA();
+ void PlaceHolder_GetTokenFromSig();
+ void PlaceHolder_DefineModuleRef();
+ void PlaceHolder_SetParent();
+ void PlaceHolder_GetTokenFromTypeSpec();
+ void PlaceHolder_SaveToMemory();
+ void PlaceHolder_DefineUserString();
+ void PlaceHolder_DeleteToken();
+ void PlaceHolder_SetMethodProps();
+ void PlaceHolder_SetTypeDefProps();
+ void PlaceHolder_SetEventProps();
+ void PlaceHolder_SetPermissionSetProps();
+ void PlaceHolder_DefinePinvokeMap();
+ void PlaceHolder_SetPinvokeMap();
+ void PlaceHolder_DeletePinvokeMap();
+ void PlaceHolder_DefineCustomAttribute();
+ void PlaceHolder_SetCustomAttributeValue();
+ void PlaceHolder_DefineField();
+ void PlaceHolder_DefineProperty();
+ void PlaceHolder_DefineParam();
+ void PlaceHolder_SetFieldProps();
+ void PlaceHolder_SetPropertyProps();
+ void PlaceHolder_SetParamProps();
+ void PlaceHolder_DefineSecurityAttributeSet();
+ void PlaceHolder_ApplyEditAndContinue();
+ void PlaceHolder_TranslateSigWithScope();
+ void PlaceHolder_SetMethodImplFlags();
+ void PlaceHolder_SetFieldRVA();
+ void PlaceHolder_Merge();
+ void PlaceHolder_MergeEnd();
+ }
+
+ [Guid("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ internal interface ISymUnmanagedDocumentWriter { }
+
+ [Guid("0b97726e-9e6d-4f05-9a26-424022093caa")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ [CoClass(typeof(CorSymWriterClass))]
+ interface ISymUnmanagedWriter2
+ {
+ ISymUnmanagedDocumentWriter DefineDocument(string url, ref Guid language, ref Guid languageVendor, ref Guid documentType);
+ void PlaceHolder_SetUserEntryPoint();
+ void OpenMethod(int method);
+ void CloseMethod();
+ int OpenScope(int startOffset);
+ void CloseScope(int endOffset);
+ void PlaceHolder_SetScopeRange();
+ void DefineLocalVariable(string name, int attributes, int cSig, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, int addrKind, int addr1, int addr2, int startOffset, int endOffset);
+ void PlaceHolder_DefineParameter();
+ void PlaceHolder_DefineField();
+ void PlaceHolder_DefineGlobalVariable();
+ void Close();
+ void PlaceHolder_SetSymAttribute();
+ void PlaceHolder_OpenNamespace();
+ void PlaceHolder_CloseNamespace();
+ void PlaceHolder_UsingNamespace();
+ void PlaceHolder_SetMethodSourceRange();
+ void Initialize([MarshalAs(UnmanagedType.IUnknown)] object emitter, string filename, [MarshalAs(UnmanagedType.IUnknown)] object pIStream, bool fFullBuild);
+
+ void GetDebugInfo(
+ [In, Out] ref IMAGE_DEBUG_DIRECTORY pIDD,
+ [In] uint cData,
+ [Out] out uint pcData,
+ [Out, MarshalAs(UnmanagedType.LPArray)] byte[] data);
+
+ void DefineSequencePoints(ISymUnmanagedDocumentWriter document, int spCount,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns);
+
+ void RemapToken(
+ [In] int oldToken,
+ [In] int newToken);
+
+ void PlaceHolder_Initialize2();
+ void PlaceHolder_DefineConstant();
+ void PlaceHolder_Abort();
+
+ void DefineLocalVariable2(string name, int attributes, int token, int addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset);
+
+ void PlaceHolder_DefineGlobalVariable2();
+ void PlaceHolder_DefineConstant2();
+ }
+
+ [Guid("108296c1-281e-11d3-bd22-0000f80849bd")]
+ [ComImport]
+ class CorSymWriterClass { }
+
+ sealed class PdbWriter : ISymbolWriterImpl, IMetaDataEmit, IMetaDataImport
+ {
+ private readonly ModuleBuilder moduleBuilder;
+ private ISymUnmanagedWriter2 symUnmanagedWriter;
+ private readonly Dictionary<string, Document> documents = new Dictionary<string, Document>();
+ private readonly List<Method> methods = new List<Method>();
+ private readonly Dictionary<int, int> remap = new Dictionary<int, int>();
+ private readonly Dictionary<int, int> reversemap = new Dictionary<int, int>();
+ private Method currentMethod;
+
+ internal PdbWriter(ModuleBuilder moduleBuilder)
+ {
+ this.moduleBuilder = moduleBuilder;
+ }
+
+ private sealed class Document : ISymbolDocumentWriter
+ {
+ internal readonly string url;
+ private Guid language;
+ private Guid languageVendor;
+ private Guid documentType;
+ private ISymUnmanagedDocumentWriter unmanagedDocument;
+
+ internal Document(string url, Guid language, Guid languageVendor, Guid documentType)
+ {
+ this.url = url;
+ this.language = language;
+ this.languageVendor = languageVendor;
+ this.documentType = documentType;
+ }
+
+ public void SetCheckSum(Guid algorithmId, byte[] checkSum)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetSource(byte[] source)
+ {
+ throw new NotImplementedException();
+ }
+
+ internal ISymUnmanagedDocumentWriter GetUnmanagedDocument(ISymUnmanagedWriter2 symUnmanagedWriter)
+ {
+ if (unmanagedDocument == null)
+ {
+ unmanagedDocument = symUnmanagedWriter.DefineDocument(url, ref language, ref languageVendor, ref documentType);
+ }
+ return unmanagedDocument;
+ }
+
+ internal void Release()
+ {
+ if (unmanagedDocument != null)
+ {
+ Marshal.ReleaseComObject(unmanagedDocument);
+ unmanagedDocument = null;
+ }
+ }
+ }
+
+ private sealed class LocalVar
+ {
+ internal readonly FieldAttributes attributes;
+ internal readonly int signature;
+ internal readonly SymAddressKind addrKind;
+ internal readonly int addr1;
+ internal readonly int addr2;
+ internal readonly int addr3;
+ internal readonly int startOffset;
+ internal readonly int endOffset;
+
+ internal LocalVar(FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+ {
+ this.attributes = attributes;
+ this.signature = signature;
+ this.addrKind = addrKind;
+ this.addr1 = addr1;
+ this.addr2 = addr2;
+ this.addr3 = addr3;
+ this.startOffset = startOffset;
+ this.endOffset = endOffset;
+ }
+ }
+
+ private sealed class Scope
+ {
+ internal readonly int startOffset;
+ internal int endOffset;
+ internal readonly List<Scope> scopes = new List<Scope>();
+ internal readonly Dictionary<string, LocalVar> locals = new Dictionary<string, LocalVar>();
+
+ internal Scope(int startOffset)
+ {
+ this.startOffset = startOffset;
+ }
+
+ internal void Do(ISymUnmanagedWriter2 symUnmanagedWriter)
+ {
+ symUnmanagedWriter.OpenScope(startOffset);
+ foreach (KeyValuePair<string, LocalVar> kv in locals)
+ {
+ symUnmanagedWriter.DefineLocalVariable2(kv.Key, (int)kv.Value.attributes, kv.Value.signature, (int)kv.Value.addrKind, kv.Value.addr1, kv.Value.addr2, kv.Value.addr3, kv.Value.startOffset, kv.Value.endOffset);
+ }
+ foreach (Scope scope in scopes)
+ {
+ scope.Do(symUnmanagedWriter);
+ }
+ symUnmanagedWriter.CloseScope(endOffset);
+ }
+ }
+
+ private sealed class Method
+ {
+ internal readonly int token;
+ internal Document document;
+ internal int[] offsets;
+ internal int[] lines;
+ internal int[] columns;
+ internal int[] endLines;
+ internal int[] endColumns;
+ internal readonly List<Scope> scopes = new List<Scope>();
+ internal readonly Stack<Scope> scopeStack = new Stack<Scope>();
+
+ internal Method(int token)
+ {
+ this.token = token;
+ }
+ }
+
+ public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
+ {
+ Document doc;
+ if (!documents.TryGetValue(url, out doc))
+ {
+ doc = new Document(url, language, languageVendor, documentType);
+ documents.Add(url, doc);
+ }
+ return doc;
+ }
+
+ public void OpenMethod(SymbolToken method)
+ {
+ currentMethod = new Method(method.GetToken());
+ }
+
+ public void CloseMethod()
+ {
+ methods.Add(currentMethod);
+ currentMethod = null;
+ }
+
+ public void DefineSequencePoints(ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)
+ {
+ currentMethod.document = (Document)document;
+ currentMethod.offsets = offsets;
+ currentMethod.lines = lines;
+ currentMethod.columns = columns;
+ currentMethod.endLines = endLines;
+ currentMethod.endColumns = endColumns;
+ }
+
+ public int OpenScope(int startOffset)
+ {
+ Scope scope = new Scope(startOffset);
+ if (currentMethod.scopeStack.Count == 0)
+ {
+ currentMethod.scopes.Add(scope);
+ }
+ else
+ {
+ currentMethod.scopeStack.Peek().scopes.Add(scope);
+ }
+ currentMethod.scopeStack.Push(scope);
+ return 0;
+ }
+
+ public void CloseScope(int endOffset)
+ {
+ currentMethod.scopeStack.Pop().endOffset = endOffset;
+ }
+
+ public void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+ {
+ currentMethod.scopeStack.Peek().locals[name] = new LocalVar(attributes, signature, addrKind, addr1, addr2, addr3, startOffset, endOffset);
+ }
+
+ private void InitWriter()
+ {
+ if (symUnmanagedWriter == null)
+ {
+ string fileName = System.IO.Path.ChangeExtension(moduleBuilder.FullyQualifiedName, ".pdb");
+ // pro-actively delete the .pdb to get a meaningful IOException, instead of COMInteropException if the file can't be overwritten (or is corrupt, or who knows what)
+ System.IO.File.Delete(fileName);
+ symUnmanagedWriter = new ISymUnmanagedWriter2();
+ symUnmanagedWriter.Initialize(this, fileName, null, true);
+ }
+ }
+
+ public byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd)
+ {
+ InitWriter();
+ uint cData;
+ symUnmanagedWriter.GetDebugInfo(ref idd, 0, out cData, null);
+ byte[] buf = new byte[cData];
+ symUnmanagedWriter.GetDebugInfo(ref idd, (uint)buf.Length, out cData, buf);
+ return buf;
+ }
+
+ public void RemapToken(int oldToken, int newToken)
+ {
+ remap.Add(oldToken, newToken);
+ reversemap.Add(newToken, oldToken);
+ }
+
+ public void Close()
+ {
+ InitWriter();
+
+ foreach (Method method in methods)
+ {
+ int remappedToken = method.token;
+ remap.TryGetValue(remappedToken, out remappedToken);
+ symUnmanagedWriter.OpenMethod(remappedToken);
+ if (method.document != null)
+ {
+ ISymUnmanagedDocumentWriter doc = method.document.GetUnmanagedDocument(symUnmanagedWriter);
+ symUnmanagedWriter.DefineSequencePoints(doc, method.offsets.Length, method.offsets, method.lines, method.columns, method.endLines, method.endColumns);
+ }
+ foreach (Scope scope in method.scopes)
+ {
+ scope.Do(symUnmanagedWriter);
+ }
+ symUnmanagedWriter.CloseMethod();
+ }
+
+ foreach (Document doc in documents.Values)
+ {
+ doc.Release();
+ }
+
+ symUnmanagedWriter.Close();
+ Marshal.ReleaseComObject(symUnmanagedWriter);
+ symUnmanagedWriter = null;
+ documents.Clear();
+ methods.Clear();
+ remap.Clear();
+ reversemap.Clear();
+ }
+
+ public void DefineLocalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void CloseNamespace()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DefineField(SymbolToken parent, string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DefineGlobalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DefineParameter(string name, System.Reflection.ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Initialize(IntPtr emitter, string filename, bool fFullBuild)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OpenNamespace(string name)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetMethodSourceRange(ISymbolDocumentWriter startDoc, int startLine, int startColumn, ISymbolDocumentWriter endDoc, int endLine, int endColumn)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetScopeRange(int scopeID, int startOffset, int endOffset)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetSymAttribute(SymbolToken parent, string name, byte[] data)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetUnderlyingWriter(IntPtr underlyingWriter)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetUserEntryPoint(SymbolToken entryMethod)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void UsingNamespace(string fullName)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_CloseEnum()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_CountEnum()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_ResetEnum()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumTypeDefs()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumInterfaceImpls()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumTypeRefs()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_FindTypeDefByName()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetScopeProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetModuleFromScope()
+ {
+ throw new NotImplementedException();
+ }
+
+ private static void WriteString(IntPtr ptrString, IntPtr ptrLength, string str, int length)
+ {
+ if (ptrString != IntPtr.Zero)
+ {
+ for (int i = 0; i < Math.Min(length, str.Length); i++)
+ {
+ Marshal.WriteInt16(ptrString, i, str[i]);
+ }
+ }
+ if (ptrLength != IntPtr.Zero)
+ {
+ Marshal.WriteInt32(ptrLength, str.Length);
+ }
+ }
+
+ private static void WriteToken(IntPtr ptr, MemberInfo member)
+ {
+ if (ptr != IntPtr.Zero)
+ {
+ Marshal.WriteInt32(ptr, member == null ? 0 : member.MetadataToken);
+ }
+ }
+
+ private static void WriteInt32(IntPtr ptr, int value)
+ {
+ if (ptr != IntPtr.Zero)
+ {
+ Marshal.WriteInt32(ptr, value);
+ }
+ }
+
+ public void GetTypeDefProps(
+ int td, // [IN] TypeDef token for inquiry.
+ IntPtr szTypeDef, // [OUT] Put name here.
+ int cchTypeDef, // [IN] size of name buffer in wide chars.
+ IntPtr pchTypeDef, // [OUT] put size of name (wide chars) here.
+ IntPtr pdwTypeDefFlags, // [OUT] Put flags here.
+ IntPtr ptkExtends) // [OUT] Put base class TypeDef/TypeRef here.
+ {
+ if (td == 0)
+ {
+ // why are we being called with an invalid token?
+ WriteString(szTypeDef, pchTypeDef, "", cchTypeDef);
+ WriteInt32(pdwTypeDefFlags, 0);
+ WriteToken(ptkExtends, null);
+ }
+ else
+ {
+ Type type = moduleBuilder.ResolveType(td);
+ WriteString(szTypeDef, pchTypeDef, type.FullName, cchTypeDef);
+ WriteInt32(pdwTypeDefFlags, (int)type.Attributes);
+ WriteToken(ptkExtends, type.BaseType);
+ }
+ }
+
+ public void PlaceHolder_GetInterfaceImplProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetTypeRefProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_ResolveTypeRef()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumMembers()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumMembersWithName()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumMethods()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumMethodsWithName()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumFields()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumFieldsWithName()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumParams()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumMemberRefs()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumMethodImpls()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumPermissionSets()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_FindMember()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_FindMethod()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_FindField()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_FindMemberRef()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void GetMethodProps(
+ int mb, // The method for which to get props.
+ IntPtr pClass, // [OUT] Put method's class here.
+ IntPtr szMethod, // [OUT] Put method's name here.
+ int cchMethod, // Size of szMethod buffer in wide chars.
+ IntPtr pchMethod, // [OUT] Put actual size here
+ IntPtr pdwAttr, // [OUT] Put flags here.
+ IntPtr ppvSigBlob, // [OUT] point to the blob value of meta data
+ IntPtr pcbSigBlob, // [OUT] actual size of signature blob
+ IntPtr pulCodeRVA, // [OUT] codeRVA
+ IntPtr pdwImplFlags) // [OUT] Impl. Flags
+ {
+ if (pdwAttr != IntPtr.Zero || ppvSigBlob != IntPtr.Zero || pcbSigBlob != IntPtr.Zero || pulCodeRVA != IntPtr.Zero || pdwImplFlags != IntPtr.Zero)
+ {
+ throw new NotImplementedException();
+ }
+ MethodBase method = moduleBuilder.ResolveMethod(reversemap[mb]);
+ WriteToken(pClass, method.DeclaringType);
+ WriteString(szMethod, pchMethod, method.Name, cchMethod);
+ }
+
+ public void PlaceHolder_GetMemberRefProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumProperties()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumEvents()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetEventProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumMethodSemantics()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetMethodSemantics()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetClassLayout()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetFieldMarshal()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetRVA()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetPermissionSetProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetSigFromToken()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetModuleRefProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumModuleRefs()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetTypeSpecFromToken()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetNameFromToken()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumUnresolvedMethods()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetUserString()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetPinvokeMap()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumSignatures()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumTypeSpecs()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumUserStrings()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetParamForMethodIndex()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_EnumCustomAttributes()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetCustomAttributeProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_FindTypeRef()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetMemberProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetFieldProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetPropertyProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetParamProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetCustomAttributeByName()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_IsValidToken()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void GetNestedClassProps(
+ int tdNestedClass, // [IN] NestedClass token.
+ IntPtr ptdEnclosingClass) // [OUT] EnclosingClass token.
+ {
+ Type type = moduleBuilder.ResolveType(tdNestedClass);
+ WriteToken(ptdEnclosingClass, type.DeclaringType);
+ }
+
+ public void PlaceHolder_GetNativeCallConvFromSig()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_IsGlobal()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetModuleProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_Save()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SaveToStream()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetSaveSize()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineTypeDef()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineNestedType()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetHandler()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineMethod()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineMethodImpl()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineTypeRefByName()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineImportType()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineMemberRef()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineImportMember()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineEvent()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetClassLayout()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DeleteClassLayout()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetFieldMarshal()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DeleteFieldMarshal()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefinePermissionSet()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetRVA()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetTokenFromSig()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineModuleRef()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetParent()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_GetTokenFromTypeSpec()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SaveToMemory()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineUserString()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DeleteToken()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetMethodProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetTypeDefProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetEventProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetPermissionSetProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefinePinvokeMap()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetPinvokeMap()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DeletePinvokeMap()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineCustomAttribute()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetCustomAttributeValue()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineField()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineProperty()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineParam()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetFieldProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetPropertyProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetParamProps()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_DefineSecurityAttributeSet()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_ApplyEditAndContinue()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_TranslateSigWithScope()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetMethodImplFlags()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_SetFieldRVA()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_Merge()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void PlaceHolder_MergeEnd()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008, 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics.SymbolStore;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Impl
+{
+ [StructLayout(LayoutKind.Sequential)]
+ struct IMAGE_DEBUG_DIRECTORY
+ {
+ public uint Characteristics;
+ public uint TimeDateStamp;
+ public ushort MajorVersion;
+ public ushort MinorVersion;
+ public uint Type;
+ public uint SizeOfData;
+ public uint AddressOfRawData;
+ public uint PointerToRawData;
+ }
+
+ interface ISymbolWriterImpl : ISymbolWriter
+ {
+ byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd);
+ void RemapToken(int oldToken, int newToken);
+ void DefineLocalVariable2(string name, FieldAttributes attributes, int signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset);
+ }
+
+ static class SymbolSupport
+ {
+ private static readonly bool runningOnMono = System.Type.GetType("Mono.Runtime") != null;
+
+ internal static ISymbolWriterImpl CreateSymbolWriterFor(ModuleBuilder moduleBuilder)
+ {
+#if !NO_SYMBOL_WRITER
+ throw new NotSupportedException ("IKVM.Reflection with no symbol writer support");
+#else
+ if (runningOnMono)
+ {
+#if MONO
+ return new MdbWriter(moduleBuilder);
+#else
+ throw new NotSupportedException("IKVM.Reflection must be compiled with MONO defined to support writing Mono debugging symbols.");
+#endif
+ }
+ else
+ {
+ return new PdbWriter(moduleBuilder);
+ }
+#endif
+ }
+
+ internal static byte[] GetDebugInfo(ISymbolWriterImpl writer, ref IMAGE_DEBUG_DIRECTORY idd)
+ {
+ return writer.GetDebugInfo(ref idd);
+ }
+
+ internal static void RemapToken(ISymbolWriterImpl writer, int oldToken, int newToken)
+ {
+ writer.RemapToken(oldToken, newToken);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+ public struct InterfaceMapping
+ {
+ public MethodInfo[] InterfaceMethods;
+ public Type InterfaceType;
+ public MethodInfo[] TargetMethods;
+ public Type TargetType;
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+ public class LocalVariableInfo
+ {
+ private readonly int index;
+ private readonly Type type;
+ private readonly bool pinned;
+
+ internal LocalVariableInfo(int index, Type type, bool pinned)
+ {
+ this.index = index;
+ this.type = type;
+ this.pinned = pinned;
+ }
+
+ public virtual bool IsPinned
+ {
+ get { return pinned; }
+ }
+
+ public virtual int LocalIndex
+ {
+ get { return index; }
+ }
+
+ public virtual Type LocalType
+ {
+ get { return type; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+ public class ManifestResourceInfo
+ {
+ private readonly ModuleReader module;
+ private readonly int index;
+
+ internal ManifestResourceInfo(ModuleReader module, int index)
+ {
+ this.module = module;
+ this.index = index;
+ }
+
+ public ResourceLocation ResourceLocation
+ {
+ get
+ {
+ int implementation = module.ManifestResource.records[index].Implementation;
+ if ((implementation >> 24) == AssemblyRefTable.Index)
+ {
+ //return ResourceLocation.ContainedInAnotherAssembly;
+ throw new NotImplementedException();
+ }
+ else if ((implementation >> 24) == FileTable.Index)
+ {
+ if ((implementation & 0xFFFFFF) == 0)
+ {
+ return ResourceLocation.ContainedInManifestFile | ResourceLocation.Embedded;
+ }
+ return 0;
+ }
+ else
+ {
+ throw new BadImageFormatException();
+ }
+ }
+ }
+
+ public Assembly ReferencedAssembly
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public string FileName
+ {
+ get
+ {
+ int implementation = module.ManifestResource.records[index].Implementation;
+ if ((implementation >> 24) == FileTable.Index)
+ {
+ if ((implementation & 0xFFFFFF) == 0)
+ {
+ return null;
+ }
+ else
+ {
+ return module.GetString(module.File.records[(implementation & 0xFFFFFF) - 1].Name);
+ }
+ }
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008, 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+ static class MarshalSpec
+ {
+ private const UnmanagedType NATIVE_TYPE_MAX = (UnmanagedType)0x50;
+
+ internal static CustomAttributeData GetMarshalAsAttribute(Module module, int token)
+ {
+ // TODO use binary search?
+ for (int i = 0; i < module.FieldMarshal.records.Length; i++)
+ {
+ if (module.FieldMarshal.records[i].Parent == token)
+ {
+ ByteReader blob = module.GetBlob(module.FieldMarshal.records[i].NativeType);
+ UnmanagedType unmanagedType = (UnmanagedType)blob.ReadCompressedInt();
+ UnmanagedType? arraySubType = null;
+ short? sizeParamIndex = null;
+ int? sizeConst = null;
+ VarEnum? safeArraySubType = null;
+ Type safeArrayUserDefinedSubType = null;
+ int? iidParameterIndex = null;
+ string marshalType = null;
+ string marshalCookie = null;
+ Type marshalTypeRef = null;
+ if (unmanagedType == UnmanagedType.LPArray)
+ {
+ arraySubType = (UnmanagedType)blob.ReadCompressedInt();
+ if (arraySubType == NATIVE_TYPE_MAX)
+ {
+ arraySubType = null;
+ }
+ if (blob.Length != 0)
+ {
+ sizeParamIndex = (short)blob.ReadCompressedInt();
+ if (blob.Length != 0)
+ {
+ sizeConst = blob.ReadCompressedInt();
+ if (blob.Length != 0 && blob.ReadCompressedInt() == 0)
+ {
+ sizeParamIndex = null;
+ }
+ }
+ }
+ }
+ else if (unmanagedType == UnmanagedType.SafeArray)
+ {
+ if (blob.Length != 0)
+ {
+ safeArraySubType = (VarEnum)blob.ReadCompressedInt();
+ if (blob.Length != 0)
+ {
+ safeArrayUserDefinedSubType = ReadType(module, blob);
+ }
+ }
+ }
+ else if (unmanagedType == UnmanagedType.ByValArray)
+ {
+ sizeConst = blob.ReadCompressedInt();
+ if (blob.Length != 0)
+ {
+ arraySubType = (UnmanagedType)blob.ReadCompressedInt();
+ }
+ }
+ else if (unmanagedType == UnmanagedType.ByValTStr)
+ {
+ sizeConst = blob.ReadCompressedInt();
+ }
+ else if (unmanagedType == UnmanagedType.Interface
+ || unmanagedType == UnmanagedType.IDispatch
+ || unmanagedType == UnmanagedType.IUnknown)
+ {
+ if (blob.Length != 0)
+ {
+ iidParameterIndex = blob.ReadCompressedInt();
+ }
+ }
+ else if (unmanagedType == UnmanagedType.CustomMarshaler)
+ {
+ blob.ReadCompressedInt();
+ blob.ReadCompressedInt();
+ marshalType = ReadString(blob);
+ marshalCookie = ReadString(blob);
+ marshalTypeRef = module.Assembly.GetType(marshalType) ?? module.universe.GetType(marshalType);
+ }
+
+ Type typeofMarshalAs = module.universe.System_Runtime_InteropServices_MarshalAsAttribute;
+ Type typeofUnmanagedType = module.universe.System_Runtime_InteropServices_UnmanagedType;
+ Type typeofVarEnum = module.universe.System_Runtime_InteropServices_VarEnum;
+ Type typeofType = module.universe.System_Type;
+ List<CustomAttributeNamedArgument> named = new List<CustomAttributeNamedArgument>();
+ if (arraySubType != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("ArraySubType"), new CustomAttributeTypedArgument(typeofUnmanagedType, arraySubType.Value)));
+ }
+ if (sizeParamIndex != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SizeParamIndex"), new CustomAttributeTypedArgument(module.universe.System_Int16, sizeParamIndex.Value)));
+ }
+ if (sizeConst != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SizeConst"), new CustomAttributeTypedArgument(module.universe.System_Int32, sizeConst.Value)));
+ }
+ if (safeArraySubType != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SafeArraySubType"), new CustomAttributeTypedArgument(typeofVarEnum, safeArraySubType.Value)));
+ }
+ if (safeArrayUserDefinedSubType != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SafeArrayUserDefinedSubType"), new CustomAttributeTypedArgument(typeofType, safeArrayUserDefinedSubType)));
+ }
+ if (iidParameterIndex != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("IidParameterIndex"), new CustomAttributeTypedArgument(module.universe.System_Int32, iidParameterIndex.Value)));
+ }
+ if (marshalType != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalType"), new CustomAttributeTypedArgument(module.universe.System_String, marshalType)));
+ }
+ if (marshalTypeRef != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalTypeRef"), new CustomAttributeTypedArgument(module.universe.System_Type, marshalTypeRef)));
+ }
+ if (marshalCookie != null)
+ {
+ named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalCookie"), new CustomAttributeTypedArgument(module.universe.System_String, marshalCookie)));
+ }
+ ConstructorInfo constructor = typeofMarshalAs.GetConstructor(new Type[] { typeofUnmanagedType });
+ return new CustomAttributeData(constructor, new object[] { unmanagedType }, named);
+ }
+ }
+ throw new BadImageFormatException();
+ }
+
+ internal static void SetMarshalAsAttribute(ModuleBuilder module, int token, CustomAttributeBuilder attribute)
+ {
+ attribute = attribute.DecodeBlob(module.Assembly);
+ FieldMarshalTable.Record rec = new FieldMarshalTable.Record();
+ rec.Parent = token;
+ rec.NativeType = WriteMarshallingDescriptor(module, attribute);
+ module.FieldMarshal.AddRecord(rec);
+ }
+
+ private static int WriteMarshallingDescriptor(ModuleBuilder module, CustomAttributeBuilder attribute)
+ {
+ UnmanagedType unmanagedType;
+ object val = attribute.GetConstructorArgument(0);
+ if (val is short)
+ {
+ unmanagedType = (UnmanagedType)(short)val;
+ }
+ else if (val is int)
+ {
+ unmanagedType = (UnmanagedType)(int)val;
+ }
+ else
+ {
+ unmanagedType = (UnmanagedType)val;
+ }
+
+ ByteBuffer bb = new ByteBuffer(5);
+ bb.WriteCompressedInt((int)unmanagedType);
+
+ if (unmanagedType == UnmanagedType.LPArray)
+ {
+ UnmanagedType arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType") ?? NATIVE_TYPE_MAX;
+ bb.WriteCompressedInt((int)arraySubType);
+ int? sizeParamIndex = attribute.GetFieldValue<short>("SizeParamIndex");
+ int? sizeConst = attribute.GetFieldValue<int>("SizeConst");
+ if (sizeParamIndex != null)
+ {
+ bb.WriteCompressedInt(sizeParamIndex.Value);
+ if (sizeConst != null)
+ {
+ bb.WriteCompressedInt(sizeConst.Value);
+ bb.WriteCompressedInt(1); // flag that says that SizeParamIndex was specified
+ }
+ }
+ else if (sizeConst != null)
+ {
+ bb.WriteCompressedInt(0); // SizeParamIndex
+ bb.WriteCompressedInt(sizeConst.Value);
+ bb.WriteCompressedInt(0); // flag that says that SizeParamIndex was not specified
+ }
+ }
+ else if (unmanagedType == UnmanagedType.SafeArray)
+ {
+ VarEnum? safeArraySubType = attribute.GetFieldValue<VarEnum>("SafeArraySubType");
+ if (safeArraySubType != null)
+ {
+ bb.WriteCompressedInt((int)safeArraySubType);
+ Type safeArrayUserDefinedSubType = (Type)attribute.GetFieldValue("SafeArrayUserDefinedSubType");
+ if (safeArrayUserDefinedSubType != null)
+ {
+ WriteType(module, bb, safeArrayUserDefinedSubType);
+ }
+ }
+ }
+ else if (unmanagedType == UnmanagedType.ByValArray)
+ {
+ bb.WriteCompressedInt(attribute.GetFieldValue<int>("SizeConst") ?? 1);
+ UnmanagedType? arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType");
+ if (arraySubType != null)
+ {
+ bb.WriteCompressedInt((int)arraySubType);
+ }
+ }
+ else if (unmanagedType == UnmanagedType.ByValTStr)
+ {
+ bb.WriteCompressedInt(attribute.GetFieldValue<int>("SizeConst").Value);
+ }
+ else if (unmanagedType == UnmanagedType.Interface
+ || unmanagedType == UnmanagedType.IDispatch
+ || unmanagedType == UnmanagedType.IUnknown)
+ {
+ int? iidParameterIndex = attribute.GetFieldValue<int>("IidParameterIndex");
+ if (iidParameterIndex != null)
+ {
+ bb.WriteCompressedInt(iidParameterIndex.Value);
+ }
+ }
+ else if (unmanagedType == UnmanagedType.CustomMarshaler)
+ {
+ bb.WriteCompressedInt(0);
+ bb.WriteCompressedInt(0);
+ string marshalType = (string)attribute.GetFieldValue("MarshalType");
+ if (marshalType != null)
+ {
+ WriteString(bb, marshalType);
+ }
+ else
+ {
+ WriteType(module, bb, (Type)attribute.GetFieldValue("MarshalTypeRef"));
+ }
+ WriteString(bb, (string)attribute.GetFieldValue("MarshalCookie") ?? "");
+ }
+
+ return module.Blobs.Add(bb);
+ }
+
+ private static Type ReadType(Module module, ByteReader br)
+ {
+ string str = ReadString(br);
+ if (str == "")
+ {
+ return null;
+ }
+ return module.Assembly.GetType(str) ?? module.universe.GetType(str, true);
+ }
+
+ private static void WriteType(Module module, ByteBuffer bb, Type type)
+ {
+ WriteString(bb, type.Assembly == module.Assembly ? type.FullName : type.AssemblyQualifiedName);
+ }
+
+ private static string ReadString(ByteReader br)
+ {
+ return Encoding.UTF8.GetString(br.ReadBytes(br.ReadCompressedInt()));
+ }
+
+ private static void WriteString(ByteBuffer bb, string str)
+ {
+ byte[] buf = Encoding.UTF8.GetBytes(str);
+ bb.WriteCompressedInt(buf.Length);
+ bb.Write(buf);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+// disable warnings that complain about us having == and != operators without also overriding Equals/GetHashCode,
+// this is intentional because most subtypes use reference equality
+#pragma warning disable 660, 661
+ public abstract class MemberInfo : ICustomAttributeProvider
+ {
+ public abstract string Name { get; }
+ public abstract Type DeclaringType { get; }
+ public abstract MemberTypes MemberType { get; }
+
+ public virtual int MetadataToken
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public abstract Module Module
+ {
+ get;
+ }
+
+ public bool IsDefined(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+ }
+
+ public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+ }
+
+ public static bool operator ==(MemberInfo m1, MemberInfo m2)
+ {
+ return ReferenceEquals(m1, m2) || (!ReferenceEquals(m1, null) && m1.Equals(m2));
+ }
+
+ public static bool operator !=(MemberInfo m1, MemberInfo m2)
+ {
+ return !(m1 == m2);
+ }
+
+ internal virtual IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return this.Module.GetCustomAttributes(this.MetadataToken, attributeType);
+ }
+
+ internal static bool BindingFlagsMatch(bool state, BindingFlags flags, BindingFlags trueFlag, BindingFlags falseFlag)
+ {
+ return (state && (flags & trueFlag) == trueFlag)
+ || (!state && (flags & falseFlag) == falseFlag);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System.IO;
+
+namespace IKVM.Reflection.Metadata
+{
+ sealed class CliHeader
+ {
+ internal const uint COMIMAGE_FLAGS_ILONLY = 0x00000001;
+ internal const uint COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002;
+ internal const uint COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008;
+ internal const uint COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = 0x00000010;
+
+ internal uint Cb = 0x48;
+ internal ushort MajorRuntimeVersion;
+ internal ushort MinorRuntimeVersion;
+ internal uint MetaDataRVA;
+ internal uint MetaDataSize;
+ internal uint Flags;
+ internal uint EntryPointToken;
+ internal uint ResourcesRVA;
+ internal uint ResourcesSize;
+ internal uint StrongNameSignatureRVA;
+ internal uint StrongNameSignatureSize;
+ internal ulong CodeManagerTable;
+ internal uint VTableFixupsRVA;
+ internal uint VTableFixupsSize;
+ internal ulong ExportAddressTableJumps;
+ internal ulong ManagedNativeHeader;
+
+ internal void Read(BinaryReader br)
+ {
+ Cb = br.ReadUInt32();
+ MajorRuntimeVersion = br.ReadUInt16();
+ MinorRuntimeVersion = br.ReadUInt16();
+ MetaDataRVA = br.ReadUInt32();
+ MetaDataSize = br.ReadUInt32();
+ Flags = br.ReadUInt32();
+ EntryPointToken = br.ReadUInt32();
+ ResourcesRVA = br.ReadUInt32();
+ ResourcesSize = br.ReadUInt32();
+ StrongNameSignatureRVA = br.ReadUInt32();
+ StrongNameSignatureSize = br.ReadUInt32();
+ CodeManagerTable = br.ReadUInt32();
+ VTableFixupsRVA = br.ReadUInt32();
+ VTableFixupsSize = br.ReadUInt32();
+ ExportAddressTableJumps = br.ReadUInt32();
+ ManagedNativeHeader = br.ReadUInt32();
+ }
+
+ internal void Write(IKVM.Reflection.Writer.MetadataWriter mw)
+ {
+ mw.Write(Cb);
+ mw.Write(MajorRuntimeVersion);
+ mw.Write(MinorRuntimeVersion);
+ mw.Write(MetaDataRVA);
+ mw.Write(MetaDataSize);
+ mw.Write(Flags);
+ mw.Write(EntryPointToken);
+ mw.Write(ResourcesRVA);
+ mw.Write(ResourcesSize);
+ mw.Write(StrongNameSignatureRVA);
+ mw.Write(StrongNameSignatureSize);
+ mw.Write(CodeManagerTable);
+ mw.Write(VTableFixupsRVA);
+ mw.Write(VTableFixupsSize);
+ mw.Write(ExportAddressTableJumps);
+ mw.Write(ManagedNativeHeader);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection.Metadata
+{
+ // base class for MetadataReader and MetadataWriter
+ abstract class MetadataRW
+ {
+ internal readonly bool bigStrings;
+ internal readonly bool bigGuids;
+ internal readonly bool bigBlobs;
+ internal readonly bool bigResolutionScope;
+ internal readonly bool bigTypeDefOrRef;
+ internal readonly bool bigMemberRefParent;
+ internal readonly bool bigHasCustomAttribute;
+ internal readonly bool bigCustomAttributeType;
+ internal readonly bool bigMethodDefOrRef;
+ internal readonly bool bigHasConstant;
+ internal readonly bool bigHasSemantics;
+ internal readonly bool bigHasFieldMarshal;
+ internal readonly bool bigHasDeclSecurity;
+ internal readonly bool bigTypeOrMethodDef;
+ internal readonly bool bigMemberForwarded;
+ internal readonly bool bigImplementation;
+ internal readonly bool bigField;
+ internal readonly bool bigMethodDef;
+ internal readonly bool bigParam;
+ internal readonly bool bigTypeDef;
+ internal readonly bool bigProperty;
+ internal readonly bool bigEvent;
+ internal readonly bool bigGenericParam;
+ internal readonly bool bigModuleRef;
+
+ protected MetadataRW(Module module, bool bigStrings, bool bigGuids, bool bigBlobs)
+ {
+ this.bigStrings = bigStrings;
+ this.bigGuids = bigGuids;
+ this.bigBlobs = bigBlobs;
+ this.bigField = module.Field.IsBig;
+ this.bigMethodDef = module.MethodDef.IsBig;
+ this.bigParam = module.Param.IsBig;
+ this.bigTypeDef = module.TypeDef.IsBig;
+ this.bigProperty = module.Property.IsBig;
+ this.bigEvent = module.Event.IsBig;
+ this.bigGenericParam = module.GenericParam.IsBig;
+ this.bigModuleRef = module.ModuleRef.IsBig;
+ this.bigResolutionScope = IsBig(2, module.ModuleTable, module.ModuleRef, module.AssemblyRef, module.TypeRef);
+ this.bigTypeDefOrRef = IsBig(2, module.TypeDef, module.TypeRef, module.TypeSpec);
+ this.bigMemberRefParent = IsBig(3, module.TypeDef, module.TypeRef, module.ModuleRef, module.MethodDef, module.TypeSpec);
+ this.bigMethodDefOrRef = IsBig(1, module.MethodDef, module.MemberRef);
+ this.bigHasCustomAttribute = IsBig(5, module.MethodDef, module.Field, module.TypeRef, module.TypeDef, module.Param, module.InterfaceImpl, module.MemberRef,
+ module.ModuleTable, /*module.Permission,*/ module.Property, module.Event, module.StandAloneSig, module.ModuleRef, module.TypeSpec, module.AssemblyTable,
+ module.AssemblyRef, module.File, module.ExportedType, module.ManifestResource);
+ this.bigCustomAttributeType = IsBig(3, module.MethodDef, module.MemberRef);
+ this.bigHasConstant = IsBig(2, module.Field, module.Param, module.Property);
+ this.bigHasSemantics = IsBig(1, module.Event, module.Property);
+ this.bigHasFieldMarshal = IsBig(1, module.Field, module.Param);
+ this.bigHasDeclSecurity = IsBig(2, module.TypeDef, module.MethodDef, module.AssemblyTable);
+ this.bigTypeOrMethodDef = IsBig(1, module.TypeDef, module.MethodDef);
+ this.bigMemberForwarded = IsBig(1, module.Field, module.MethodDef);
+ this.bigImplementation = IsBig(2, module.File, module.AssemblyRef, module.ExportedType);
+ }
+
+ private static bool IsBig(int bitsUsed, params Table[] tables)
+ {
+ int limit = 1 << (16 - bitsUsed);
+ foreach (Table table in tables)
+ {
+ if (table.RowCount >= limit)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection.Metadata
+{
+ internal abstract class Table
+ {
+ internal bool IsBig
+ {
+ get { return RowCount > 65535; }
+ }
+
+ internal abstract int RowCount { get; set; }
+
+ internal abstract void Write(MetadataWriter mw);
+ internal abstract void Read(MetadataReader mr);
+
+ internal int GetLength(MetadataWriter md)
+ {
+ return RowCount * GetRowSize(new RowSizeCalc(md));
+ }
+
+ protected abstract int GetRowSize(RowSizeCalc rsc);
+
+ protected sealed class RowSizeCalc
+ {
+ private readonly MetadataWriter mw;
+ private int size;
+
+ internal RowSizeCalc(MetadataWriter mw)
+ {
+ this.mw = mw;
+ }
+
+ internal RowSizeCalc AddFixed(int size)
+ {
+ this.size += size;
+ return this;
+ }
+
+ internal RowSizeCalc WriteStringIndex()
+ {
+ if (mw.bigStrings)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteGuidIndex()
+ {
+ if (mw.bigGuids)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteBlobIndex()
+ {
+ if (mw.bigBlobs)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteTypeDefOrRef()
+ {
+ if (mw.bigTypeDefOrRef)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteField()
+ {
+ if (mw.bigField)
+ {
+ size += 4;
+ }
+ else
+ {
+ size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteMethodDef()
+ {
+ if (mw.bigMethodDef)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteParam()
+ {
+ if (mw.bigParam)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteResolutionScope()
+ {
+ if (mw.bigResolutionScope)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteMemberRefParent()
+ {
+ if (mw.bigMemberRefParent)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteHasCustomAttribute()
+ {
+ if (mw.bigHasCustomAttribute)
+ {
+ size += 4;
+ }
+ else
+ {
+ size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteCustomAttributeType()
+ {
+ if (mw.bigCustomAttributeType)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteHasConstant()
+ {
+ if (mw.bigHasConstant)
+ {
+ size += 4;
+ }
+ else
+ {
+ size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteTypeDef()
+ {
+ if (mw.bigTypeDef)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteMethodDefOrRef()
+ {
+ if (mw.bigMethodDefOrRef)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteEvent()
+ {
+ if (mw.bigEvent)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteProperty()
+ {
+ if (mw.bigProperty)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteHasSemantics()
+ {
+ if (mw.bigHasSemantics)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteImplementation()
+ {
+ if (mw.bigImplementation)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteTypeOrMethodDef()
+ {
+ if (mw.bigTypeOrMethodDef)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteGenericParam()
+ {
+ if (mw.bigGenericParam)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteHasDeclSecurity()
+ {
+ if (mw.bigHasDeclSecurity)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteMemberForwarded()
+ {
+ if (mw.bigMemberForwarded)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteModuleRef()
+ {
+ if (mw.bigModuleRef)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal RowSizeCalc WriteHasFieldMarshal()
+ {
+ if (mw.bigHasFieldMarshal)
+ {
+ this.size += 4;
+ }
+ else
+ {
+ this.size += 2;
+ }
+ return this;
+ }
+
+ internal int Value
+ {
+ get { return size; }
+ }
+ }
+ }
+
+ abstract class Table<T> : Table
+ {
+ internal T[] records = new T[1];
+ protected int rowCount;
+
+ internal sealed override int RowCount
+ {
+ get { return rowCount; }
+ set { rowCount = value; records = new T[value]; }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal int AddRecord(T newRecord)
+ {
+ if (rowCount == records.Length)
+ {
+ T[] newarr = new T[records.Length * 2];
+ Array.Copy(records, newarr, records.Length);
+ records = newarr;
+ }
+ records[rowCount++] = newRecord;
+ return rowCount;
+ }
+
+ internal int AddVirtualRecord()
+ {
+ return ++rowCount;
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+
+ sealed class ModuleTable : Table<ModuleTable.Record>
+ {
+ internal const int Index = 0x00;
+
+ internal struct Record
+ {
+ internal short Generation;
+ internal int Name; // -> StringHeap
+ internal int Mvid; // -> GuidHeap
+ internal int EncId; // -> GuidHeap
+ internal int EncBaseId; // -> GuidHeap
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Generation = mr.ReadInt16();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Mvid = mr.ReadGuidIndex();
+ records[i].EncId = mr.ReadGuidIndex();
+ records[i].EncBaseId = mr.ReadGuidIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Generation);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteGuidIndex(records[i].Mvid);
+ mw.WriteGuidIndex(records[i].EncId);
+ mw.WriteGuidIndex(records[i].EncBaseId);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteStringIndex()
+ .WriteGuidIndex()
+ .WriteGuidIndex()
+ .WriteGuidIndex()
+ .Value;
+ }
+
+ internal void Add(short generation, int name, int mvid, int encid, int encbaseid)
+ {
+ Record record = new Record();
+ record.Generation = generation;
+ record.Name = name;
+ record.Mvid = mvid;
+ record.EncId = encid;
+ record.EncBaseId = encbaseid;
+ AddRecord(record);
+ }
+ }
+
+ sealed class TypeRefTable : Table<TypeRefTable.Record>
+ {
+ internal const int Index = 0x01;
+
+ internal struct Record
+ {
+ internal int ResolutionScope;
+ internal int TypeName;
+ internal int TypeNameSpace;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].ResolutionScope = mr.ReadResolutionScope();
+ records[i].TypeName = mr.ReadStringIndex();
+ records[i].TypeNameSpace = mr.ReadStringIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteResolutionScope(records[i].ResolutionScope);
+ mw.WriteStringIndex(records[i].TypeName);
+ mw.WriteStringIndex(records[i].TypeNameSpace);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteResolutionScope()
+ .WriteStringIndex()
+ .WriteStringIndex()
+ .Value;
+ }
+ }
+
+ sealed class TypeDefTable : Table<TypeDefTable.Record>
+ {
+ internal const int Index = 0x02;
+
+ internal struct Record
+ {
+ internal int Flags;
+ internal int TypeName;
+ internal int TypeNamespace;
+ internal int Extends;
+ internal int FieldList;
+ internal int MethodList;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Flags = mr.ReadInt32();
+ records[i].TypeName = mr.ReadStringIndex();
+ records[i].TypeNamespace = mr.ReadStringIndex();
+ records[i].Extends = mr.ReadTypeDefOrRef();
+ records[i].FieldList = mr.ReadField();
+ records[i].MethodList = mr.ReadMethodDef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ mw.ModuleBuilder.WriteTypeDefTable(mw);
+ }
+
+ internal int AllocToken()
+ {
+ return 0x02000000 + AddVirtualRecord();
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(4)
+ .WriteStringIndex()
+ .WriteStringIndex()
+ .WriteTypeDefOrRef()
+ .WriteField()
+ .WriteMethodDef()
+ .Value;
+ }
+ }
+
+ sealed class FieldTable : Table<FieldTable.Record>
+ {
+ internal const int Index = 0x04;
+
+ internal struct Record
+ {
+ internal short Flags;
+ internal int Name;
+ internal int Signature;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Flags = mr.ReadInt16();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Signature = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ mw.ModuleBuilder.WriteFieldTable(mw);
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteStringIndex()
+ .WriteBlobIndex()
+ .Value;
+ }
+ }
+
+ sealed class MethodDefTable : Table<MethodDefTable.Record>
+ {
+ internal const int Index = 0x06;
+ private int baseRVA;
+
+ internal struct Record
+ {
+ internal int RVA;
+ internal short ImplFlags;
+ internal short Flags;
+ internal int Name;
+ internal int Signature;
+ internal int ParamList;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].RVA = mr.ReadInt32();
+ records[i].ImplFlags = mr.ReadInt16();
+ records[i].Flags = mr.ReadInt16();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Signature = mr.ReadBlobIndex();
+ records[i].ParamList = mr.ReadParam();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ mw.ModuleBuilder.WriteMethodDefTable(baseRVA, mw);
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(8)
+ .WriteStringIndex()
+ .WriteBlobIndex()
+ .WriteParam()
+ .Value;
+ }
+
+ internal void Fixup(TextSection code)
+ {
+ baseRVA = (int)code.MethodBodiesRVA;
+ }
+ }
+
+ sealed class ParamTable : Table<ParamTable.Record>
+ {
+ internal const int Index = 0x08;
+
+ internal struct Record
+ {
+ internal short Flags;
+ internal short Sequence;
+ internal int Name;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Flags = mr.ReadInt16();
+ records[i].Sequence = mr.ReadInt16();
+ records[i].Name = mr.ReadStringIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ mw.ModuleBuilder.WriteParamTable(mw);
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(4)
+ .WriteStringIndex()
+ .Value;
+ }
+ }
+
+ sealed class InterfaceImplTable : Table<InterfaceImplTable.Record>, IComparer<InterfaceImplTable.Record>
+ {
+ internal const int Index = 0x09;
+
+ internal struct Record
+ {
+ internal int Class;
+ internal int Interface;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Class = mr.ReadTypeDef();
+ records[i].Interface = mr.ReadTypeDefOrRef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteTypeDef(records[i].Class);
+ mw.WriteEncodedTypeDefOrRef(records[i].Interface);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteTypeDef()
+ .WriteTypeDefOrRef()
+ .Value;
+ }
+
+ internal void Fixup()
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ int token = records[i].Interface;
+ switch (token >> 24)
+ {
+ case 0:
+ break;
+ case TypeDefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 0;
+ break;
+ case TypeRefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 1;
+ break;
+ case TypeSpecTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 2;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ records[i].Interface = token;
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ if (x.Class == y.Class)
+ {
+ return x.Interface == y.Interface ? 0 : (x.Interface > y.Interface ? 1 : -1);
+ }
+ return x.Class > y.Class ? 1 : -1;
+ }
+ }
+
+ sealed class MemberRefTable : Table<MemberRefTable.Record>
+ {
+ internal const int Index = 0x0A;
+
+ internal struct Record
+ {
+ internal int Class;
+ internal int Name;
+ internal int Signature;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Class = mr.ReadMemberRefParent();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Signature = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteMemberRefParent(records[i].Class);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteBlobIndex(records[i].Signature);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteMemberRefParent()
+ .WriteStringIndex()
+ .WriteBlobIndex()
+ .Value;
+ }
+
+ internal int FindOrAddRecord(Record record)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i].Class == record.Class
+ && records[i].Name == record.Name
+ && records[i].Signature == record.Signature)
+ {
+ return i + 1;
+ }
+ }
+ return AddRecord(record);
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (moduleBuilder.IsPseudoToken(records[i].Class))
+ {
+ records[i].Class = moduleBuilder.ResolvePseudoToken(records[i].Class);
+ }
+ }
+ }
+ }
+
+ sealed class ConstantTable : Table<ConstantTable.Record>, IComparer<ConstantTable.Record>
+ {
+ internal const int Index = 0x0B;
+
+ internal struct Record
+ {
+ internal short Type;
+ internal int Parent;
+ internal int Value;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Type = mr.ReadInt16();
+ records[i].Parent = mr.ReadHasConstant();
+ records[i].Value = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Type);
+ mw.WriteHasConstant(records[i].Parent);
+ mw.WriteBlobIndex(records[i].Value);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteHasConstant()
+ .WriteBlobIndex()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ int token = records[i].Parent;
+ if (moduleBuilder.IsPseudoToken(token))
+ {
+ token = moduleBuilder.ResolvePseudoToken(token);
+ }
+ // do the HasConstant encoding, so that we can sort the table
+ switch (token >> 24)
+ {
+ case FieldTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 2 | 0;
+ break;
+ case ParamTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 2 | 1;
+ break;
+ case PropertyTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 2 | 2;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+ }
+
+ internal object GetRawConstantValue(Module module, int parent)
+ {
+ // TODO use binary search (if sorted)
+ for (int i = 0; i < module.Constant.records.Length; i++)
+ {
+ if (module.Constant.records[i].Parent == parent)
+ {
+ ByteReader br = module.GetBlob(module.Constant.records[i].Value);
+ switch (module.Constant.records[i].Type)
+ {
+ // see ModuleBuilder.AddConstant for the encodings
+ case Signature.ELEMENT_TYPE_BOOLEAN:
+ return br.ReadByte() != 0;
+ case Signature.ELEMENT_TYPE_I1:
+ return br.ReadSByte();
+ case Signature.ELEMENT_TYPE_I2:
+ return br.ReadInt16();
+ case Signature.ELEMENT_TYPE_I4:
+ return br.ReadInt32();
+ case Signature.ELEMENT_TYPE_I8:
+ return br.ReadInt64();
+ case Signature.ELEMENT_TYPE_U1:
+ return br.ReadByte();
+ case Signature.ELEMENT_TYPE_U2:
+ return br.ReadUInt16();
+ case Signature.ELEMENT_TYPE_U4:
+ return br.ReadUInt32();
+ case Signature.ELEMENT_TYPE_U8:
+ return br.ReadUInt64();
+ case Signature.ELEMENT_TYPE_R4:
+ return br.ReadSingle();
+ case Signature.ELEMENT_TYPE_R8:
+ return br.ReadDouble();
+ case Signature.ELEMENT_TYPE_CHAR:
+ return br.ReadChar();
+ case Signature.ELEMENT_TYPE_STRING:
+ {
+ char[] chars = new char[br.Length / 2];
+ for (int j = 0; j < chars.Length; j++)
+ {
+ chars[j] = br.ReadChar();
+ }
+ return new String(chars);
+ }
+ case Signature.ELEMENT_TYPE_CLASS:
+ if (br.ReadInt32() != 0)
+ {
+ throw new BadImageFormatException();
+ }
+ return null;
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+ }
+ throw new InvalidOperationException();
+ }
+ }
+
+ sealed class CustomAttributeTable : Table<CustomAttributeTable.Record>, IComparer<CustomAttributeTable.Record>
+ {
+ internal const int Index = 0x0C;
+
+ internal struct Record
+ {
+ internal int Parent;
+ internal int Type;
+ internal int Value;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Parent = mr.ReadHasCustomAttribute();
+ records[i].Type = mr.ReadCustomAttributeType();
+ records[i].Value = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteHasCustomAttribute(records[i].Parent);
+ mw.WriteCustomAttributeType(records[i].Type);
+ mw.WriteBlobIndex(records[i].Value);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteHasCustomAttribute()
+ .WriteCustomAttributeType()
+ .WriteBlobIndex()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ int[] genericParamFixup = moduleBuilder.GenericParam.GetIndexFixup();
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (moduleBuilder.IsPseudoToken(records[i].Type))
+ {
+ records[i].Type = moduleBuilder.ResolvePseudoToken(records[i].Type);
+ }
+ int token = records[i].Parent;
+ if (moduleBuilder.IsPseudoToken(token))
+ {
+ token = moduleBuilder.ResolvePseudoToken(token);
+ }
+ // do the HasCustomAttribute encoding, so that we can sort the table
+ switch (token >> 24)
+ {
+ case MethodDefTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 0;
+ break;
+ case FieldTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 1;
+ break;
+ case TypeRefTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 2;
+ break;
+ case TypeDefTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 3;
+ break;
+ case ParamTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 4;
+ break;
+ case InterfaceImplTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 5;
+ break;
+ case MemberRefTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 6;
+ break;
+ case ModuleTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 7;
+ break;
+ // Permission (8) table doesn't exist in the spec
+ case PropertyTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 9;
+ break;
+ case EventTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 10;
+ break;
+ case StandAloneSigTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 11;
+ break;
+ case ModuleRefTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 12;
+ break;
+ case TypeSpecTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 13;
+ break;
+ case AssemblyTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 14;
+ break;
+ case AssemblyRefTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 15;
+ break;
+ case FileTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 16;
+ break;
+ case ExportedTypeTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 17;
+ break;
+ case ManifestResourceTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 5 | 18;
+ break;
+ case GenericParamTable.Index:
+ records[i].Parent = (genericParamFixup[(token & 0xFFFFFF) - 1] + 1) << 5 | 19;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+ }
+ }
+
+ sealed class FieldMarshalTable : Table<FieldMarshalTable.Record>, IComparer<FieldMarshalTable.Record>
+ {
+ internal const int Index = 0x0D;
+
+ internal struct Record
+ {
+ internal int Parent;
+ internal int NativeType;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Parent = mr.ReadHasFieldMarshal();
+ records[i].NativeType = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteHasFieldMarshal(records[i].Parent);
+ mw.WriteBlobIndex(records[i].NativeType);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteHasFieldMarshal()
+ .WriteBlobIndex()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ int token = moduleBuilder.ResolvePseudoToken(records[i].Parent);
+ // do the HasFieldMarshal encoding, so that we can sort the table
+ switch (token >> 24)
+ {
+ case FieldTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 1 | 0;
+ break;
+ case ParamTable.Index:
+ records[i].Parent = (token & 0xFFFFFF) << 1 | 1;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+ }
+ }
+
+ sealed class DeclSecurityTable : Table<DeclSecurityTable.Record>, IComparer<DeclSecurityTable.Record>
+ {
+ internal const int Index = 0x0E;
+
+ internal struct Record
+ {
+ internal short Action;
+ internal int Parent;
+ internal int PermissionSet;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Action = mr.ReadInt16();
+ records[i].Parent = mr.ReadHasDeclSecurity();
+ records[i].PermissionSet = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Action);
+ mw.WriteHasDeclSecurity(records[i].Parent);
+ mw.WriteBlobIndex(records[i].PermissionSet);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteHasDeclSecurity()
+ .WriteBlobIndex()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ int token = records[i].Parent;
+ if (moduleBuilder.IsPseudoToken(token))
+ {
+ token = moduleBuilder.ResolvePseudoToken(token);
+ }
+ // do the HasDeclSecurity encoding, so that we can sort the table
+ switch (token >> 24)
+ {
+ case TypeDefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 0;
+ break;
+ case MethodDefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 1;
+ break;
+ case AssemblyTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 2;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ records[i].Parent = token;
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+ }
+ }
+
+ sealed class ClassLayoutTable : Table<ClassLayoutTable.Record>, IComparer<ClassLayoutTable.Record>
+ {
+ internal const int Index = 0x0f;
+
+ internal struct Record
+ {
+ internal short PackingSize;
+ internal int ClassSize;
+ internal int Parent;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].PackingSize = mr.ReadInt16();
+ records[i].ClassSize = mr.ReadInt32();
+ records[i].Parent = mr.ReadTypeDef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ Array.Sort(records, 0, rowCount, this);
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].PackingSize);
+ mw.Write(records[i].ClassSize);
+ mw.WriteTypeDef(records[i].Parent);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(6)
+ .WriteTypeDef()
+ .Value;
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
+ }
+
+ internal void GetLayout(int token, ref int pack, ref int size)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i].Parent == token)
+ {
+ pack = records[i].PackingSize;
+ size = records[i].ClassSize;
+ break;
+ }
+ }
+ }
+ }
+
+ sealed class FieldLayoutTable : Table<FieldLayoutTable.Record>, IComparer<FieldLayoutTable.Record>
+ {
+ internal const int Index = 0x10;
+
+ internal struct Record
+ {
+ internal int Offset;
+ internal int Field;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Offset = mr.ReadInt32();
+ records[i].Field = mr.ReadField();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Offset);
+ mw.WriteField(records[i].Field);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(4)
+ .WriteField()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
+ }
+ }
+
+ sealed class StandAloneSigTable : Table<int>
+ {
+ internal const int Index = 0x11;
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i] = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteBlobIndex(records[i]);
+ }
+ }
+
+ protected override int GetRowSize(Table.RowSizeCalc rsc)
+ {
+ return rsc.WriteBlobIndex().Value;
+ }
+
+ internal int FindOrAddRecord(int blob)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i] == blob)
+ {
+ return i + 1;
+ }
+ }
+ return AddRecord(blob);
+ }
+ }
+
+ sealed class EventMapTable : Table<EventMapTable.Record>
+ {
+ internal const int Index = 0x12;
+
+ internal struct Record
+ {
+ internal int Parent;
+ internal int EventList;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Parent = mr.ReadTypeDef();
+ records[i].EventList = mr.ReadEvent();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteTypeDef(records[i].Parent);
+ mw.WriteEvent(records[i].EventList);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteTypeDef()
+ .WriteEvent()
+ .Value;
+ }
+ }
+
+ sealed class EventTable : Table<EventTable.Record>
+ {
+ internal const int Index = 0x14;
+
+ internal struct Record
+ {
+ internal short EventFlags;
+ internal int Name;
+ internal int EventType;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].EventFlags = mr.ReadInt16();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].EventType = mr.ReadTypeDefOrRef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].EventFlags);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteTypeDefOrRef(records[i].EventType);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteStringIndex()
+ .WriteTypeDefOrRef()
+ .Value;
+ }
+ }
+
+ sealed class PropertyMapTable : Table<PropertyMapTable.Record>
+ {
+ internal const int Index = 0x15;
+
+ internal struct Record
+ {
+ internal int Parent;
+ internal int PropertyList;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Parent = mr.ReadTypeDef();
+ records[i].PropertyList = mr.ReadProperty();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteTypeDef(records[i].Parent);
+ mw.WriteProperty(records[i].PropertyList);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteTypeDef()
+ .WriteProperty()
+ .Value;
+ }
+ }
+
+ sealed class PropertyTable : Table<PropertyTable.Record>
+ {
+ internal const int Index = 0x17;
+
+ internal struct Record
+ {
+ internal short Flags;
+ internal int Name;
+ internal int Type;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Flags = mr.ReadInt16();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Type = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Flags);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteBlobIndex(records[i].Type);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteStringIndex()
+ .WriteBlobIndex()
+ .Value;
+ }
+ }
+
+ sealed class MethodSemanticsTable : Table<MethodSemanticsTable.Record>, IComparer<MethodSemanticsTable.Record>
+ {
+ internal const int Index = 0x18;
+
+ // semantics
+ internal const short Setter = 0x0001;
+ internal const short Getter = 0x0002;
+ internal const short Other = 0x0004;
+ internal const short AddOn = 0x0008;
+ internal const short RemoveOn = 0x0010;
+ internal const short Fire = 0x0020;
+
+ internal struct Record
+ {
+ internal short Semantics;
+ internal int Method;
+ internal int Association;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Semantics = mr.ReadInt16();
+ records[i].Method = mr.ReadMethodDef();
+ records[i].Association = mr.ReadHasSemantics();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Semantics);
+ mw.WriteMethodDef(records[i].Method);
+ mw.WriteHasSemantics(records[i].Association);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteMethodDef()
+ .WriteHasSemantics()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (moduleBuilder.IsPseudoToken(records[i].Method))
+ {
+ records[i].Method = moduleBuilder.ResolvePseudoToken(records[i].Method);
+ }
+ int token = records[i].Association;
+ // do the HasSemantics encoding, so that we can sort the table
+ switch (token >> 24)
+ {
+ case EventTable.Index:
+ token = (token & 0xFFFFFF) << 1 | 0;
+ break;
+ case PropertyTable.Index:
+ token = (token & 0xFFFFFF) << 1 | 1;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ records[i].Association = token;
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Association == y.Association ? 0 : (x.Association > y.Association ? 1 : -1);
+ }
+
+ internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics)
+ {
+ int i = 0;
+ return GetNextMethod(module, token, nonPublic, semantics, ref i);
+ }
+
+ internal MethodInfo[] GetMethods(Module module, int token, bool nonPublic, short semantics)
+ {
+ List<MethodInfo> methods = new List<MethodInfo>();
+ MethodInfo method;
+ for (int i = 0; (method = GetNextMethod(module, token, nonPublic, semantics, ref i)) != null; )
+ {
+ methods.Add(method);
+ }
+ return methods.ToArray();
+ }
+
+ private MethodInfo GetNextMethod(Module module, int token, bool nonPublic, short semantics, ref int i)
+ {
+ // TODO use binary search?
+ for (; i < records.Length; i++)
+ {
+ if (records[i].Association == token)
+ {
+ if ((records[i].Semantics & semantics) != 0)
+ {
+ MethodInfo method = (MethodInfo)module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
+ if (nonPublic || method.IsPublic)
+ {
+ i++;
+ return method;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ internal void ComputeFlags(Module module, int token, out bool isPublic, out bool isStatic)
+ {
+ isPublic = false;
+ isStatic = false;
+ MethodInfo method;
+ for (int i = 0; (method = GetNextMethod(module, token, true, -1, ref i)) != null; )
+ {
+ if (method.IsPublic)
+ {
+ isPublic = true;
+ }
+ if (method.IsStatic)
+ {
+ isStatic = true;
+ }
+ }
+ }
+ }
+
+ sealed class MethodImplTable : Table<MethodImplTable.Record>, IComparer<MethodImplTable.Record>
+ {
+ internal const int Index = 0x19;
+
+ internal struct Record
+ {
+ internal int Class;
+ internal int MethodBody;
+ internal int MethodDeclaration;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Class = mr.ReadTypeDef();
+ records[i].MethodBody = mr.ReadMethodDefOrRef();
+ records[i].MethodDeclaration = mr.ReadMethodDefOrRef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteTypeDef(records[i].Class);
+ mw.WriteMethodDefOrRef(records[i].MethodBody);
+ mw.WriteMethodDefOrRef(records[i].MethodDeclaration);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteTypeDef()
+ .WriteMethodDefOrRef()
+ .WriteMethodDefOrRef()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (moduleBuilder.IsPseudoToken(records[i].MethodBody))
+ {
+ records[i].MethodBody = moduleBuilder.ResolvePseudoToken(records[i].MethodBody);
+ }
+ if (moduleBuilder.IsPseudoToken(records[i].MethodDeclaration))
+ {
+ records[i].MethodDeclaration = moduleBuilder.ResolvePseudoToken(records[i].MethodDeclaration);
+ }
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Class == y.Class ? 0 : (x.Class > y.Class ? 1 : -1);
+ }
+ }
+
+ sealed class ModuleRefTable : Table<int>
+ {
+ internal const int Index = 0x1A;
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i] = mr.ReadStringIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteStringIndex(records[i]);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteStringIndex()
+ .Value;
+ }
+
+ internal int FindOrAddRecord(int str)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i] == str)
+ {
+ return i + 1;
+ }
+ }
+ return AddRecord(str);
+ }
+ }
+
+ sealed class TypeSpecTable : Table<int>
+ {
+ internal const int Index = 0x1B;
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i] = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteBlobIndex(records[i]);
+ }
+ }
+
+ protected override int GetRowSize(Table.RowSizeCalc rsc)
+ {
+ return rsc.WriteBlobIndex().Value;
+ }
+ }
+
+ sealed class ImplMapTable : Table<ImplMapTable.Record>, IComparer<ImplMapTable.Record>
+ {
+ internal const int Index = 0x1C;
+
+ internal struct Record
+ {
+ internal short MappingFlags;
+ internal int MemberForwarded;
+ internal int ImportName;
+ internal int ImportScope;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].MappingFlags = mr.ReadInt16();
+ records[i].MemberForwarded = mr.ReadMemberForwarded();
+ records[i].ImportName = mr.ReadStringIndex();
+ records[i].ImportScope = mr.ReadModuleRef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].MappingFlags);
+ mw.WriteMemberForwarded(records[i].MemberForwarded);
+ mw.WriteStringIndex(records[i].ImportName);
+ mw.WriteModuleRef(records[i].ImportScope);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(2)
+ .WriteMemberForwarded()
+ .WriteStringIndex()
+ .WriteModuleRef()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (moduleBuilder.IsPseudoToken(records[i].MemberForwarded))
+ {
+ records[i].MemberForwarded = moduleBuilder.ResolvePseudoToken(records[i].MemberForwarded);
+ }
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.MemberForwarded == y.MemberForwarded ? 0 : (x.MemberForwarded > y.MemberForwarded ? 1 : -1);
+ }
+ }
+
+ sealed class FieldRVATable : Table<FieldRVATable.Record>, IComparer<FieldRVATable.Record>
+ {
+ internal const int Index = 0x1D;
+
+ internal struct Record
+ {
+ internal int RVA;
+ internal int Field;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].RVA = mr.ReadInt32();
+ records[i].Field = mr.ReadField();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].RVA);
+ mw.WriteField(records[i].Field);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(4)
+ .WriteField()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder, int sdataRVA)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ records[i].RVA += sdataRVA;
+ if (moduleBuilder.IsPseudoToken(records[i].Field))
+ {
+ records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
+ }
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
+ }
+ }
+
+ sealed class AssemblyTable : Table<AssemblyTable.Record>
+ {
+ internal const int Index = 0x20;
+
+ internal struct Record
+ {
+ internal int HashAlgId;
+ internal ushort MajorVersion;
+ internal ushort MinorVersion;
+ internal ushort BuildNumber;
+ internal ushort RevisionNumber;
+ internal int Flags;
+ internal int PublicKey;
+ internal int Name;
+ internal int Culture;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].HashAlgId = mr.ReadInt32();
+ records[i].MajorVersion = mr.ReadUInt16();
+ records[i].MinorVersion = mr.ReadUInt16();
+ records[i].BuildNumber = mr.ReadUInt16();
+ records[i].RevisionNumber = mr.ReadUInt16();
+ records[i].Flags = mr.ReadInt32();
+ records[i].PublicKey = mr.ReadBlobIndex();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Culture = mr.ReadStringIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].HashAlgId);
+ mw.Write(records[i].MajorVersion);
+ mw.Write(records[i].MinorVersion);
+ mw.Write(records[i].BuildNumber);
+ mw.Write(records[i].RevisionNumber);
+ mw.Write(records[i].Flags);
+ mw.WriteBlobIndex(records[i].PublicKey);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteStringIndex(records[i].Culture);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(16)
+ .WriteBlobIndex()
+ .WriteStringIndex()
+ .WriteStringIndex()
+ .Value;
+ }
+ }
+
+ sealed class AssemblyRefTable : Table<AssemblyRefTable.Record>
+ {
+ internal const int Index = 0x23;
+
+ internal struct Record
+ {
+ internal ushort MajorVersion;
+ internal ushort MinorVersion;
+ internal ushort BuildNumber;
+ internal ushort RevisionNumber;
+ internal int Flags;
+ internal int PublicKeyOrToken;
+ internal int Name;
+ internal int Culture;
+ internal int HashValue;
+ }
+
+ internal int FindOrAddRecord(Record rec)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i].Name == rec.Name
+ && records[i].MajorVersion == rec.MajorVersion
+ && records[i].MinorVersion == rec.MinorVersion
+ && records[i].BuildNumber == rec.BuildNumber
+ && records[i].RevisionNumber == rec.RevisionNumber
+ && records[i].Flags == rec.Flags
+ && records[i].PublicKeyOrToken == rec.PublicKeyOrToken
+ && records[i].Culture == rec.Culture
+ && records[i].HashValue == rec.HashValue
+ )
+ {
+ return i + 1;
+ }
+ }
+ return AddRecord(rec);
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].MajorVersion = mr.ReadUInt16();
+ records[i].MinorVersion = mr.ReadUInt16();
+ records[i].BuildNumber = mr.ReadUInt16();
+ records[i].RevisionNumber = mr.ReadUInt16();
+ records[i].Flags = mr.ReadInt32();
+ records[i].PublicKeyOrToken = mr.ReadBlobIndex();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Culture = mr.ReadStringIndex();
+ records[i].HashValue = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].MajorVersion);
+ mw.Write(records[i].MinorVersion);
+ mw.Write(records[i].BuildNumber);
+ mw.Write(records[i].RevisionNumber);
+ mw.Write(records[i].Flags);
+ mw.WriteBlobIndex(records[i].PublicKeyOrToken);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteStringIndex(records[i].Culture);
+ mw.WriteBlobIndex(records[i].HashValue);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(12)
+ .WriteBlobIndex()
+ .WriteStringIndex()
+ .WriteStringIndex()
+ .WriteBlobIndex()
+ .Value;
+ }
+ }
+
+ sealed class FileTable : Table<FileTable.Record>
+ {
+ internal const int Index = 0x26;
+
+ internal struct Record
+ {
+ internal int Flags;
+ internal int Name;
+ internal int HashValue;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Flags = mr.ReadInt32();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].HashValue = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Flags);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteBlobIndex(records[i].HashValue);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(4)
+ .WriteStringIndex()
+ .WriteBlobIndex()
+ .Value;
+ }
+ }
+
+ sealed class ExportedTypeTable : Table<ExportedTypeTable.Record>
+ {
+ internal const int Index = 0x27;
+
+ internal struct Record
+ {
+ internal int Flags;
+ internal int TypeDefId;
+ internal int TypeName;
+ internal int TypeNamespace;
+ internal int Implementation;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Flags = mr.ReadInt32();
+ records[i].TypeDefId = mr.ReadInt32();
+ records[i].TypeName = mr.ReadStringIndex();
+ records[i].TypeNamespace = mr.ReadStringIndex();
+ records[i].Implementation = mr.ReadImplementation();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Flags);
+ mw.Write(records[i].TypeDefId);
+ mw.WriteStringIndex(records[i].TypeName);
+ mw.WriteStringIndex(records[i].TypeNamespace);
+ mw.WriteImplementation(records[i].Implementation);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(8)
+ .WriteStringIndex()
+ .WriteStringIndex()
+ .WriteImplementation()
+ .Value;
+ }
+
+ internal int FindOrAddRecord(Record rec)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i].Implementation == rec.Implementation
+ && records[i].TypeName == rec.TypeName
+ && records[i].TypeNamespace == rec.TypeNamespace)
+ {
+ return i + 1;
+ }
+ }
+ return AddRecord(rec);
+ }
+ }
+
+ sealed class ManifestResourceTable : Table<ManifestResourceTable.Record>
+ {
+ internal const int Index = 0x28;
+
+ internal struct Record
+ {
+ internal int Offset;
+ internal int Flags;
+ internal int Name;
+ internal int Implementation;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Offset = mr.ReadInt32();
+ records[i].Flags = mr.ReadInt32();
+ records[i].Name = mr.ReadStringIndex();
+ records[i].Implementation = mr.ReadImplementation();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Offset);
+ mw.Write(records[i].Flags);
+ mw.WriteStringIndex(records[i].Name);
+ mw.WriteImplementation(records[i].Implementation);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(8)
+ .WriteStringIndex()
+ .WriteImplementation()
+ .Value;
+ }
+ }
+
+ sealed class NestedClassTable : Table<NestedClassTable.Record>
+ {
+ internal const int Index = 0x29;
+
+ internal struct Record
+ {
+ internal int NestedClass;
+ internal int EnclosingClass;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].NestedClass = mr.ReadTypeDef();
+ records[i].EnclosingClass = mr.ReadTypeDef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteTypeDef(records[i].NestedClass);
+ mw.WriteTypeDef(records[i].EnclosingClass);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteTypeDef()
+ .WriteTypeDef()
+ .Value;
+ }
+
+ internal List<int> GetNestedClasses(int enclosingClass)
+ {
+ List<int> nestedClasses = new List<int>();
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i].EnclosingClass == enclosingClass)
+ {
+ nestedClasses.Add(records[i].NestedClass);
+ }
+ }
+ return nestedClasses;
+ }
+ }
+
+ sealed class GenericParamTable : Table<GenericParamTable.Record>, IComparer<GenericParamTable.Record>
+ {
+ internal const int Index = 0x2A;
+
+ internal struct Record
+ {
+ internal short Number;
+ internal short Flags;
+ internal int Owner;
+ internal int Name;
+ // not part of the table, we use it to be able to fixup the GenericParamConstraint table
+ internal int unsortedIndex;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Number = mr.ReadInt16();
+ records[i].Flags = mr.ReadInt16();
+ records[i].Owner = mr.ReadTypeOrMethodDef();
+ records[i].Name = mr.ReadStringIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.Write(records[i].Number);
+ mw.Write(records[i].Flags);
+ mw.WriteTypeOrMethodDef(records[i].Owner);
+ mw.WriteStringIndex(records[i].Name);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .AddFixed(4)
+ .WriteTypeOrMethodDef()
+ .WriteStringIndex()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ int token = records[i].Owner;
+ if (moduleBuilder.IsPseudoToken(token))
+ {
+ token = moduleBuilder.ResolvePseudoToken(token);
+ }
+ // do the TypeOrMethodDef encoding, so that we can sort the table
+ switch (token >> 24)
+ {
+ case TypeDefTable.Index:
+ records[i].Owner = (token & 0xFFFFFF) << 1 | 0;
+ break;
+ case MethodDefTable.Index:
+ records[i].Owner = (token & 0xFFFFFF) << 1 | 1;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ records[i].unsortedIndex = i;
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ if (x.Owner == y.Owner)
+ {
+ return x.Number == y.Number ? 0 : (x.Number > y.Number ? 1 : -1);
+ }
+ return x.Owner > y.Owner ? 1 : -1;
+ }
+
+ internal GenericParameterAttributes GetAttributes(int token)
+ {
+ return (GenericParameterAttributes)records[(token & 0xFFFFFF) - 1].Flags;
+ }
+
+ internal void PatchAttribute(int token, GenericParameterAttributes genericParameterAttributes)
+ {
+ records[(token & 0xFFFFFF) - 1].Flags = (short)genericParameterAttributes;
+ }
+
+ internal int[] GetIndexFixup()
+ {
+ int[] array = new int[rowCount];
+ for (int i = 0; i < rowCount; i++)
+ {
+ array[records[i].unsortedIndex] = i;
+ }
+ return array;
+ }
+
+ internal int FindFirstByOwner(int token)
+ {
+ // TODO use binary search (if sorted)
+ for (int i = 0; i < records.Length; i++)
+ {
+ if (records[i].Owner == token)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+ }
+
+ sealed class MethodSpecTable : Table<MethodSpecTable.Record>
+ {
+ internal const int Index = 0x2B;
+
+ internal struct Record
+ {
+ internal int Method;
+ internal int Instantiation;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Method = mr.ReadMethodDefOrRef();
+ records[i].Instantiation = mr.ReadBlobIndex();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteMethodDefOrRef(records[i].Method);
+ mw.WriteBlobIndex(records[i].Instantiation);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteMethodDefOrRef()
+ .WriteBlobIndex()
+ .Value;
+ }
+
+ internal int FindOrAddRecord(Record record)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (records[i].Method == record.Method
+ && records[i].Instantiation == record.Instantiation)
+ {
+ return i + 1;
+ }
+ }
+ return AddRecord(record);
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ if (moduleBuilder.IsPseudoToken(records[i].Method))
+ {
+ records[i].Method = moduleBuilder.ResolvePseudoToken(records[i].Method);
+ }
+ }
+ }
+ }
+
+ sealed class GenericParamConstraintTable : Table<GenericParamConstraintTable.Record>, IComparer<GenericParamConstraintTable.Record>
+ {
+ internal const int Index = 0x2C;
+
+ internal struct Record
+ {
+ internal int Owner;
+ internal int Constraint;
+ }
+
+ internal override void Read(MetadataReader mr)
+ {
+ for (int i = 0; i < records.Length; i++)
+ {
+ records[i].Owner = mr.ReadGenericParam();
+ records[i].Constraint = mr.ReadTypeDefOrRef();
+ }
+ }
+
+ internal override void Write(MetadataWriter mw)
+ {
+ for (int i = 0; i < rowCount; i++)
+ {
+ mw.WriteGenericParam(records[i].Owner);
+ mw.WriteTypeDefOrRef(records[i].Constraint);
+ }
+ }
+
+ protected override int GetRowSize(RowSizeCalc rsc)
+ {
+ return rsc
+ .WriteGenericParam()
+ .WriteTypeDefOrRef()
+ .Value;
+ }
+
+ internal void Fixup(ModuleBuilder moduleBuilder)
+ {
+ int[] fixups = moduleBuilder.GenericParam.GetIndexFixup();
+ for (int i = 0; i < rowCount; i++)
+ {
+ records[i].Owner = fixups[records[i].Owner - 1] + 1;
+ }
+ Array.Sort(records, 0, rowCount, this);
+ }
+
+ int IComparer<Record>.Compare(Record x, Record y)
+ {
+ return x.Owner == y.Owner ? 0 : (x.Owner > y.Owner ? 1 : -1);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+ public abstract class MethodBase : MemberInfo
+ {
+ internal abstract MethodSignature MethodSignature { get; }
+ internal abstract int ParameterCount { get; }
+ public abstract ParameterInfo[] GetParameters();
+ public abstract MethodAttributes Attributes { get; }
+ public abstract MethodImplAttributes GetMethodImplementationFlags();
+ public abstract MethodBody GetMethodBody();
+ public abstract CallingConventions CallingConvention { get; }
+
+ public bool IsConstructor
+ {
+ get
+ {
+ if ((this.Attributes & MethodAttributes.RTSpecialName) != 0)
+ {
+ string name = this.Name;
+ return name == ConstructorInfo.ConstructorName || name == ConstructorInfo.TypeConstructorName;
+ }
+ return false;
+ }
+ }
+
+ public bool IsStatic
+ {
+ get { return (Attributes & MethodAttributes.Static) != 0; }
+ }
+
+ public bool IsVirtual
+ {
+ get { return (Attributes & MethodAttributes.Virtual) != 0; }
+ }
+
+ public bool IsAbstract
+ {
+ get { return (Attributes & MethodAttributes.Abstract) != 0; }
+ }
+
+ public bool IsFinal
+ {
+ get { return (Attributes & MethodAttributes.Final) != 0; }
+ }
+
+ public bool IsPublic
+ {
+ get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; }
+ }
+
+ public bool IsFamily
+ {
+ get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; }
+ }
+
+ public bool IsFamilyOrAssembly
+ {
+ get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; }
+ }
+
+ public bool IsAssembly
+ {
+ get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly; }
+ }
+
+ public bool IsFamilyAndAssembly
+ {
+ get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; }
+ }
+
+ public bool IsPrivate
+ {
+ get { return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; }
+ }
+
+ public bool IsSpecialName
+ {
+ get { return (Attributes & MethodAttributes.SpecialName) != 0; }
+ }
+
+ public bool IsHideBySig
+ {
+ get { return (Attributes & MethodAttributes.HideBySig) != 0; }
+ }
+
+ public virtual Type[] GetGenericArguments()
+ {
+ return Type.EmptyTypes;
+ }
+
+ public virtual bool IsGenericMethod
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsGenericMethodDefinition
+ {
+ get { return false; }
+ }
+
+ public virtual bool ContainsGenericParameters
+ {
+ get { return IsGenericMethodDefinition; }
+ }
+
+ // This goes to the (uninstantiated) MethodInfo on the (uninstantiated) Type. For constructors
+ // it also has the effect of removing the ConstructorInfo wrapper and returning the underlying MethodInfo.
+ internal abstract MethodInfo GetMethodOnTypeDefinition();
+
+ internal abstract int ImportTo(Emit.ModuleBuilder module);
+
+ internal abstract MethodBase BindTypeParameters(Type type);
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using IKVM.Reflection.Reader;
+using System.IO;
+
+namespace IKVM.Reflection
+{
+ public sealed class MethodBody
+ {
+ private readonly IList<ExceptionHandlingClause> exceptionClauses;
+ private readonly IList<LocalVariableInfo> locals;
+ private readonly bool initLocals;
+ private readonly int maxStack;
+ private readonly int localVarSigTok;
+ private byte[] body;
+
+ internal MethodBody(ModuleReader module, int rva, IGenericContext context)
+ {
+ const byte CorILMethod_TinyFormat = 0x02;
+ const byte CorILMethod_FatFormat = 0x03;
+ const byte CorILMethod_MoreSects = 0x08;
+ const byte CorILMethod_InitLocals = 0x10;
+ const byte CorILMethod_Sect_EHTable = 0x01;
+ const byte CorILMethod_Sect_FatFormat = 0x40;
+ const byte CorILMethod_Sect_MoreSects = 0x80;
+
+ List<ExceptionHandlingClause> exceptionClauses = new List<ExceptionHandlingClause>();
+ List<LocalVariableInfo> locals = new List<LocalVariableInfo>();
+ module.SeekRVA(rva);
+ BinaryReader br = new BinaryReader(module.stream);
+ byte b = br.ReadByte();
+ if ((b & 3) == CorILMethod_TinyFormat)
+ {
+ initLocals = true;
+ body = br.ReadBytes(b >> 2);
+ }
+ else if ((b & 3) == CorILMethod_FatFormat)
+ {
+ initLocals = (b & CorILMethod_InitLocals) != 0;
+ short flagsAndSize = (short)(b | (br.ReadByte() << 8));
+ if ((flagsAndSize >> 12) != 3)
+ {
+ throw new BadImageFormatException("Fat format method header size should be 3");
+ }
+ maxStack = br.ReadUInt16();
+ int codeLength = br.ReadInt32();
+ localVarSigTok = br.ReadInt32();
+ body = br.ReadBytes(codeLength);
+ if ((b & CorILMethod_MoreSects) != 0)
+ {
+ module.stream.Position = (module.stream.Position + 3) & ~3;
+ int hdr = br.ReadInt32();
+ if ((hdr & CorILMethod_Sect_MoreSects) != 0 || (hdr & CorILMethod_Sect_EHTable) == 0)
+ {
+ throw new NotImplementedException();
+ }
+ else if ((hdr & CorILMethod_Sect_FatFormat) != 0)
+ {
+ int count = ComputeExceptionCount((hdr >> 8) & 0xFFFFFF, 24);
+ for (int i = 0; i < count; i++)
+ {
+ int flags = br.ReadInt32();
+ int tryOffset = br.ReadInt32();
+ int tryLength = br.ReadInt32();
+ int handlerOffset = br.ReadInt32();
+ int handlerLength = br.ReadInt32();
+ int classTokenOrFilterOffset = br.ReadInt32();
+ exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
+ }
+ }
+ else
+ {
+ int count = ComputeExceptionCount((hdr >> 8) & 0xFF, 12);
+ for (int i = 0; i < count; i++)
+ {
+ int flags = br.ReadUInt16();
+ int tryOffset = br.ReadUInt16();
+ int tryLength = br.ReadByte();
+ int handlerOffset = br.ReadUInt16();
+ int handlerLength = br.ReadByte();
+ int classTokenOrFilterOffset = br.ReadInt32();
+ exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
+ }
+ }
+ }
+ if (localVarSigTok != 0)
+ {
+ ByteReader sig = module.ResolveSignature(localVarSigTok);
+ Signature.ReadLocalVarSig(module, sig, context, locals);
+ }
+ }
+ else
+ {
+ throw new BadImageFormatException();
+ }
+ this.exceptionClauses = exceptionClauses.AsReadOnly();
+ this.locals = locals.AsReadOnly();
+ }
+
+ private static int ComputeExceptionCount(int size, int itemLength)
+ {
+ // LAMESPEC according to the spec, the count should be calculated as "(size - 4) / itemLength",
+ // FXBUG but to workaround a VB compiler bug that specifies the size incorrectly,
+ // we do a truncating division instead.
+ return size / itemLength;
+ }
+
+ public IList<ExceptionHandlingClause> ExceptionHandlingClauses
+ {
+ get { return exceptionClauses; }
+ }
+
+ public bool InitLocals
+ {
+ get { return initLocals; }
+ }
+
+ public IList<LocalVariableInfo> LocalVariables
+ {
+ get { return locals; }
+ }
+
+ public byte[] GetILAsByteArray()
+ {
+ return body;
+ }
+
+ public int LocalSignatureMetadataToken
+ {
+ get { return localVarSigTok; }
+ }
+
+ public int MaxStackSize
+ {
+ get { return maxStack; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ public struct __MethodImplMap
+ {
+ public Type TargetType;
+ public MethodInfo[] MethodBodies;
+ public MethodInfo[][] MethodDeclarations;
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ public abstract class MethodInfo : MethodBase, IGenericContext, IGenericBinder
+ {
+ public sealed override MemberTypes MemberType
+ {
+ get { return MemberTypes.Method; }
+ }
+
+ public abstract Type ReturnType { get; }
+ public abstract ParameterInfo ReturnParameter { get; }
+
+ public virtual MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ throw new NotSupportedException(this.GetType().FullName);
+ }
+
+ public virtual MethodInfo GetGenericMethodDefinition()
+ {
+ throw new NotSupportedException(this.GetType().FullName);
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(this.ReturnType.Name).Append(' ').Append(this.Name);
+ string sep;
+ if (this.IsGenericMethod)
+ {
+ sb.Append('[');
+ sep = "";
+ foreach (Type arg in GetGenericArguments())
+ {
+ sb.Append(sep).Append(arg);
+ sep = ", ";
+ }
+ sb.Append(']');
+ }
+ sb.Append('(');
+ sep = "";
+ foreach (ParameterInfo arg in GetParameters())
+ {
+ sb.Append(sep).Append(arg.ParameterType);
+ sep = ", ";
+ }
+ sb.Append(')');
+ return sb.ToString();
+ }
+
+ internal bool IsNewSlot
+ {
+ get { return (this.Attributes & MethodAttributes.NewSlot) != 0; }
+ }
+
+ public MethodInfo GetBaseDefinition()
+ {
+ MethodInfo match = this;
+ if (match.IsVirtual)
+ {
+ for (Type type = this.DeclaringType.BaseType; type != null && !match.IsNewSlot; type = type.BaseType)
+ {
+ MethodInfo method = type.FindMethod(this.Name, this.MethodSignature) as MethodInfo;
+ if (method != null && method.IsVirtual)
+ {
+ match = method;
+ }
+ }
+ }
+ return match;
+ }
+
+ Type IGenericContext.GetGenericTypeArgument(int index)
+ {
+ return this.DeclaringType.GetGenericTypeArgument(index);
+ }
+
+ Type IGenericContext.GetGenericMethodArgument(int index)
+ {
+ return GetGenericMethodArgument(index);
+ }
+
+ internal virtual Type GetGenericMethodArgument(int index)
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal virtual int GetGenericMethodArgumentCount()
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal override MethodInfo GetMethodOnTypeDefinition()
+ {
+ return this;
+ }
+
+ Type IGenericBinder.BindTypeParameter(Type type)
+ {
+ return this.DeclaringType.GetGenericTypeArgument(type.GenericParameterPosition);
+ }
+
+ Type IGenericBinder.BindMethodParameter(Type type)
+ {
+ return GetGenericMethodArgument(type.GenericParameterPosition);
+ }
+
+ internal override MethodBase BindTypeParameters(Type type)
+ {
+ return new GenericMethodInstance(this.DeclaringType.BindTypeParameters(type), this, null);
+ }
+
+ // This method is used by ILGenerator and exists to allow ArrayMethod to override it,
+ // because ArrayMethod doesn't have a working MethodAttributes property, so it needs
+ // to base the result of this on the CallingConvention.
+ internal virtual bool HasThis
+ {
+ get { return !IsStatic; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection
+{
+ sealed class MethodSignature : Signature
+ {
+ private readonly Type returnType;
+ private readonly Type[] parameterTypes;
+ private readonly Type[][][] modifiers; // see PackedCustomModifiers
+ private readonly CallingConventions callingConvention;
+ private readonly int genericParamCount;
+
+ private MethodSignature(Type returnType, Type[] parameterTypes, Type[][][] modifiers, CallingConventions callingConvention, int genericParamCount)
+ {
+ this.returnType = returnType;
+ this.parameterTypes = parameterTypes;
+ this.modifiers = modifiers;
+ this.callingConvention = callingConvention;
+ this.genericParamCount = genericParamCount;
+ }
+
+ public override bool Equals(object obj)
+ {
+ MethodSignature other = obj as MethodSignature;
+ return other != null
+ && other.callingConvention == callingConvention
+ && other.genericParamCount == genericParamCount
+ && other.returnType.Equals(returnType)
+ && Util.ArrayEquals(other.parameterTypes, parameterTypes)
+ && Util.ArrayEquals(other.modifiers, modifiers);
+ }
+
+ public override int GetHashCode()
+ {
+ return genericParamCount ^ 77 * (int)callingConvention
+ ^ 3 * returnType.GetHashCode()
+ ^ Util.GetHashCode(parameterTypes) * 5
+ ^ Util.GetHashCode(modifiers) * 55;
+ }
+
+ private sealed class UnboundGenericMethodContext : IGenericContext
+ {
+ private readonly IGenericContext original;
+
+ internal UnboundGenericMethodContext(IGenericContext original)
+ {
+ this.original = original;
+ }
+
+ public Type GetGenericTypeArgument(int index)
+ {
+ return original.GetGenericTypeArgument(index);
+ }
+
+ public Type GetGenericMethodArgument(int index)
+ {
+ return UnboundGenericMethodParameter.Make(index);
+ }
+ }
+
+ internal static MethodSignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ CallingConventions callingConvention;
+ int genericParamCount;
+ Type returnType;
+ Type[] parameterTypes;
+ byte flags = br.ReadByte();
+ switch (flags & 7)
+ {
+ case DEFAULT:
+ callingConvention = CallingConventions.Standard;
+ break;
+ case VARARG:
+ callingConvention = CallingConventions.VarArgs;
+ break;
+ default:
+ throw new BadImageFormatException();
+ }
+ if ((flags & HASTHIS) != 0)
+ {
+ callingConvention |= CallingConventions.HasThis;
+ }
+ if ((flags & EXPLICITTHIS) != 0)
+ {
+ callingConvention |= CallingConventions.ExplicitThis;
+ }
+ genericParamCount = 0;
+ if ((flags & GENERIC) != 0)
+ {
+ genericParamCount = br.ReadCompressedInt();
+ context = new UnboundGenericMethodContext(context);
+ }
+ int paramCount = br.ReadCompressedInt();
+ Type[][][] modifiers = null;
+ Type[] optionalCustomModifiers;
+ Type[] requiredCustomModifiers;
+ ReadCustomModifiers(module, br, context, out requiredCustomModifiers, out optionalCustomModifiers);
+ returnType = ReadRetType(module, br, context);
+ parameterTypes = new Type[paramCount];
+ PackedCustomModifiers.SetModifiers(ref modifiers, 0, 0, optionalCustomModifiers, paramCount + 1);
+ PackedCustomModifiers.SetModifiers(ref modifiers, 0, 1, requiredCustomModifiers, paramCount + 1);
+ for (int i = 0; i < parameterTypes.Length; i++)
+ {
+ if ((callingConvention & CallingConventions.VarArgs) != 0 && br.PeekByte() == SENTINEL)
+ {
+ Array.Resize(ref parameterTypes, i);
+ if (modifiers != null)
+ {
+ Array.Resize(ref modifiers, i + 1);
+ }
+ break;
+ }
+ ReadCustomModifiers(module, br, context, out requiredCustomModifiers, out optionalCustomModifiers);
+ PackedCustomModifiers.SetModifiers(ref modifiers, i + 1, 0, optionalCustomModifiers, paramCount + 1);
+ PackedCustomModifiers.SetModifiers(ref modifiers, i + 1, 1, requiredCustomModifiers, paramCount + 1);
+ parameterTypes[i] = ReadParam(module, br, context);
+ }
+ return new MethodSignature(returnType, parameterTypes, modifiers, callingConvention, genericParamCount);
+ }
+
+ internal static __StandAloneMethodSig ReadStandAloneMethodSig(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ CallingConventions callingConvention = 0;
+ System.Runtime.InteropServices.CallingConvention unmanagedCallingConvention = 0;
+ bool unmanaged;
+ byte flags = br.ReadByte();
+ switch (flags & 7)
+ {
+ case DEFAULT:
+ callingConvention = CallingConventions.Standard;
+ unmanaged = false;
+ break;
+ case 0x01: // C
+ unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
+ unmanaged = true;
+ break;
+ case 0x02: // STDCALL
+ unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
+ unmanaged = true;
+ break;
+ case 0x03: // THISCALL
+ unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
+ unmanaged = true;
+ break;
+ case 0x04: // FASTCALL
+ unmanagedCallingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
+ unmanaged = true;
+ break;
+ case VARARG:
+ callingConvention = CallingConventions.VarArgs;
+ unmanaged = false;
+ break;
+ default:
+ throw new BadImageFormatException();
+ }
+ if ((flags & HASTHIS) != 0)
+ {
+ callingConvention |= CallingConventions.HasThis;
+ }
+ if ((flags & EXPLICITTHIS) != 0)
+ {
+ callingConvention |= CallingConventions.ExplicitThis;
+ }
+ if ((flags & GENERIC) != 0)
+ {
+ throw new BadImageFormatException();
+ }
+ int paramCount = br.ReadCompressedInt();
+ SkipCustomModifiers(br);
+ Type returnType = ReadRetType(module, br, context);
+ List<Type> parameterTypes = new List<Type>();
+ List<Type> optionalParameterTypes = new List<Type>();
+ List<Type> curr = parameterTypes;
+ for (int i = 0; i < paramCount; i++)
+ {
+ if (br.PeekByte() == SENTINEL)
+ {
+ br.ReadByte();
+ curr = optionalParameterTypes;
+ }
+ SkipCustomModifiers(br);
+ curr.Add(ReadParam(module, br, context));
+ }
+ return new __StandAloneMethodSig(unmanaged, unmanagedCallingConvention, callingConvention, returnType, parameterTypes.ToArray(), optionalParameterTypes.ToArray());
+ }
+
+ internal int GetParameterCount()
+ {
+ return parameterTypes.Length;
+ }
+
+ internal Type GetParameterType(int index)
+ {
+ return parameterTypes[index];
+ }
+
+ internal Type GetReturnType(IGenericBinder binder)
+ {
+ return returnType.BindTypeParameters(binder);
+ }
+
+ internal Type[] GetReturnTypeOptionalCustomModifiers(IGenericBinder binder)
+ {
+ return BindTypeParameters(binder, modifiers, 0, 0);
+ }
+
+ internal Type[] GetReturnTypeRequiredCustomModifiers(IGenericBinder binder)
+ {
+ return BindTypeParameters(binder, modifiers, 0, 1);
+ }
+
+ internal Type GetParameterType(IGenericBinder binder, int index)
+ {
+ return parameterTypes[index].BindTypeParameters(binder);
+ }
+
+ internal Type[] GetParameterOptionalCustomModifiers(IGenericBinder binder, int index)
+ {
+ return BindTypeParameters(binder, modifiers, index + 1, 0);
+ }
+
+ internal Type[] GetParameterRequiredCustomModifiers(IGenericBinder binder, int index)
+ {
+ return BindTypeParameters(binder, modifiers, index + 1, 1);
+ }
+
+ internal CallingConventions CallingConvention
+ {
+ get { return callingConvention; }
+ }
+
+ private sealed class Binder : IGenericBinder
+ {
+ private readonly Type declaringType;
+ private readonly Type[] methodArgs;
+
+ internal Binder(Type declaringType, Type[] methodArgs)
+ {
+ this.declaringType = declaringType;
+ this.methodArgs = methodArgs;
+ }
+
+ public Type BindTypeParameter(Type type)
+ {
+ return declaringType.GetGenericTypeArgument(type.GenericParameterPosition);
+ }
+
+ public Type BindMethodParameter(Type type)
+ {
+ if (methodArgs == null)
+ {
+ return type;
+ }
+ return methodArgs[type.GenericParameterPosition];
+ }
+ }
+
+ internal MethodSignature Bind(Type type, Type[] methodArgs)
+ {
+ Binder binder = new Binder(type, methodArgs);
+ return new MethodSignature(returnType.BindTypeParameters(binder),
+ BindTypeParameters(binder, parameterTypes),
+ BindTypeParameters(binder, modifiers),
+ callingConvention, genericParamCount);
+ }
+
+ private sealed class Unbinder : IGenericBinder
+ {
+ internal static readonly Unbinder Instance = new Unbinder();
+
+ private Unbinder()
+ {
+ }
+
+ public Type BindTypeParameter(Type type)
+ {
+ return type;
+ }
+
+ public Type BindMethodParameter(Type type)
+ {
+ return UnboundGenericMethodParameter.Make(type.GenericParameterPosition);
+ }
+ }
+
+ internal static MethodSignature MakeFromBuilder(Type returnType, Type[] parameterTypes, Type[][][] modifiers, CallingConventions callingConvention, int genericParamCount)
+ {
+ if (genericParamCount > 0)
+ {
+ returnType = returnType.BindTypeParameters(Unbinder.Instance);
+ parameterTypes = BindTypeParameters(Unbinder.Instance, parameterTypes);
+ modifiers = BindTypeParameters(Unbinder.Instance, modifiers);
+ }
+ return new MethodSignature(returnType, parameterTypes, modifiers, callingConvention, genericParamCount);
+ }
+
+ internal bool MatchParameterTypes(Type[] types)
+ {
+ if (types == parameterTypes)
+ {
+ return true;
+ }
+ if (types == null)
+ {
+ return parameterTypes.Length == 0;
+ }
+ if (parameterTypes == null)
+ {
+ return types.Length == 0;
+ }
+ if (types.Length == parameterTypes.Length)
+ {
+ for (int i = 0; i < types.Length; i++)
+ {
+ if (!Util.TypeEquals(types[i], parameterTypes[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
+ {
+ WriteSigImpl(module, bb, parameterTypes.Length);
+ }
+
+ internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes)
+ {
+ WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length);
+ if (optionalParameterTypes.Length > 0)
+ {
+ bb.Write(SENTINEL);
+ foreach (Type type in optionalParameterTypes)
+ {
+ WriteType(module, bb, type);
+ }
+ }
+ }
+
+ private void WriteSigImpl(ModuleBuilder module, ByteBuffer bb, int parameterCount)
+ {
+ byte first;
+ if ((callingConvention & CallingConventions.Any) == CallingConventions.VarArgs)
+ {
+ Debug.Assert(genericParamCount == 0);
+ first = VARARG;
+ }
+ else if (genericParamCount > 0)
+ {
+ first = GENERIC;
+ }
+ else
+ {
+ first = DEFAULT;
+ }
+ if ((callingConvention & CallingConventions.HasThis) != 0)
+ {
+ first |= HASTHIS;
+ }
+ if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+ {
+ first |= EXPLICITTHIS;
+ }
+ bb.Write(first);
+ if (genericParamCount > 0)
+ {
+ bb.WriteCompressedInt(genericParamCount);
+ }
+ bb.WriteCompressedInt(parameterCount);
+ // RetType
+ if (modifiers != null && modifiers[0] != null)
+ {
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[0][0]);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[0][1]);
+ }
+ WriteType(module, bb, returnType);
+ // Param
+ for (int i = 0; i < parameterTypes.Length; i++)
+ {
+ if (modifiers != null && modifiers[i + 1] != null)
+ {
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[i + 1][0]);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[i + 1][1]);
+ }
+ WriteType(module, bb, parameterTypes[i]);
+ }
+ }
+ }
+
+ static class PackedCustomModifiers
+ {
+ // modifiers are packed in a very specific way (and required to be so, otherwise equality checks will fail)
+ // For modifiers[x][y][z]:
+ // x = parameter index, 0 = return type, 1 = first parameters, ...
+ // y = 0 = optional custom modifiers, 1 = required custom modifiers
+ // z = the custom modifiers
+ // At any level the reference can be null (and *must* be null, if there are no modifiers below that level).
+ // Empty arrays are not allowed at any level.
+
+ // this can be used to "add" elements to the modifiers array (and the elements are assumed to already be in normalized form)
+ internal static void SetModifiers(ref Type[][][] modifiers, int index, int optOrReq, Type[] add, int count)
+ {
+ if (add != null)
+ {
+ if (modifiers == null)
+ {
+ modifiers = new Type[count][][];
+ }
+ if (modifiers[index] == null)
+ {
+ modifiers[index] = new Type[2][];
+ }
+ modifiers[index][optOrReq] = add;
+ }
+ }
+
+ // this method make a copy of the incoming arrays (where necessary) and returns a normalized modifiers array
+ internal static Type[][][] CreateFromExternal(Type[] returnOptional, Type[] returnRequired, Type[][] parameterOptional, Type[][] parameterRequired, int parameterCount)
+ {
+ Type[][][] modifiers = null;
+ SetModifiers(ref modifiers, 0, 0, NormalizeAndCopy(returnOptional), parameterCount + 1);
+ SetModifiers(ref modifiers, 0, 1, NormalizeAndCopy(returnRequired), parameterCount + 1);
+ for (int i = 0; i < parameterCount; i++)
+ {
+ SetModifiers(ref modifiers, i + 1, 0, NormalizeAndCopy(parameterOptional, i), parameterCount + 1);
+ SetModifiers(ref modifiers, i + 1, 1, NormalizeAndCopy(parameterRequired, i), parameterCount + 1);
+ }
+ return modifiers;
+ }
+
+ private static Type[] NormalizeAndCopy(Type[] array)
+ {
+ if (array == null || array.Length == 0)
+ {
+ return null;
+ }
+ Type[] copy = null;
+ for (int i = 0; i < array.Length; i++)
+ {
+ if (array[i] != null)
+ {
+ if (copy == null)
+ {
+ copy = new Type[array.Length];
+ }
+ copy[i] = array[i];
+ }
+ }
+ return copy;
+ }
+
+ private static Type[] NormalizeAndCopy(Type[][] array, int index)
+ {
+ if (array == null || array.Length == 0)
+ {
+ return null;
+ }
+ return NormalizeAndCopy(array[index]);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using IKVM.Reflection.Metadata;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+ public sealed class RawModule : IDisposable
+ {
+ private readonly ModuleReader module;
+ private readonly bool isManifestModule;
+ private bool imported;
+
+ internal RawModule(ModuleReader module)
+ {
+ this.module = module;
+ this.isManifestModule = module.Assembly != null;
+ }
+
+ public string Location
+ {
+ get { return module.FullyQualifiedName; }
+ }
+
+ public bool IsManifestModule
+ {
+ get { return isManifestModule; }
+ }
+
+ private void CheckManifestModule()
+ {
+ if (!IsManifestModule)
+ {
+ throw new BadImageFormatException("Module does not contain a manifest");
+ }
+ }
+
+ public AssemblyName GetAssemblyName()
+ {
+ CheckManifestModule();
+ return module.Assembly.GetName();
+ }
+
+ public AssemblyName[] GetReferencedAssemblies()
+ {
+ return module.__GetReferencedAssemblies();
+ }
+
+ public void Dispose()
+ {
+ if (!imported)
+ {
+ module.stream.Dispose();
+ }
+ }
+
+ internal Assembly ToAssembly()
+ {
+ if (imported)
+ {
+ throw new InvalidOperationException();
+ }
+ imported = true;
+ return module.Assembly;
+ }
+
+ internal Module ToModule(Assembly assembly)
+ {
+ if (module.Assembly != null)
+ {
+ throw new InvalidOperationException();
+ }
+ imported = true;
+ module.SetAssembly(assembly);
+ return module;
+ }
+ }
+
+ public abstract class Module : ICustomAttributeProvider
+ {
+ internal readonly Universe universe;
+ internal readonly ModuleTable ModuleTable = new ModuleTable();
+ internal readonly TypeRefTable TypeRef = new TypeRefTable();
+ internal readonly TypeDefTable TypeDef = new TypeDefTable();
+ internal readonly FieldTable Field = new FieldTable();
+ internal readonly MemberRefTable MemberRef = new MemberRefTable();
+ internal readonly ConstantTable Constant = new ConstantTable();
+ internal readonly CustomAttributeTable CustomAttribute = new CustomAttributeTable();
+ internal readonly FieldMarshalTable FieldMarshal = new FieldMarshalTable();
+ internal readonly DeclSecurityTable DeclSecurity = new DeclSecurityTable();
+ internal readonly ClassLayoutTable ClassLayout = new ClassLayoutTable();
+ internal readonly FieldLayoutTable FieldLayout = new FieldLayoutTable();
+ internal readonly ParamTable Param = new ParamTable();
+ internal readonly InterfaceImplTable InterfaceImpl = new InterfaceImplTable();
+ internal readonly StandAloneSigTable StandAloneSig = new StandAloneSigTable();
+ internal readonly EventMapTable EventMap = new EventMapTable();
+ internal readonly EventTable Event = new EventTable();
+ internal readonly PropertyMapTable PropertyMap = new PropertyMapTable();
+ internal readonly PropertyTable Property = new PropertyTable();
+ internal readonly MethodSemanticsTable MethodSemantics = new MethodSemanticsTable();
+ internal readonly MethodImplTable MethodImpl = new MethodImplTable();
+ internal readonly ModuleRefTable ModuleRef = new ModuleRefTable();
+ internal readonly TypeSpecTable TypeSpec = new TypeSpecTable();
+ internal readonly ImplMapTable ImplMap = new ImplMapTable();
+ internal readonly FieldRVATable FieldRVA = new FieldRVATable();
+ internal readonly AssemblyTable AssemblyTable = new AssemblyTable();
+ internal readonly AssemblyRefTable AssemblyRef = new AssemblyRefTable();
+ internal readonly MethodDefTable MethodDef = new MethodDefTable();
+ internal readonly NestedClassTable NestedClass = new NestedClassTable();
+ internal readonly FileTable File = new FileTable();
+ internal readonly ExportedTypeTable ExportedType = new ExportedTypeTable();
+ internal readonly ManifestResourceTable ManifestResource = new ManifestResourceTable();
+ internal readonly GenericParamTable GenericParam = new GenericParamTable();
+ internal readonly MethodSpecTable MethodSpec = new MethodSpecTable();
+ internal readonly GenericParamConstraintTable GenericParamConstraint = new GenericParamConstraintTable();
+
+ internal Module(Universe universe)
+ {
+ this.universe = universe;
+ }
+
+ internal Table[] GetTables()
+ {
+ Table[] tables = new Table[64];
+ tables[ModuleTable.Index] = ModuleTable;
+ tables[TypeRefTable.Index] = TypeRef;
+ tables[TypeDefTable.Index] = TypeDef;
+ tables[FieldTable.Index] = Field;
+ tables[MemberRefTable.Index] = MemberRef;
+ tables[ConstantTable.Index] = Constant;
+ tables[CustomAttributeTable.Index] = CustomAttribute;
+ tables[FieldMarshalTable.Index] = FieldMarshal;
+ tables[DeclSecurityTable.Index] = DeclSecurity;
+ tables[ClassLayoutTable.Index] = ClassLayout;
+ tables[FieldLayoutTable.Index] = FieldLayout;
+ tables[ParamTable.Index] = Param;
+ tables[InterfaceImplTable.Index] = InterfaceImpl;
+ tables[StandAloneSigTable.Index] = StandAloneSig;
+ tables[EventMapTable.Index] = EventMap;
+ tables[EventTable.Index] = Event;
+ tables[PropertyMapTable.Index] = PropertyMap;
+ tables[PropertyTable.Index] = Property;
+ tables[MethodSemanticsTable.Index] = MethodSemantics;
+ tables[MethodImplTable.Index] = MethodImpl;
+ tables[ModuleRefTable.Index] = ModuleRef;
+ tables[TypeSpecTable.Index] = TypeSpec;
+ tables[ImplMapTable.Index] = ImplMap;
+ tables[FieldRVATable.Index] = FieldRVA;
+ tables[AssemblyTable.Index] = AssemblyTable;
+ tables[AssemblyRefTable.Index] = AssemblyRef;
+ tables[MethodDefTable.Index] = MethodDef;
+ tables[NestedClassTable.Index] = NestedClass;
+ tables[FileTable.Index] = File;
+ tables[ExportedTypeTable.Index] = ExportedType;
+ tables[ManifestResourceTable.Index] = ManifestResource;
+ tables[GenericParamTable.Index] = GenericParam;
+ tables[MethodSpecTable.Index] = MethodSpec;
+ tables[GenericParamConstraintTable.Index] = GenericParamConstraint;
+ return tables;
+ }
+
+ public virtual void __GetDataDirectoryEntry(int index, out int rva, out int length)
+ {
+ throw new NotSupportedException();
+ }
+
+ public virtual long __RelativeVirtualAddressToFileOffset(int rva)
+ {
+ throw new NotSupportedException();
+ }
+
+ public virtual void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
+ {
+ throw new NotSupportedException();
+ }
+
+ public virtual int __Subsystem
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public FieldInfo GetField(string name)
+ {
+ return IsResource() ? null : GetModuleType().GetField(name);
+ }
+
+ public FieldInfo GetField(string name, BindingFlags bindingFlags)
+ {
+ return IsResource() ? null : GetModuleType().GetField(name, bindingFlags);
+ }
+
+ public FieldInfo[] GetFields()
+ {
+ return IsResource() ? Empty<FieldInfo>.Array : GetModuleType().GetFields();
+ }
+
+ public FieldInfo[] GetFields(BindingFlags bindingFlags)
+ {
+ return IsResource() ? Empty<FieldInfo>.Array : GetModuleType().GetFields(bindingFlags);
+ }
+
+ public MethodInfo GetMethod(string name)
+ {
+ return IsResource() ? null : GetModuleType().GetMethod(name);
+ }
+
+ public MethodInfo GetMethod(string name, Type[] types)
+ {
+ return IsResource() ? null : GetModuleType().GetMethod(name, types);
+ }
+
+ public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv, Type[] types, ParameterModifier[] modifiers)
+ {
+ return IsResource() ? null : GetModuleType().GetMethod(name, bindingAttr, binder, callConv, types, modifiers);
+ }
+
+ public MethodInfo[] GetMethods()
+ {
+ return IsResource() ? Empty<MethodInfo>.Array : GetModuleType().GetMethods();
+ }
+
+ public MethodInfo[] GetMethods(BindingFlags bindingFlags)
+ {
+ return IsResource() ? Empty<MethodInfo>.Array : GetModuleType().GetMethods(bindingFlags);
+ }
+
+ public ConstructorInfo __ModuleInitializer
+ {
+ get { return IsResource() ? null : GetModuleType().TypeInitializer; }
+ }
+
+ public byte[] ResolveSignature(int metadataToken)
+ {
+ ModuleReader rdr = this as ModuleReader;
+ if (rdr != null)
+ {
+ ByteReader br = rdr.ResolveSignature(metadataToken);
+ return br.ReadBytes(br.Length);
+ }
+ throw new NotSupportedException();
+ }
+
+ public virtual __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new NotSupportedException();
+ }
+
+ public int MetadataToken
+ {
+ get { return IsResource() ? 0 : 1; }
+ }
+
+ public abstract int MDStreamVersion { get ;}
+ public abstract Assembly Assembly { get; }
+ public abstract string FullyQualifiedName { get; }
+ public abstract string Name { get; }
+ public abstract Guid ModuleVersionId { get; }
+ public abstract Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+ public abstract MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+ public abstract FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+ public abstract MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
+
+ public abstract string ResolveString(int metadataToken);
+ public abstract Type[] __ResolveOptionalParameterTypes(int metadataToken);
+ public abstract string ScopeName { get; }
+
+ internal abstract Type GetTypeImpl(string typeName);
+ internal abstract void GetTypesImpl(List<Type> list);
+
+ public Type GetType(string className)
+ {
+ return GetType(className, false, false);
+ }
+
+ public Type GetType(string className, bool ignoreCase)
+ {
+ return GetType(className, false, ignoreCase);
+ }
+
+ public Type GetType(string className, bool throwOnError, bool ignoreCase)
+ {
+ if (ignoreCase)
+ {
+ throw new NotImplementedException();
+ }
+ TypeNameParser parser = TypeNameParser.Parse(className, throwOnError);
+ if (parser.Error)
+ {
+ return null;
+ }
+ if (parser.AssemblyName != null)
+ {
+ if (throwOnError)
+ {
+ throw new ArgumentException("Type names passed to Module.GetType() must not specify an assembly.");
+ }
+ else
+ {
+ return null;
+ }
+ }
+ return parser.Expand(GetTypeImpl(parser.FirstNamePart), this.Assembly, throwOnError, className);
+ }
+
+ public Type[] GetTypes()
+ {
+ List<Type> list = new List<Type>();
+ GetTypesImpl(list);
+ return list.ToArray();
+ }
+
+ public Type[] FindTypes(TypeFilter filter, object filterCriteria)
+ {
+ List<Type> list = new List<Type>();
+ foreach (Type type in GetTypes())
+ {
+ if (filter(type, filterCriteria))
+ {
+ list.Add(type);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public virtual bool IsResource()
+ {
+ return false;
+ }
+
+ public Type ResolveType(int metadataToken)
+ {
+ return ResolveType(metadataToken, null, null);
+ }
+
+ public MethodBase ResolveMethod(int metadataToken)
+ {
+ return ResolveMethod(metadataToken, null, null);
+ }
+
+ public FieldInfo ResolveField(int metadataToken)
+ {
+ return ResolveField(metadataToken, null, null);
+ }
+
+ public MemberInfo ResolveMember(int metadataToken)
+ {
+ return ResolveMember(metadataToken, null, null);
+ }
+
+ public bool IsDefined(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+ }
+
+ public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+ }
+
+ public virtual IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
+ {
+ return Empty<CustomAttributeData>.Array;
+ }
+
+ public abstract AssemblyName[] __GetReferencedAssemblies();
+
+ internal Type CanonicalizeType(Type type)
+ {
+ Type canon;
+ if (!universe.canonicalizedTypes.TryGetValue(type, out canon))
+ {
+ canon = type;
+ universe.canonicalizedTypes.Add(canon, canon);
+ }
+ return canon;
+ }
+
+ internal abstract Type GetModuleType();
+
+ internal abstract ByteReader GetBlob(int blobIndex);
+
+ internal IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return GetCustomAttributes(0x00000001, attributeType);
+ }
+
+ internal List<CustomAttributeData> GetCustomAttributes(int metadataToken, Type attributeType)
+ {
+ List<CustomAttributeData> list = new List<CustomAttributeData>();
+ // TODO use binary search?
+ for (int i = 0; i < CustomAttribute.records.Length; i++)
+ {
+ if (CustomAttribute.records[i].Parent == metadataToken)
+ {
+ if (attributeType == null)
+ {
+ list.Add(new CustomAttributeData(this, i));
+ }
+ else
+ {
+ ConstructorInfo constructor = (ConstructorInfo)ResolveMethod(CustomAttribute.records[i].Type);
+ if (attributeType.IsAssignableFrom(constructor.DeclaringType))
+ {
+ list.Add(new CustomAttributeData(this.Assembly, constructor, GetBlob(CustomAttribute.records[i].Value)));
+ }
+ }
+ }
+ }
+ return list;
+ }
+
+ internal IList<CustomAttributeData> GetDeclarativeSecurity(int metadataToken)
+ {
+ List<CustomAttributeData> list = new List<CustomAttributeData>();
+ // TODO use binary search?
+ for (int i = 0; i < DeclSecurity.records.Length; i++)
+ {
+ if (DeclSecurity.records[i].Parent == metadataToken)
+ {
+ int action = DeclSecurity.records[i].Action;
+ int permissionSet = DeclSecurity.records[i].PermissionSet;
+ CustomAttributeData.ReadDeclarativeSecurity(this.Assembly, list, action, GetBlob(permissionSet));
+ }
+ }
+ return list;
+ }
+
+ internal virtual void Dispose()
+ {
+ }
+
+ internal virtual void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
+ {
+ }
+ }
+
+ public delegate bool TypeFilter(Type m, object filterCriteria);
+ public delegate bool MemberFilter(MemberInfo m, object filterCriteria);
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System.Collections.Generic;
+
+namespace IKVM.Reflection
+{
+ public abstract class ParameterInfo : ICustomAttributeProvider
+ {
+ public sealed override bool Equals(object obj)
+ {
+ ParameterInfo other = obj as ParameterInfo;
+ return other != null && other.Member == this.Member && other.Position == this.Position;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return this.Member.GetHashCode() * 1777 + this.Position;
+ }
+
+ public static bool operator ==(ParameterInfo p1, ParameterInfo p2)
+ {
+ return ReferenceEquals(p1, p2) || (!ReferenceEquals(p1, null) && p1.Equals(p2));
+ }
+
+ public static bool operator !=(ParameterInfo p1, ParameterInfo p2)
+ {
+ return !(p1 == p2);
+ }
+
+ public abstract string Name { get; }
+ public abstract Type ParameterType { get; }
+ public abstract ParameterAttributes Attributes { get; }
+ public abstract int Position { get; }
+ public abstract object RawDefaultValue { get; }
+ public abstract Type[] GetOptionalCustomModifiers();
+ public abstract Type[] GetRequiredCustomModifiers();
+ public abstract MemberInfo Member { get; }
+ public abstract int MetadataToken { get; }
+ internal abstract Module Module { get; }
+
+ public bool IsIn
+ {
+ get { return (Attributes & ParameterAttributes.In) != 0; }
+ }
+
+ public bool IsOut
+ {
+ get { return (Attributes & ParameterAttributes.Out) != 0; }
+ }
+
+ public bool IsLcid
+ {
+ get { return (Attributes & ParameterAttributes.Lcid) != 0; }
+ }
+
+ public bool IsRetval
+ {
+ get { return (Attributes & ParameterAttributes.Retval) != 0; }
+ }
+
+ public bool IsOptional
+ {
+ get { return (Attributes & ParameterAttributes.Optional) != 0; }
+ }
+
+ public bool IsDefined(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
+ }
+
+ public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
+ }
+
+ internal virtual IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return this.Module.GetCustomAttributes(this.MetadataToken, attributeType);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ public struct ParameterModifier
+ {
+ private readonly bool[] values;
+
+ public ParameterModifier(int parameterCount)
+ {
+ values = new bool[parameterCount];
+ }
+
+ public bool this[int index]
+ {
+ get { return values[index]; }
+ set { values[index] = value; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("IKVM.NET Reflection")]
+[assembly: AssemblyDescription("Managed (partial) Reflection implementation for use by ikvmc")]
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+namespace IKVM.Reflection
+{
+ public abstract class PropertyInfo : MemberInfo
+ {
+ public sealed override MemberTypes MemberType
+ {
+ get { return MemberTypes.Property; }
+ }
+
+ public abstract PropertyAttributes Attributes { get; }
+ public abstract bool CanRead { get; }
+ public abstract bool CanWrite { get; }
+ public abstract MethodInfo GetGetMethod(bool nonPublic);
+ public abstract MethodInfo GetSetMethod(bool nonPublic);
+ public abstract MethodInfo[] GetAccessors(bool nonPublic);
+ public abstract object GetRawConstantValue();
+ internal abstract bool IsPublic { get; }
+ internal abstract bool IsStatic { get; }
+ internal abstract PropertySignature PropertySignature { get; }
+
+ private sealed class ParameterInfoImpl : ParameterInfo
+ {
+ private readonly PropertyInfo property;
+ private readonly int parameter;
+
+ internal ParameterInfoImpl(PropertyInfo property, int parameter)
+ {
+ this.property = property;
+ this.parameter = parameter;
+ }
+
+ public override string Name
+ {
+ get { return null; }
+ }
+
+ public override Type ParameterType
+ {
+ get { return property.PropertySignature.GetParameter(parameter); }
+ }
+
+ public override ParameterAttributes Attributes
+ {
+ get { return ParameterAttributes.None; }
+ }
+
+ public override int Position
+ {
+ get { return parameter; }
+ }
+
+ public override object RawDefaultValue
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return property.PropertySignature.GetOptionalCustomModifiers(parameter);
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return property.PropertySignature.GetRequiredCustomModifiers(parameter);
+ }
+
+ public override MemberInfo Member
+ {
+ get { return property; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return 0x08000000; }
+ }
+
+ internal override Module Module
+ {
+ get { return property.Module; }
+ }
+ }
+
+ public ParameterInfo[] GetIndexParameters()
+ {
+ ParameterInfo[] parameters = new ParameterInfo[this.PropertySignature.ParameterCount];
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = new ParameterInfoImpl(this, i);
+ }
+ return parameters;
+ }
+
+ public Type PropertyType
+ {
+ get { return this.PropertySignature.PropertyType; }
+ }
+
+ public Type[] GetRequiredCustomModifiers()
+ {
+ return this.PropertySignature.GetRequiredCustomModifiers();
+ }
+
+ public Type[] GetOptionalCustomModifiers()
+ {
+ return this.PropertySignature.GetOptionalCustomModifiers();
+ }
+
+ public bool IsSpecialName
+ {
+ get { return (Attributes & PropertyAttributes.SpecialName) != 0; }
+ }
+
+ public MethodInfo GetGetMethod()
+ {
+ return GetGetMethod(false);
+ }
+
+ public MethodInfo GetSetMethod()
+ {
+ return GetSetMethod(false);
+ }
+
+ public MethodInfo[] GetAccessors()
+ {
+ return GetAccessors(false);
+ }
+
+ internal virtual PropertyInfo BindTypeParameters(Type type)
+ {
+ return new GenericPropertyInfo(this.DeclaringType.BindTypeParameters(type), this);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+ sealed class PropertySignature : Signature
+ {
+ private CallingConventions callingConvention;
+ private readonly Type propertyType;
+ private readonly Type[] optionalCustomModifiers;
+ private readonly Type[] requiredCustomModifiers;
+ private readonly Type[] parameterTypes;
+ private readonly Type[][] parameterOptionalCustomModifiers;
+ private readonly Type[][] parameterRequiredCustomModifiers;
+
+ internal static PropertySignature Create(CallingConventions callingConvention, Type propertyType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeOptionalCustomModifiers, Type[][] parameterTypeRequiredCustomModifiers)
+ {
+ return new PropertySignature(callingConvention, propertyType, Util.Copy(optionalCustomModifiers), Util.Copy(requiredCustomModifiers), Util.Copy(parameterTypes), Util.Copy(parameterTypeOptionalCustomModifiers), Util.Copy(parameterTypeRequiredCustomModifiers));
+ }
+
+ private PropertySignature(CallingConventions callingConvention, Type propertyType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeOptionalCustomModifiers, Type[][] parameterTypeRequiredCustomModifiers)
+ {
+ this.callingConvention = callingConvention;
+ this.propertyType = propertyType;
+ this.optionalCustomModifiers = optionalCustomModifiers;
+ this.requiredCustomModifiers = requiredCustomModifiers;
+ this.parameterTypes = parameterTypes;
+ this.parameterOptionalCustomModifiers = parameterTypeOptionalCustomModifiers;
+ this.parameterRequiredCustomModifiers = parameterTypeRequiredCustomModifiers;
+ }
+
+ public override bool Equals(object obj)
+ {
+ PropertySignature other = obj as PropertySignature;
+ return other != null
+ && other.propertyType.Equals(propertyType)
+ && Util.ArrayEquals(other.optionalCustomModifiers, optionalCustomModifiers)
+ && Util.ArrayEquals(other.requiredCustomModifiers, requiredCustomModifiers);
+ }
+
+ public override int GetHashCode()
+ {
+ return propertyType.GetHashCode() ^ Util.GetHashCode(optionalCustomModifiers) ^ Util.GetHashCode(requiredCustomModifiers);
+ }
+
+ internal int ParameterCount
+ {
+ get { return parameterTypes.Length; }
+ }
+
+ internal bool HasThis
+ {
+ set
+ {
+ if (value)
+ {
+ callingConvention |= CallingConventions.HasThis;
+ }
+ else
+ {
+ callingConvention &= ~CallingConventions.HasThis;
+ }
+ }
+ }
+
+ internal Type PropertyType
+ {
+ get { return propertyType; }
+ }
+
+ internal Type[] GetOptionalCustomModifiers()
+ {
+ return Util.Copy(optionalCustomModifiers);
+ }
+
+ internal Type[] GetRequiredCustomModifiers()
+ {
+ return Util.Copy(requiredCustomModifiers);
+ }
+
+ internal PropertySignature ExpandTypeParameters(Type declaringType)
+ {
+ return new PropertySignature(
+ callingConvention,
+ propertyType.BindTypeParameters(declaringType),
+ BindTypeParameters(declaringType, optionalCustomModifiers),
+ BindTypeParameters(declaringType, requiredCustomModifiers),
+ BindTypeParameters(declaringType, parameterTypes),
+ BindTypeParameters(declaringType, parameterOptionalCustomModifiers),
+ BindTypeParameters(declaringType, parameterRequiredCustomModifiers));
+ }
+
+ internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
+ {
+ byte flags = PROPERTY;
+ if ((callingConvention & CallingConventions.HasThis) != 0)
+ {
+ flags |= HASTHIS;
+ }
+ if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+ {
+ flags |= EXPLICITTHIS;
+ }
+ if ((callingConvention & CallingConventions.VarArgs) != 0)
+ {
+ flags |= VARARG;
+ }
+ bb.Write(flags);
+ bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers);
+ WriteType(module, bb, propertyType);
+ if (parameterTypes != null)
+ {
+ for (int i = 0; i < parameterTypes.Length; i++)
+ {
+ if (parameterRequiredCustomModifiers != null)
+ {
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, parameterRequiredCustomModifiers[i]);
+ }
+ if (parameterOptionalCustomModifiers != null)
+ {
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, parameterOptionalCustomModifiers[i]);
+ }
+ WriteType(module, bb, parameterTypes[i]);
+ }
+ }
+ }
+
+ internal Type GetParameter(int parameter)
+ {
+ return parameterTypes[parameter];
+ }
+
+ internal Type[] GetOptionalCustomModifiers(int parameter)
+ {
+ return parameterOptionalCustomModifiers == null ? Type.EmptyTypes : parameterOptionalCustomModifiers[parameter];
+ }
+
+ internal Type[] GetRequiredCustomModifiers(int parameter)
+ {
+ return parameterRequiredCustomModifiers == null ? Type.EmptyTypes : parameterRequiredCustomModifiers[parameter];
+ }
+
+ internal static PropertySignature ReadSig(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ byte flags = br.ReadByte();
+ if ((flags & PROPERTY) == 0)
+ {
+ throw new BadImageFormatException();
+ }
+ CallingConventions callingConvention = CallingConventions.Standard;
+ if ((flags & HASTHIS) != 0)
+ {
+ callingConvention |= CallingConventions.HasThis;
+ }
+ if ((flags & EXPLICITTHIS) != 0)
+ {
+ callingConvention |= CallingConventions.ExplicitThis;
+ }
+ Type returnType;
+ Type[] returnTypeRequiredCustomModifiers;
+ Type[] returnTypeOptionalCustomModifiers;
+ Type[] parameterTypes;
+ Type[][] parameterRequiredCustomModifiers;
+ Type[][] parameterOptionalCustomModifiers;
+ int paramCount = br.ReadCompressedInt();
+ ReadCustomModifiers(module, br, context, out returnTypeRequiredCustomModifiers, out returnTypeOptionalCustomModifiers);
+ returnType = ReadRetType(module, br, context);
+ parameterTypes = new Type[paramCount];
+ parameterRequiredCustomModifiers = null;
+ parameterOptionalCustomModifiers = null;
+ for (int i = 0; i < parameterTypes.Length; i++)
+ {
+ if (IsCustomModifier(br.PeekByte()))
+ {
+ if (parameterOptionalCustomModifiers == null)
+ {
+ parameterOptionalCustomModifiers = new Type[parameterTypes.Length][];
+ parameterRequiredCustomModifiers = new Type[parameterTypes.Length][];
+ }
+ ReadCustomModifiers(module, br, context, out parameterRequiredCustomModifiers[i], out parameterOptionalCustomModifiers[i]);
+ }
+ parameterTypes[i] = ReadParam(module, br, context);
+ }
+ return new PropertySignature(callingConvention, returnType, returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers,
+ parameterTypes, parameterOptionalCustomModifiers, parameterRequiredCustomModifiers);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Configuration.Assemblies;
+using System.IO;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class AssemblyReader : Assembly
+ {
+ private const int ContainsNoMetaData = 0x0001;
+ private readonly string location;
+ private readonly ModuleReader manifestModule;
+ private readonly Module[] externalModules;
+
+ internal AssemblyReader(string location, ModuleReader manifestModule)
+ : base(manifestModule.universe)
+ {
+ this.location = location;
+ this.manifestModule = manifestModule;
+ externalModules = new Module[manifestModule.File.records.Length];
+ }
+
+ public override string Location
+ {
+ get { return location; }
+ }
+
+ public override string FullName
+ {
+ get { return GetName().FullName; }
+ }
+
+ public override AssemblyName GetName()
+ {
+ return GetNameImpl(ref manifestModule.AssemblyTable.records[0]);
+ }
+
+ private AssemblyName GetNameImpl(ref AssemblyTable.Record rec)
+ {
+ AssemblyName name = new AssemblyName();
+ name.Name = manifestModule.GetString(rec.Name);
+ name.Version = new Version(rec.MajorVersion, rec.MinorVersion, rec.BuildNumber, rec.RevisionNumber);
+ if (rec.PublicKey != 0)
+ {
+ name.SetPublicKey(manifestModule.GetBlobCopy(rec.PublicKey));
+ }
+ else
+ {
+ name.SetPublicKey(Empty<byte>.Array);
+ }
+ if (rec.Culture != 0)
+ {
+ name.CultureInfo = new System.Globalization.CultureInfo(manifestModule.GetString(rec.Culture));
+ }
+ else
+ {
+ name.CultureInfo = System.Globalization.CultureInfo.InvariantCulture;
+ }
+ name.HashAlgorithm = (AssemblyHashAlgorithm)rec.HashAlgId;
+ name.CodeBase = this.CodeBase;
+ name.Flags = (AssemblyNameFlags)rec.Flags;
+ return name;
+ }
+
+ public override Type[] GetTypes()
+ {
+ if (externalModules.Length == 0)
+ {
+ return manifestModule.GetTypes();
+ }
+
+ List<Type> list = new List<Type>();
+ foreach (Module module in GetModules(false))
+ {
+ list.AddRange(module.GetTypes());
+ }
+ return list.ToArray();
+ }
+
+ internal override Type GetTypeImpl(string typeName)
+ {
+ Type type = manifestModule.GetType(typeName);
+ for (int i = 0; type == null && i < externalModules.Length; i++)
+ {
+ if ((manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
+ {
+ type = GetModule(i).GetType(typeName);
+ }
+ }
+ return type;
+ }
+
+ public override string ImageRuntimeVersion
+ {
+ get { return manifestModule.ImageRuntimeVersion; }
+ }
+
+ public override Module ManifestModule
+ {
+ get { return manifestModule; }
+ }
+
+ public override Module[] GetLoadedModules(bool getResourceModules)
+ {
+ List<Module> list = new List<Module>();
+ list.Add(manifestModule);
+ foreach (Module m in externalModules)
+ {
+ if (m != null)
+ {
+ list.Add(m);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public override Module[] GetModules(bool getResourceModules)
+ {
+ if (externalModules.Length == 0)
+ {
+ return new Module[] { manifestModule };
+ }
+ else
+ {
+ List<Module> list = new List<Module>();
+ list.Add(manifestModule);
+ for (int i = 0; i < manifestModule.File.records.Length; i++)
+ {
+ if (getResourceModules || (manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
+ {
+ list.Add(GetModule(i));
+ }
+ }
+ return list.ToArray();
+ }
+ }
+
+ public override Module GetModule(string name)
+ {
+ if (name.Equals(manifestModule.ScopeName, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return manifestModule;
+ }
+ int index = GetModuleIndex(name);
+ if (index != -1)
+ {
+ return GetModule(index);
+ }
+ return null;
+ }
+
+ private int GetModuleIndex(string name)
+ {
+ for (int i = 0; i < manifestModule.File.records.Length; i++)
+ {
+ if (name.Equals(manifestModule.GetString(manifestModule.File.records[i].Name), StringComparison.InvariantCultureIgnoreCase))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private Module GetModule(int index)
+ {
+ if (externalModules[index] != null)
+ {
+ return externalModules[index];
+ }
+ // TODO add ModuleResolve event
+ string location = Path.Combine(Path.GetDirectoryName(this.location), manifestModule.GetString(manifestModule.File.records[index].Name));
+ return LoadModule(index, File.ReadAllBytes(location), location);
+ }
+
+ private Module LoadModule(int index, byte[] rawModule, string location)
+ {
+ if ((manifestModule.File.records[index].Flags & ContainsNoMetaData) != 0)
+ {
+ return externalModules[index] = new ResourceModule(this, manifestModule.GetString(manifestModule.File.records[index].Name), location);
+ }
+ else
+ {
+ return externalModules[index] = new ModuleReader(this, manifestModule.universe, new MemoryStream(rawModule), location);
+ }
+ }
+
+ public override Module LoadModule(string moduleName, byte[] rawModule)
+ {
+ int index = GetModuleIndex(moduleName);
+ if (index == -1)
+ {
+ throw new ArgumentException();
+ }
+ if (externalModules[index] != null)
+ {
+ return externalModules[index];
+ }
+ return LoadModule(index, rawModule, null);
+ }
+
+ public override MethodInfo EntryPoint
+ {
+ get { return manifestModule.GetEntryPoint(); }
+ }
+
+ public override string[] GetManifestResourceNames()
+ {
+ return manifestModule.GetManifestResourceNames();
+ }
+
+ public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
+ {
+ return manifestModule.GetManifestResourceInfo(resourceName);
+ }
+
+ public override Stream GetManifestResourceStream(string resourceName)
+ {
+ return manifestModule.GetManifestResourceStream(resourceName);
+ }
+
+ public override AssemblyName[] GetReferencedAssemblies()
+ {
+ return manifestModule.__GetReferencedAssemblies();
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return manifestModule.GetCustomAttributes(0x20000001, attributeType);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class ByteReader
+ {
+ private byte[] buffer;
+ private int pos;
+ private int end;
+
+ internal ByteReader(byte[] buffer, int offset, int length)
+ {
+ this.buffer = buffer;
+ this.pos = offset;
+ this.end = pos + length;
+ }
+
+ internal static ByteReader FromBlob(byte[] blobHeap, int blob)
+ {
+ ByteReader br = new ByteReader(blobHeap, blob, 4);
+ int length = br.ReadCompressedInt();
+ br.end = br.pos + length;
+ return br;
+ }
+
+ internal int Length
+ {
+ get { return end - pos; }
+ }
+
+ internal byte PeekByte()
+ {
+ if (pos == end)
+ throw new BadImageFormatException();
+ return buffer[pos];
+ }
+
+ internal byte ReadByte()
+ {
+ if (pos == end)
+ throw new BadImageFormatException();
+ return buffer[pos++];
+ }
+
+ internal byte[] ReadBytes(int count)
+ {
+ if (count < 0)
+ throw new BadImageFormatException();
+ if (end - pos < count)
+ throw new BadImageFormatException();
+ byte[] buf = new byte[count];
+ Buffer.BlockCopy(buffer, pos, buf, 0, count);
+ pos += count;
+ return buf;
+ }
+
+ internal int ReadCompressedInt()
+ {
+ byte b1 = ReadByte();
+ if (b1 <= 0x7F)
+ {
+ return b1;
+ }
+ else if ((b1 & 0xC0) == 0x80)
+ {
+ byte b2 = ReadByte();
+ return ((b1 & 0x3F) << 8) | b2;
+ }
+ else
+ {
+ byte b2 = ReadByte();
+ byte b3 = ReadByte();
+ byte b4 = ReadByte();
+ return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
+ }
+ }
+
+ internal string ReadString()
+ {
+ if (PeekByte() == 0xFF)
+ {
+ pos++;
+ return null;
+ }
+ int length = ReadCompressedInt();
+ string str = Encoding.UTF8.GetString(buffer, pos, length);
+ pos += length;
+ return str;
+ }
+
+ internal char ReadChar()
+ {
+ return (char)ReadInt16();
+ }
+
+ internal sbyte ReadSByte()
+ {
+ return (sbyte)ReadByte();
+ }
+
+ internal short ReadInt16()
+ {
+ if (end - pos < 2)
+ throw new BadImageFormatException();
+ byte b1 = buffer[pos++];
+ byte b2 = buffer[pos++];
+ return (short)(b1 | (b2 << 8));
+ }
+
+ internal ushort ReadUInt16()
+ {
+ return (ushort)ReadInt16();
+ }
+
+ internal int ReadInt32()
+ {
+ if (end - pos < 4)
+ throw new BadImageFormatException();
+ byte b1 = buffer[pos++];
+ byte b2 = buffer[pos++];
+ byte b3 = buffer[pos++];
+ byte b4 = buffer[pos++];
+ return (int)(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24));
+ }
+
+ internal uint ReadUInt32()
+ {
+ return (uint)ReadInt32();
+ }
+
+ internal long ReadInt64()
+ {
+ ulong lo = ReadUInt32();
+ ulong hi = ReadUInt32();
+ return (long)(lo | (hi << 32));
+ }
+
+ internal ulong ReadUInt64()
+ {
+ return (ulong)ReadInt64();
+ }
+
+ internal float ReadSingle()
+ {
+ if (end - pos < 4)
+ throw new BadImageFormatException();
+ float value = BitConverter.ToSingle(buffer, pos);
+ pos += 4;
+ return value;
+ }
+
+ internal double ReadDouble()
+ {
+ return BitConverter.Int64BitsToDouble(ReadInt64());
+ }
+
+ internal ByteReader Slice(int length)
+ {
+ if (end - pos < length)
+ throw new BadImageFormatException();
+ ByteReader br = new ByteReader(buffer, pos, length);
+ pos += length;
+ return br;
+ }
+
+ // NOTE this method only works if the original offset was aligned and for alignments that are a power of 2
+ internal void Align(int alignment)
+ {
+ alignment--;
+ pos = (pos + alignment) & ~alignment;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class EventInfoImpl : EventInfo
+ {
+ private readonly ModuleReader module;
+ private readonly Type declaringType;
+ private readonly int index;
+ private bool isPublic;
+ private bool isStatic;
+ private bool flagsCached;
+
+ internal EventInfoImpl(ModuleReader module, Type declaringType, int index)
+ {
+ this.module = module;
+ this.declaringType = declaringType;
+ this.index = index;
+ }
+
+ public override bool Equals(object obj)
+ {
+ EventInfoImpl other = obj as EventInfoImpl;
+ return other != null && other.declaringType == declaringType && other.index == index;
+ }
+
+ public override int GetHashCode()
+ {
+ return declaringType.GetHashCode() * 123 + index;
+ }
+
+ public override EventAttributes Attributes
+ {
+ get { return (EventAttributes)module.Event.records[index].EventFlags; }
+ }
+
+ public override MethodInfo GetAddMethod(bool nonPublic)
+ {
+ return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.AddOn);
+ }
+
+ public override MethodInfo GetRaiseMethod(bool nonPublic)
+ {
+ return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Fire);
+ }
+
+ public override MethodInfo GetRemoveMethod(bool nonPublic)
+ {
+ return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.RemoveOn);
+ }
+
+ public override MethodInfo[] GetOtherMethods(bool nonPublic)
+ {
+ return module.MethodSemantics.GetMethods(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Other);
+ }
+
+ public override Type EventHandlerType
+ {
+ get { return module.ResolveType(module.Event.records[index].EventType, declaringType); }
+ }
+
+ public override string Name
+ {
+ get { return module.GetString(module.Event.records[index].Name); }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return declaringType; }
+ }
+
+ public override Module Module
+ {
+ get { return module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return (EventTable.Index << 24) + index + 1; }
+ }
+
+ internal override bool IsPublic
+ {
+ get
+ {
+ if (!flagsCached)
+ {
+ ComputeFlags();
+ }
+ return isPublic;
+ }
+ }
+
+ internal override bool IsStatic
+ {
+ get
+ {
+ if (!flagsCached)
+ {
+ ComputeFlags();
+ }
+ return isStatic;
+ }
+ }
+
+ private void ComputeFlags()
+ {
+ module.MethodSemantics.ComputeFlags(module, this.MetadataToken, out isPublic, out isStatic);
+ flagsCached = true;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class FieldDefImpl : FieldInfo
+ {
+ private readonly ModuleReader module;
+ private readonly TypeDefImpl declaringType;
+ private readonly int index;
+ private FieldSignature lazyFieldSig;
+
+ internal FieldDefImpl(ModuleReader module, TypeDefImpl declaringType, int index)
+ {
+ this.module = module;
+ this.declaringType = declaringType;
+ this.index = index;
+ }
+
+ public override FieldAttributes Attributes
+ {
+ get { return (FieldAttributes)module.Field.records[index].Flags; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return declaringType.IsModulePseudoType ? null : declaringType; }
+ }
+
+ public override string Name
+ {
+ get { return module.GetString(module.Field.records[index].Name); }
+ }
+
+ public override string ToString()
+ {
+ return this.FieldType.Name + " " + this.Name;
+ }
+
+ public override Module Module
+ {
+ get { return module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return (FieldTable.Index << 24) + index + 1; }
+ }
+
+ public override object GetRawConstantValue()
+ {
+ return module.Constant.GetRawConstantValue(module, this.MetadataToken);
+ }
+
+ public override void __GetDataFromRVA(byte[] data, int offset, int length)
+ {
+ int rid = index + 1;
+ // TODO binary search?
+ for (int i = 0; i < module.FieldRVA.records.Length; i++)
+ {
+ if (module.FieldRVA.records[i].Field == rid)
+ {
+ int rva = module.FieldRVA.records[i].RVA;
+ if (rva == 0)
+ {
+ // C++ assemblies can have fields that have an RVA that is zero
+ Array.Clear(data, offset, length);
+ return;
+ }
+ module.SeekRVA(rva);
+ while (length > 0)
+ {
+ int read = module.stream.Read(data, offset, length);
+ if (read == 0)
+ {
+ // C++ assemblies can have fields that have an RVA that lies outside of the file
+ break;
+ }
+ offset += read;
+ length -= read;
+ }
+ return;
+ }
+ }
+ throw new InvalidOperationException();
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ List<CustomAttributeData> list = module.GetCustomAttributes(this.MetadataToken, attributeType);
+ if ((this.Attributes & FieldAttributes.HasFieldMarshal) != 0
+ && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_MarshalAsAttribute)))
+ {
+ list.Add(MarshalSpec.GetMarshalAsAttribute(module, this.MetadataToken));
+ }
+ if (declaringType.IsExplicitLayout
+ && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_FieldOffsetAttribute)))
+ {
+ int rid = index + 1;
+ // TODO use binary search?
+ for (int i = 0; i < module.FieldLayout.records.Length; i++)
+ {
+ if (module.FieldLayout.records[i].Field == rid)
+ {
+ ConstructorInfo constructor = module.universe.System_Runtime_InteropServices_FieldOffsetAttribute.GetConstructor(new Type[] { module.universe.System_Int32 });
+ list.Add(new CustomAttributeData(constructor,
+ new object[] { module.FieldLayout.records[i].Offset },
+ null));
+ break;
+ }
+ }
+ }
+ return list;
+ }
+
+ internal override FieldSignature FieldSignature
+ {
+ get { return lazyFieldSig ?? (lazyFieldSig = FieldSignature.ReadSig(module, module.GetBlob(module.Field.records[index].Signature), declaringType)); }
+ }
+
+ internal override int ImportTo(Emit.ModuleBuilder module)
+ {
+ return module.ImportMethodOrField(declaringType, this.Name, this.FieldSignature);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ abstract class TypeParameterType : Type
+ {
+ public sealed override string AssemblyQualifiedName
+ {
+ get { return null; }
+ }
+
+ public sealed override bool IsValueType
+ {
+ get { return (this.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; }
+ }
+
+ public sealed override Type BaseType
+ {
+ get
+ {
+ foreach (Type type in GetGenericParameterConstraints())
+ {
+ if (!type.IsInterface && !type.IsGenericParameter)
+ {
+ return type;
+ }
+ }
+ return this.IsValueType ? this.Module.universe.System_ValueType : this.Module.universe.System_Object;
+ }
+ }
+
+ public override Type[] __GetDeclaredInterfaces()
+ {
+ List<Type> list = new List<Type>();
+ foreach (Type type in GetGenericParameterConstraints())
+ {
+ if (type.IsInterface)
+ {
+ list.Add(type);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public sealed override TypeAttributes Attributes
+ {
+ get { return TypeAttributes.Public; }
+ }
+
+ public sealed override Type UnderlyingSystemType
+ {
+ get { return this; }
+ }
+
+ public sealed override string FullName
+ {
+ get { return null; }
+ }
+
+ public sealed override string ToString()
+ {
+ return this.Name;
+ }
+
+ public sealed override bool IsGenericParameter
+ {
+ get { return true; }
+ }
+ }
+
+ sealed class UnboundGenericMethodParameter : TypeParameterType
+ {
+ private static readonly DummyModule module = new DummyModule();
+ private readonly int position;
+
+ private sealed class DummyModule : Module
+ {
+ internal DummyModule()
+ : base(new Universe())
+ {
+ }
+
+ public override bool Equals(object obj)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override int GetHashCode()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override string ToString()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override int MDStreamVersion
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override Assembly Assembly
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ internal override Type GetTypeImpl(string typeName)
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal override void GetTypesImpl(List<Type> list)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override string FullyQualifiedName
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override string Name
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override Guid ModuleVersionId
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override string ResolveString(int metadataToken)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override string ScopeName
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override AssemblyName[] __GetReferencedAssemblies()
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal override Type GetModuleType()
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal override ByteReader GetBlob(int blobIndex)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+
+ internal static Type Make(int position)
+ {
+ return module.CanonicalizeType(new UnboundGenericMethodParameter(position));
+ }
+
+ private UnboundGenericMethodParameter(int position)
+ {
+ this.position = position;
+ }
+
+ public override bool Equals(object obj)
+ {
+ UnboundGenericMethodParameter other = obj as UnboundGenericMethodParameter;
+ return other != null && other.position == position;
+ }
+
+ public override int GetHashCode()
+ {
+ return position;
+ }
+
+ public override string Namespace
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override string Name
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override int MetadataToken
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override Module Module
+ {
+ get { return module; }
+ }
+
+ public override int GenericParameterPosition
+ {
+ get { return position; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return null; }
+ }
+
+ public override MethodBase DeclaringMethod
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public override Type[] GetGenericParameterConstraints()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ internal override Type BindTypeParameters(IGenericBinder binder)
+ {
+ return binder.BindMethodParameter(this);
+ }
+ }
+
+ sealed class GenericTypeParameter : TypeParameterType
+ {
+ private readonly ModuleReader module;
+ private readonly int index;
+
+ internal GenericTypeParameter(ModuleReader module, int index)
+ {
+ this.module = module;
+ this.index = index;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ public override string Namespace
+ {
+ get { return DeclaringType.Namespace; }
+ }
+
+ public override string Name
+ {
+ get { return module.GetString(module.GenericParam.records[index].Name); }
+ }
+
+ public override Module Module
+ {
+ get { return module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return (GenericParamTable.Index << 24) + index + 1; }
+ }
+
+ public override int GenericParameterPosition
+ {
+ get { return module.GenericParam.records[index].Number; }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ int owner = module.GenericParam.records[index].Owner;
+ return (owner >> 24) == TypeDefTable.Index ? module.ResolveType(owner) : null;
+ }
+ }
+
+ public override MethodBase DeclaringMethod
+ {
+ get
+ {
+ int owner = module.GenericParam.records[index].Owner;
+ return (owner >> 24) == MethodDefTable.Index ? module.ResolveMethod(owner) : null;
+ }
+ }
+
+ public override Type[] GetGenericParameterConstraints()
+ {
+ IGenericContext context = (this.DeclaringMethod as IGenericContext) ?? this.DeclaringType;
+ List<Type> list = new List<Type>();
+ int token = this.MetadataToken;
+ // TODO use binary search
+ for (int i = 0; i < module.GenericParamConstraint.records.Length; i++)
+ {
+ if (module.GenericParamConstraint.records[i].Owner == token)
+ {
+ list.Add(module.ResolveType(module.GenericParamConstraint.records[i].Constraint, context));
+ }
+ }
+ return list.ToArray();
+ }
+
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ get { return (GenericParameterAttributes)module.GenericParam.records[index].Flags; }
+ }
+
+ internal override Type BindTypeParameters(IGenericBinder binder)
+ {
+ int owner = module.GenericParam.records[index].Owner;
+ if ((owner >> 24) == MethodDefTable.Index)
+ {
+ return binder.BindMethodParameter(this);
+ }
+ else
+ {
+ return binder.BindTypeParameter(this);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class MetadataReader : MetadataRW
+ {
+ private readonly BinaryReader br;
+
+ internal MetadataReader(ModuleReader module, BinaryReader br, byte heapSizes)
+ : base(module, (heapSizes & 0x01) != 0, (heapSizes & 0x02) != 0, (heapSizes & 0x04) != 0)
+ {
+ this.br = br;
+ }
+
+ internal short ReadInt16()
+ {
+ return br.ReadInt16();
+ }
+
+ internal ushort ReadUInt16()
+ {
+ return br.ReadUInt16();
+ }
+
+ internal int ReadInt32()
+ {
+ return br.ReadInt32();
+ }
+
+ internal int ReadStringIndex()
+ {
+ if (bigStrings)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadGuidIndex()
+ {
+ if (bigGuids)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadBlobIndex()
+ {
+ if (bigBlobs)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadResolutionScope()
+ {
+ int codedIndex;
+ if (bigResolutionScope)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 3)
+ {
+ case 0:
+ return (ModuleTable.Index << 24) + (codedIndex >> 2);
+ case 1:
+ return (ModuleRefTable.Index << 24) + (codedIndex >> 2);
+ case 2:
+ return (AssemblyRefTable.Index << 24) + (codedIndex >> 2);
+ case 3:
+ return (TypeRefTable.Index << 24) + (codedIndex >> 2);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadTypeDefOrRef()
+ {
+ int codedIndex;
+ if (bigTypeDefOrRef)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 3)
+ {
+ case 0:
+ return (TypeDefTable.Index << 24) + (codedIndex >> 2);
+ case 1:
+ return (TypeRefTable.Index << 24) + (codedIndex >> 2);
+ case 2:
+ return (TypeSpecTable.Index << 24) + (codedIndex >> 2);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadMemberRefParent()
+ {
+ int codedIndex;
+ if (bigMemberRefParent)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 7)
+ {
+ case 0:
+ return (TypeDefTable.Index << 24) + (codedIndex >> 3);
+ case 1:
+ return (TypeRefTable.Index << 24) + (codedIndex >> 3);
+ case 2:
+ return (ModuleRefTable.Index << 24) + (codedIndex >> 3);
+ case 3:
+ return (MethodDefTable.Index << 24) + (codedIndex >> 3);
+ case 4:
+ return (TypeSpecTable.Index << 24) + (codedIndex >> 3);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadHasCustomAttribute()
+ {
+ int codedIndex;
+ if (bigHasCustomAttribute)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 31)
+ {
+ case 0:
+ return (MethodDefTable.Index << 24) + (codedIndex >> 5);
+ case 1:
+ return (FieldTable.Index << 24) + (codedIndex >> 5);
+ case 2:
+ return (TypeRefTable.Index << 24) + (codedIndex >> 5);
+ case 3:
+ return (TypeDefTable.Index << 24) + (codedIndex >> 5);
+ case 4:
+ return (ParamTable.Index << 24) + (codedIndex >> 5);
+ case 5:
+ return (InterfaceImplTable.Index << 24) + (codedIndex >> 5);
+ case 6:
+ return (MemberRefTable.Index << 24) + (codedIndex >> 5);
+ case 7:
+ return (ModuleTable.Index << 24) + (codedIndex >> 5);
+ case 8:
+ throw new BadImageFormatException();
+ case 9:
+ return (PropertyTable.Index << 24) + (codedIndex >> 5);
+ case 10:
+ return (EventTable.Index << 24) + (codedIndex >> 5);
+ case 11:
+ return (StandAloneSigTable.Index << 24) + (codedIndex >> 5);
+ case 12:
+ return (ModuleRefTable.Index << 24) + (codedIndex >> 5);
+ case 13:
+ return (TypeSpecTable.Index << 24) + (codedIndex >> 5);
+ case 14:
+ return (AssemblyTable.Index << 24) + (codedIndex >> 5);
+ case 15:
+ return (AssemblyRefTable.Index << 24) + (codedIndex >> 5);
+ case 16:
+ return (FileTable.Index << 24) + (codedIndex >> 5);
+ case 17:
+ return (ExportedTypeTable.Index << 24) + (codedIndex >> 5);
+ case 18:
+ return (ManifestResourceTable.Index << 24) + (codedIndex >> 5);
+ case 19:
+ return (GenericParamTable.Index << 24) + (codedIndex >> 5);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadCustomAttributeType()
+ {
+ int codedIndex;
+ if (bigCustomAttributeType)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 7)
+ {
+ case 2:
+ return (MethodDefTable.Index << 24) + (codedIndex >> 3);
+ case 3:
+ return (MemberRefTable.Index << 24) + (codedIndex >> 3);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadMethodDefOrRef()
+ {
+ int codedIndex;
+ if (bigMethodDefOrRef)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 1)
+ {
+ case 0:
+ return (MethodDefTable.Index << 24) + (codedIndex >> 1);
+ case 1:
+ return (MemberRefTable.Index << 24) + (codedIndex >> 1);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadHasConstant()
+ {
+ int codedIndex;
+ if (bigHasConstant)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 3)
+ {
+ case 0:
+ return (FieldTable.Index << 24) + (codedIndex >> 2);
+ case 1:
+ return (ParamTable.Index << 24) + (codedIndex >> 2);
+ case 2:
+ return (PropertyTable.Index << 24) + (codedIndex >> 2);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadHasSemantics()
+ {
+ int codedIndex;
+ if (bigHasSemantics)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 1)
+ {
+ case 0:
+ return (EventTable.Index << 24) + (codedIndex >> 1);
+ case 1:
+ return (PropertyTable.Index << 24) + (codedIndex >> 1);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadHasFieldMarshal()
+ {
+ int codedIndex;
+ if (bigHasFieldMarshal)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 1)
+ {
+ case 0:
+ return (FieldTable.Index << 24) + (codedIndex >> 1);
+ case 1:
+ return (ParamTable.Index << 24) + (codedIndex >> 1);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadHasDeclSecurity()
+ {
+ int codedIndex;
+ if (bigHasDeclSecurity)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 3)
+ {
+ case 0:
+ return (TypeDefTable.Index << 24) + (codedIndex >> 2);
+ case 1:
+ return (MethodDefTable.Index << 24) + (codedIndex >> 2);
+ case 2:
+ return (AssemblyTable.Index << 24) + (codedIndex >> 2);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadTypeOrMethodDef()
+ {
+ int codedIndex;
+ if (bigTypeOrMethodDef)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 1)
+ {
+ case 0:
+ return (TypeDefTable.Index << 24) + (codedIndex >> 1);
+ case 1:
+ return (MethodDefTable.Index << 24) + (codedIndex >> 1);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadMemberForwarded()
+ {
+ int codedIndex;
+ if (bigMemberForwarded)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 1)
+ {
+ case 0:
+ return (FieldTable.Index << 24) + (codedIndex >> 1);
+ case 1:
+ return (MethodDefTable.Index << 24) + (codedIndex >> 1);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal int ReadImplementation()
+ {
+ int codedIndex;
+ if (bigImplementation)
+ {
+ codedIndex = br.ReadInt32();
+ }
+ else
+ {
+ codedIndex = br.ReadUInt16();
+ }
+ switch (codedIndex & 3)
+ {
+ case 0:
+ return (FileTable.Index << 24) + (codedIndex >> 2);
+ case 1:
+ return (AssemblyRefTable.Index << 24) + (codedIndex >> 2);
+ case 2:
+ return (ExportedTypeTable.Index << 24) + (codedIndex >> 2);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ private int ReadToken(int table, bool big)
+ {
+ int rid;
+ if (big)
+ {
+ rid = br.ReadInt32();
+ }
+ else
+ {
+ rid = br.ReadUInt16();
+ }
+ return rid | (table << 24);
+ }
+
+ internal int ReadField()
+ {
+ if (bigField)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadMethodDef()
+ {
+ if (bigMethodDef)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadParam()
+ {
+ if (bigParam)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadProperty()
+ {
+ if (bigProperty)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadEvent()
+ {
+ if (bigEvent)
+ {
+ return br.ReadInt32();
+ }
+ else
+ {
+ return br.ReadUInt16();
+ }
+ }
+
+ internal int ReadTypeDef()
+ {
+ return ReadToken(TypeDefTable.Index, bigTypeDef);
+ }
+
+ internal int ReadGenericParam()
+ {
+ return ReadToken(GenericParamTable.Index, bigGenericParam);
+ }
+
+ internal int ReadModuleRef()
+ {
+ return ReadToken(ModuleRefTable.Index, bigModuleRef);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class MethodDefImpl : MethodInfo
+ {
+ private readonly ModuleReader module;
+ private readonly int index;
+ private readonly TypeDefImpl declaringType;
+ private MethodSignature lazyMethodSignature;
+ private ParameterInfo returnParameter;
+ private ParameterInfo[] parameters;
+ private Type[] typeArgs;
+
+ internal MethodDefImpl(ModuleReader module, TypeDefImpl declaringType, int index)
+ {
+ this.module = module;
+ this.index = index;
+ this.declaringType = declaringType;
+ }
+
+ public override MethodBody GetMethodBody()
+ {
+ return GetMethodBody(this);
+ }
+
+ internal MethodBody GetMethodBody(IGenericContext context)
+ {
+ if ((GetMethodImplementationFlags() & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL)
+ {
+ // method is not IL
+ return null;
+ }
+ int rva = module.MethodDef.records[index].RVA;
+ return rva == 0 ? null : new MethodBody(module, rva, context);
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get { return this.MethodSignature.CallingConvention; }
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return (MethodAttributes)module.MethodDef.records[index].Flags; }
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return (MethodImplAttributes)module.MethodDef.records[index].ImplFlags;
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ PopulateParameters();
+ return (ParameterInfo[])parameters.Clone();
+ }
+
+ private void PopulateParameters()
+ {
+ if (parameters == null)
+ {
+ MethodSignature methodSignature = this.MethodSignature;
+ parameters = new ParameterInfo[methodSignature.GetParameterCount()];
+ int parameter = module.MethodDef.records[index].ParamList - 1;
+ int end = module.MethodDef.records.Length > index + 1 ? module.MethodDef.records[index + 1].ParamList - 1 : module.Param.records.Length;
+ for (; parameter < end; parameter++)
+ {
+ int seq = module.Param.records[parameter].Sequence - 1;
+ if (seq == -1)
+ {
+ returnParameter = new ParameterInfoImpl(this, seq, parameter);
+ }
+ else
+ {
+ parameters[seq] = new ParameterInfoImpl(this, seq, parameter);
+ }
+ }
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ if (parameters[i] == null)
+ {
+ parameters[i] = new ParameterInfoImpl(this, i, -1);
+ }
+ }
+ if (returnParameter == null)
+ {
+ returnParameter = new ParameterInfoImpl(this, -1, -1);
+ }
+ }
+ }
+
+ internal override int ParameterCount
+ {
+ get { return this.MethodSignature.GetParameterCount(); }
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get
+ {
+ PopulateParameters();
+ return returnParameter;
+ }
+ }
+
+ public override Type ReturnType
+ {
+ get
+ {
+ return this.ReturnParameter.ParameterType;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return declaringType.IsModulePseudoType ? null : declaringType; }
+ }
+
+ public override string Name
+ {
+ get { return module.GetString(module.MethodDef.records[index].Name); }
+ }
+
+ public override int MetadataToken
+ {
+ get { return (MethodDefTable.Index << 24) + index + 1; }
+ }
+
+ public override bool IsGenericMethodDefinition
+ {
+ get
+ {
+ PopulateGenericArguments();
+ return typeArgs.Length > 0;
+ }
+ }
+
+ public override bool IsGenericMethod
+ {
+ get { return IsGenericMethodDefinition; }
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ PopulateGenericArguments();
+ return Util.Copy(typeArgs);
+ }
+
+ private void PopulateGenericArguments()
+ {
+ if (typeArgs == null)
+ {
+ int token = this.MetadataToken;
+ int first = module.GenericParam.FindFirstByOwner(token);
+ if (first == -1)
+ {
+ typeArgs = Type.EmptyTypes;
+ }
+ else
+ {
+ List<Type> list = new List<Type>();
+ int len = module.GenericParam.records.Length;
+ for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
+ {
+ list.Add(new GenericTypeParameter(module, i));
+ }
+ typeArgs = list.ToArray();
+ }
+ }
+ }
+
+ internal override Type GetGenericMethodArgument(int index)
+ {
+ PopulateGenericArguments();
+ return typeArgs[index];
+ }
+
+ internal override int GetGenericMethodArgumentCount()
+ {
+ PopulateGenericArguments();
+ return typeArgs.Length;
+ }
+
+ public override MethodInfo GetGenericMethodDefinition()
+ {
+ if (this.IsGenericMethodDefinition)
+ {
+ return this;
+ }
+ throw new InvalidOperationException();
+ }
+
+ public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ return new GenericMethodInstance(declaringType, this, typeArguments);
+ }
+
+ public override Module Module
+ {
+ get { return module; }
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ List<CustomAttributeData> list = module.GetCustomAttributes(this.MetadataToken, attributeType);
+ if ((this.Attributes & MethodAttributes.PinvokeImpl) != 0
+ && (attributeType == null || attributeType.IsAssignableFrom(module.universe.System_Runtime_InteropServices_DllImportAttribute)))
+ {
+ CreateDllImportPseudoCustomAttribute(list);
+ }
+ return list;
+ }
+
+ private void CreateDllImportPseudoCustomAttribute(List<CustomAttributeData> attribs)
+ {
+ int token = this.MetadataToken;
+ // TODO use binary search?
+ for (int i = 0; i < module.ImplMap.records.Length; i++)
+ {
+ if (module.ImplMap.records[i].MemberForwarded == token)
+ {
+ const short NoMangle = 0x0001;
+ const short CharSetMask = 0x0006;
+ const short CharSetNotSpec = 0x0000;
+ const short CharSetAnsi = 0x0002;
+ const short CharSetUnicode = 0x0004;
+ const short CharSetAuto = 0x0006;
+ const short SupportsLastError = 0x0040;
+ const short CallConvMask = 0x0700;
+ const short CallConvWinapi = 0x0100;
+ const short CallConvCdecl = 0x0200;
+ const short CallConvStdcall = 0x0300;
+ const short CallConvThiscall = 0x0400;
+ const short CallConvFastcall = 0x0500;
+ // non-standard flags
+ const short BestFitOn = 0x0010;
+ const short BestFitOff = 0x0020;
+ const short CharMapErrorOn = 0x1000;
+ const short CharMapErrorOff = 0x2000;
+
+ Type type = module.universe.System_Runtime_InteropServices_DllImportAttribute;
+ ConstructorInfo constructor = type.GetConstructor(new Type[] { module.universe.System_String });
+ List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>();
+ int flags = module.ImplMap.records[i].MappingFlags;
+ string entryPoint = module.GetString(module.ImplMap.records[i].ImportName);
+ string dllName = module.GetString(module.ModuleRef.records[(module.ImplMap.records[i].ImportScope & 0xFFFFFF) - 1]);
+ System.Runtime.InteropServices.CharSet? charSet;
+ switch (flags & CharSetMask)
+ {
+ case CharSetAnsi:
+ charSet = System.Runtime.InteropServices.CharSet.Ansi;
+ break;
+ case CharSetUnicode:
+ charSet = System.Runtime.InteropServices.CharSet.Unicode;
+ break;
+ case CharSetAuto:
+ charSet = System.Runtime.InteropServices.CharSet.Auto;
+ break;
+ case CharSetNotSpec:
+ default:
+ charSet = null;
+ break;
+ }
+ System.Runtime.InteropServices.CallingConvention callingConvention;
+ switch (flags & CallConvMask)
+ {
+ case CallConvCdecl:
+ callingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
+ break;
+ case CallConvFastcall:
+ callingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
+ break;
+ case CallConvStdcall:
+ callingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
+ break;
+ case CallConvThiscall:
+ callingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
+ break;
+ case CallConvWinapi:
+ default:
+ callingConvention = System.Runtime.InteropServices.CallingConvention.Winapi;
+ break;
+ }
+ list.Add(MakeNamedArgument(type, "EntryPoint", entryPoint));
+ list.Add(MakeNamedArgument(type, "ExactSpelling", flags, NoMangle));
+ list.Add(MakeNamedArgument(type, "SetLastError", flags, SupportsLastError));
+ list.Add(MakeNamedArgument(type, "PreserveSig", (int)GetMethodImplementationFlags(), (int)MethodImplAttributes.PreserveSig));
+ list.Add(MakeNamedArgument(type, "CallingConvention", (int)callingConvention));
+ if (charSet.HasValue)
+ {
+ list.Add(MakeNamedArgument(type, "CharSet", (int)charSet.Value));
+ }
+ if ((flags & (BestFitOn | BestFitOff)) != 0)
+ {
+ list.Add(MakeNamedArgument(type, "BestFitMapping", flags, BestFitOn));
+ }
+ if ((flags & (CharMapErrorOn | CharMapErrorOff)) != 0)
+ {
+ list.Add(MakeNamedArgument(type, "ThrowOnUnmappableChar", flags, CharMapErrorOn));
+ }
+ attribs.Add(new CustomAttributeData(constructor, new object[] { dllName }, list));
+ return;
+ }
+ }
+ }
+
+ private static CustomAttributeNamedArgument MakeNamedArgument(Type type, string field, string value)
+ {
+ return new CustomAttributeNamedArgument(type.GetField(field), new CustomAttributeTypedArgument(type.Module.universe.System_String, value));
+ }
+
+ private static CustomAttributeNamedArgument MakeNamedArgument(Type type, string field, int value)
+ {
+ return new CustomAttributeNamedArgument(type.GetField(field), new CustomAttributeTypedArgument(type.Module.universe.System_Int32, value));
+ }
+
+ private static CustomAttributeNamedArgument MakeNamedArgument(Type type, string field, int flags, int flagMask)
+ {
+ return new CustomAttributeNamedArgument(type.GetField(field), new CustomAttributeTypedArgument(type.Module.universe.System_Boolean, (flags & flagMask) != 0));
+ }
+
+ internal override MethodSignature MethodSignature
+ {
+ get { return lazyMethodSignature ?? (lazyMethodSignature = MethodSignature.ReadSig(module, module.GetBlob(module.MethodDef.records[index].Signature), this)); }
+ }
+
+ internal override int ImportTo(Emit.ModuleBuilder module)
+ {
+ return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature);
+ }
+ }
+
+ sealed class ParameterInfoImpl : ParameterInfo
+ {
+ private readonly MethodDefImpl method;
+ private readonly int position;
+ private readonly int index;
+
+ internal ParameterInfoImpl(MethodDefImpl method, int position, int index)
+ {
+ this.method = method;
+ this.position = position;
+ this.index = index;
+ }
+
+ public override string Name
+ {
+ get { return index == -1 ? null : ((ModuleReader)this.Module).GetString(this.Module.Param.records[index].Name); }
+ }
+
+ public override Type ParameterType
+ {
+ get { return position == -1 ? method.MethodSignature.GetReturnType(method) : method.MethodSignature.GetParameterType(method, position); }
+ }
+
+ public override ParameterAttributes Attributes
+ {
+ get { return index == -1 ? ParameterAttributes.None : (ParameterAttributes)this.Module.Param.records[index].Flags; }
+ }
+
+ public override int Position
+ {
+ get { return position; }
+ }
+
+ public override object RawDefaultValue
+ {
+ get
+ {
+ if ((this.Attributes & ParameterAttributes.HasDefault) != 0)
+ {
+ return this.Module.Constant.GetRawConstantValue(this.Module, this.MetadataToken);
+ }
+ Universe universe = this.Module.universe;
+ if (this.ParameterType == universe.System_Decimal)
+ {
+ Type attr = universe.System_Runtime_CompilerServices_DecimalConstantAttribute;
+ if (attr != null)
+ {
+ foreach (CustomAttributeData cad in GetCustomAttributesData(attr))
+ {
+ IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
+ if (args.Count == 5)
+ {
+ if (args[0].ArgumentType == universe.System_Byte
+ && args[1].ArgumentType == universe.System_Byte
+ && args[2].ArgumentType == universe.System_Int32
+ && args[3].ArgumentType == universe.System_Int32
+ && args[4].ArgumentType == universe.System_Int32)
+ {
+ return new Decimal((int)args[4].Value, (int)args[3].Value, (int)args[2].Value, (byte)args[1].Value != 0, (byte)args[0].Value);
+ }
+ else if (args[0].ArgumentType == universe.System_Byte
+ && args[1].ArgumentType == universe.System_Byte
+ && args[2].ArgumentType == universe.System_UInt32
+ && args[3].ArgumentType == universe.System_UInt32
+ && args[4].ArgumentType == universe.System_UInt32)
+ {
+ return new Decimal(unchecked((int)(uint)args[4].Value), unchecked((int)(uint)args[3].Value), unchecked((int)(uint)args[2].Value), (byte)args[1].Value != 0, (byte)args[0].Value);
+ }
+ }
+ }
+ }
+ }
+ if ((this.Attributes & ParameterAttributes.Optional) != 0)
+ {
+ return Missing.Value;
+ }
+ return null;
+ }
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return Util.Copy(position == -1 ? method.MethodSignature.GetReturnTypeRequiredCustomModifiers(method) : method.MethodSignature.GetParameterRequiredCustomModifiers(method, position));
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return Util.Copy(position == -1 ? method.MethodSignature.GetReturnTypeOptionalCustomModifiers(method) : method.MethodSignature.GetParameterOptionalCustomModifiers(method, position));
+ }
+
+ public override MemberInfo Member
+ {
+ get
+ {
+ // return the right ConstructorInfo wrapper
+ return method.Module.ResolveMethod(method.MetadataToken);
+ }
+ }
+
+ public override int MetadataToken
+ {
+ get
+ {
+ // for parameters that don't have a row in the Param table, we return 0x08000000 (because index is -1 in that case),
+ // just like .NET
+ return (ParamTable.Index << 24) + index + 1;
+ }
+ }
+
+ internal override Module Module
+ {
+ get { return method.Module; }
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ IList<CustomAttributeData> list = base.GetCustomAttributesData(attributeType);
+ if ((this.Attributes & ParameterAttributes.HasFieldMarshal) != 0
+ && (attributeType == null || attributeType.IsAssignableFrom(this.Module.universe.System_Runtime_InteropServices_MarshalAsAttribute)))
+ {
+ list.Add(MarshalSpec.GetMarshalAsAttribute(this.Module, this.MetadataToken));
+ }
+ return list;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class StreamHeader
+ {
+ internal uint Offset;
+ internal uint Size;
+ internal string Name;
+
+ internal void Read(BinaryReader br)
+ {
+ Offset = br.ReadUInt32();
+ Size = br.ReadUInt32();
+ byte[] buf = new byte[32];
+ byte b;
+ int len = 0;
+ while ((b = br.ReadByte()) != 0)
+ {
+ buf[len++] = b;
+ }
+ Name = Encoding.UTF8.GetString(buf, 0, len); ;
+ int padding = -1 + ((len + 4) & ~3) - len;
+ br.BaseStream.Seek(padding, SeekOrigin.Current);
+ }
+ }
+
+ sealed class ModuleReader : Module
+ {
+ internal readonly Stream stream;
+ private readonly string location;
+ private Assembly assembly;
+ private readonly PEReader peFile = new PEReader();
+ private readonly CliHeader cliHeader = new CliHeader();
+ private string imageRuntimeVersion;
+ private int metadataStreamVersion;
+ private byte[] stringHeap;
+ private byte[] blobHeap;
+ private byte[] userStringHeap;
+ private byte[] guidHeap;
+ private TypeDefImpl[] typeDefs;
+ private TypeDefImpl moduleType;
+ private Assembly[] assemblyRefs;
+ private Type[] typeRefs;
+ private Type[] typeSpecs;
+ private FieldInfo[] fields;
+ private MethodBase[] methods;
+ private MemberInfo[] memberRefs;
+ private Dictionary<int, string> strings = new Dictionary<int, string>();
+ private Dictionary<string, Type> types = new Dictionary<string, Type>();
+ private Dictionary<string, LazyForwardedType> forwardedTypes = new Dictionary<string, LazyForwardedType>();
+
+ private sealed class LazyForwardedType
+ {
+ private readonly int assemblyRef;
+ private Type type;
+
+ internal LazyForwardedType(int assemblyRef)
+ {
+ this.assemblyRef = assemblyRef;
+ }
+
+ internal Type GetType(ModuleReader module, string typeName)
+ {
+ if (type == null)
+ {
+ Assembly asm = module.ResolveAssemblyRef(assemblyRef);
+ type = asm.GetType(typeName, true);
+ }
+ return type;
+ }
+ }
+
+ internal ModuleReader(AssemblyReader assembly, Universe universe, Stream stream, string location)
+ : base(universe)
+ {
+ this.stream = stream;
+ this.location = location;
+ Read();
+ if (assembly == null && AssemblyTable.records.Length != 0)
+ {
+ assembly = new AssemblyReader(location, this);
+ }
+ this.assembly = assembly;
+ }
+
+ private void Read()
+ {
+ BinaryReader br = new BinaryReader(stream);
+ peFile.Read(br);
+ stream.Seek(peFile.RvaToFileOffset(peFile.GetComDescriptorVirtualAddress()), SeekOrigin.Begin);
+ cliHeader.Read(br);
+ stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaDataRVA), SeekOrigin.Begin);
+ foreach (StreamHeader sh in ReadStreamHeaders(br, out imageRuntimeVersion))
+ {
+ switch (sh.Name)
+ {
+ case "#Strings":
+ stringHeap = ReadHeap(stream, sh);
+ break;
+ case "#Blob":
+ blobHeap = ReadHeap(stream, sh);
+ break;
+ case "#US":
+ userStringHeap = ReadHeap(stream, sh);
+ break;
+ case "#GUID":
+ guidHeap = ReadHeap(stream, sh);
+ break;
+ case "#~":
+ stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaDataRVA + sh.Offset), SeekOrigin.Begin);
+ ReadTables(br);
+ break;
+ default:
+ throw new BadImageFormatException("Unsupported stream: " + sh.Name);
+ }
+ }
+ }
+
+ internal void SetAssembly(Assembly assembly)
+ {
+ this.assembly = assembly;
+ }
+
+ private static StreamHeader[] ReadStreamHeaders(BinaryReader br, out string Version)
+ {
+ uint Signature = br.ReadUInt32();
+ if (Signature != 0x424A5342)
+ {
+ throw new BadImageFormatException("Invalid metadata signature");
+ }
+ ushort MajorVersion = br.ReadUInt16();
+ ushort MinorVersion = br.ReadUInt16();
+ uint Reserved = br.ReadUInt32();
+ uint Length = br.ReadUInt32();
+ byte[] buf = br.ReadBytes((int)Length);
+ Version = Encoding.UTF8.GetString(buf).TrimEnd('\u0000');
+ ushort Flags = br.ReadUInt16();
+ ushort Streams = br.ReadUInt16();
+ StreamHeader[] streamHeaders = new StreamHeader[Streams];
+ for (int i = 0; i < streamHeaders.Length; i++)
+ {
+ streamHeaders[i] = new StreamHeader();
+ streamHeaders[i].Read(br);
+ }
+ return streamHeaders;
+ }
+
+ private void ReadTables(BinaryReader br)
+ {
+ Table[] tables = GetTables();
+ uint Reserved0 = br.ReadUInt32();
+ byte MajorVersion = br.ReadByte();
+ byte MinorVersion = br.ReadByte();
+ metadataStreamVersion = MajorVersion << 16 | MinorVersion;
+ byte HeapSizes = br.ReadByte();
+ byte Reserved7 = br.ReadByte();
+ ulong Valid = br.ReadUInt64();
+ ulong Sorted = br.ReadUInt64();
+ for (int i = 0; i < 64; i++)
+ {
+ if ((Valid & (1UL << i)) != 0)
+ {
+ tables[i].RowCount = br.ReadInt32();
+ }
+ else if (tables[i] != null)
+ {
+ tables[i].RowCount = 0;
+ }
+ }
+ MetadataReader mr = new MetadataReader(this, br, HeapSizes);
+ for (int i = 0; i < 64; i++)
+ {
+ if ((Valid & (1UL << i)) != 0)
+ {
+ tables[i].Read(mr);
+ }
+ }
+ }
+
+ private byte[] ReadHeap(Stream stream, StreamHeader sh)
+ {
+ byte[] buf = new byte[sh.Size];
+ stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaDataRVA + sh.Offset), SeekOrigin.Begin);
+ for (int pos = 0; pos < buf.Length; )
+ {
+ int read = stream.Read(buf, pos, buf.Length - pos);
+ if (read == 0)
+ {
+ throw new BadImageFormatException();
+ }
+ pos += read;
+ }
+ return buf;
+ }
+
+ internal void SeekRVA(int rva)
+ {
+ stream.Seek(peFile.RvaToFileOffset((uint)rva), SeekOrigin.Begin);
+ }
+
+ internal override void GetTypesImpl(List<Type> list)
+ {
+ PopulateTypeDef();
+ foreach (TypeDefImpl type in typeDefs)
+ {
+ if (type != moduleType)
+ {
+ list.Add(type);
+ }
+ }
+ }
+
+ private void PopulateTypeDef()
+ {
+ if (typeDefs == null)
+ {
+ typeDefs = new TypeDefImpl[TypeDef.records.Length];
+ for (int i = 0; i < typeDefs.Length; i++)
+ {
+ TypeDefImpl type = new TypeDefImpl(this, i);
+ typeDefs[i] = type;
+ if (type.IsModulePseudoType)
+ {
+ moduleType = type;
+ }
+ else
+ {
+ types.Add(type.FullName, type);
+ }
+ }
+ // add forwarded types to forwardedTypes dictionary (because Module.GetType(string) should return them)
+ for (int i = 0; i < ExportedType.records.Length; i++)
+ {
+ int implementation = ExportedType.records[i].Implementation;
+ if (implementation >> 24 == AssemblyRefTable.Index)
+ {
+ string typeName = GetTypeName(ExportedType.records[i].TypeNamespace, ExportedType.records[i].TypeName);
+ forwardedTypes.Add(typeName, new LazyForwardedType((implementation & 0xFFFFFF) - 1));
+ }
+ }
+ }
+ }
+
+ internal string GetString(int index)
+ {
+ if (index == 0)
+ {
+ return null;
+ }
+ string str;
+ if (!strings.TryGetValue(index, out str))
+ {
+ int len = 0;
+ while (stringHeap[index + len] != 0)
+ {
+ len++;
+ }
+ str = Encoding.UTF8.GetString(stringHeap, index, len);
+ strings.Add(index, str);
+ }
+ return str;
+ }
+
+ private static int ReadCompressedInt(byte[] buffer, ref int offset)
+ {
+ byte b1 = buffer[offset++];
+ if (b1 <= 0x7F)
+ {
+ return b1;
+ }
+ else if ((b1 & 0xC0) == 0x80)
+ {
+ byte b2 = buffer[offset++];
+ return ((b1 & 0x3F) << 8) | b2;
+ }
+ else
+ {
+ byte b2 = buffer[offset++];
+ byte b3 = buffer[offset++];
+ byte b4 = buffer[offset++];
+ return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
+ }
+ }
+
+ internal byte[] GetBlobCopy(int blobIndex)
+ {
+ int len = ReadCompressedInt(blobHeap, ref blobIndex);
+ byte[] buf = new byte[len];
+ Buffer.BlockCopy(blobHeap, blobIndex, buf, 0, len);
+ return buf;
+ }
+
+ internal override ByteReader GetBlob(int blobIndex)
+ {
+ return ByteReader.FromBlob(blobHeap, blobIndex);
+ }
+
+ public override string ResolveString(int metadataToken)
+ {
+ string str;
+ if (!strings.TryGetValue(metadataToken, out str))
+ {
+ if ((metadataToken >> 24) != 0x70)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+ int index = metadataToken & 0xFFFFFF;
+ int len = ReadCompressedInt(userStringHeap, ref index) & ~1;
+ str = Encoding.Unicode.GetString(userStringHeap, index, len);
+ strings.Add(metadataToken, str);
+ }
+ return str;
+ }
+
+ internal Type ResolveType(int metadataToken, IGenericContext context)
+ {
+ switch (metadataToken >> 24)
+ {
+ case TypeDefTable.Index:
+ PopulateTypeDef();
+ return typeDefs[(metadataToken & 0xFFFFFF) - 1];
+ case TypeRefTable.Index:
+ {
+ if (typeRefs == null)
+ {
+ typeRefs = new Type[TypeRef.records.Length];
+ }
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ if (typeRefs[index] == null)
+ {
+ int scope = TypeRef.records[index].ResolutionScope;
+ switch (scope >> 24)
+ {
+ case AssemblyRefTable.Index:
+ {
+ Assembly assembly = ResolveAssemblyRef((scope & 0xFFFFFF) - 1);
+ string typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
+ Type type = assembly.GetType(typeName);
+ if (type == null)
+ {
+ throw new TypeLoadException(String.Format("Type '{0}' not found in assembly '{1}'", typeName, assembly.FullName));
+ }
+ typeRefs[index] = type;
+ break;
+ }
+ case TypeRefTable.Index:
+ {
+ Type outer = ResolveType(scope, null);
+ typeRefs[index] = outer.GetNestedType(GetString(TypeRef.records[index].TypeName), BindingFlags.Public | BindingFlags.NonPublic);
+ break;
+ }
+ case ModuleTable.Index:
+ if (scope != 0 && scope != 1)
+ {
+ throw new NotImplementedException("self reference scope?");
+ }
+ typeRefs[index] = GetType(GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName));
+ break;
+ case ModuleRefTable.Index:
+ {
+ Module module = ResolveModuleRef(ModuleRef.records[(scope & 0xFFFFFF) - 1]);
+ string typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
+ Type type = assembly.GetType(typeName);
+ if (type == null)
+ {
+ throw new TypeLoadException(String.Format("Type '{0}' not found in module '{1}'", typeName, module.Name));
+ }
+ typeRefs[index] = type;
+ break;
+ }
+ default:
+ throw new NotImplementedException("ResolutionScope = " + scope.ToString("X"));
+ }
+ }
+ return typeRefs[index];
+ }
+ case TypeSpecTable.Index:
+ {
+ if (typeSpecs == null)
+ {
+ typeSpecs = new Type[TypeSpec.records.Length];
+ }
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ Type type = typeSpecs[index];
+ if (type == null)
+ {
+ TrackingGenericContext tc = context == null ? null : new TrackingGenericContext(context);
+ type = Signature.ReadTypeSpec(this, ByteReader.FromBlob(blobHeap, TypeSpec.records[index]), tc);
+ if (tc == null || !tc.IsUsed)
+ {
+ typeSpecs[index] = type;
+ }
+ }
+ return type;
+ }
+ default:
+ throw new NotImplementedException(String.Format("0x{0:X}", metadataToken));
+ }
+ }
+
+ private Module ResolveModuleRef(int moduleNameIndex)
+ {
+ string moduleName = GetString(moduleNameIndex);
+ Module module = assembly.GetModule(moduleName);
+ if (module == null)
+ {
+ throw new FileNotFoundException(moduleName);
+ }
+ return module;
+ }
+
+ private sealed class TrackingGenericContext : IGenericContext
+ {
+ private readonly IGenericContext context;
+ private bool used;
+
+ internal TrackingGenericContext(IGenericContext context)
+ {
+ this.context = context;
+ }
+
+ internal bool IsUsed
+ {
+ get { return used; }
+ }
+
+ public Type GetGenericTypeArgument(int index)
+ {
+ used = true;
+ return context.GetGenericTypeArgument(index);
+ }
+
+ public Type GetGenericMethodArgument(int index)
+ {
+ used = true;
+ return context.GetGenericMethodArgument(index);
+ }
+ }
+
+ public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ if ((metadataToken >> 24) == TypeSpecTable.Index)
+ {
+ return ResolveType(metadataToken, new GenericContext(genericTypeArguments, genericMethodArguments));
+ }
+ else
+ {
+ return ResolveType(metadataToken, null);
+ }
+ }
+
+ private string GetTypeName(int typeNamespace, int typeName)
+ {
+ if (typeNamespace == 0)
+ {
+ return GetString(typeName);
+ }
+ else
+ {
+ return GetString(typeNamespace) + "." + GetString(typeName);
+ }
+ }
+
+ private Assembly ResolveAssemblyRef(int index)
+ {
+ if (assemblyRefs == null)
+ {
+ assemblyRefs = new Assembly[AssemblyRef.RowCount];
+ }
+ if (assemblyRefs[index] == null)
+ {
+ assemblyRefs[index] = ResolveAssemblyRefImpl(ref AssemblyRef.records[index]);
+ }
+ return assemblyRefs[index];
+ }
+
+ private Assembly ResolveAssemblyRefImpl(ref AssemblyRefTable.Record rec)
+ {
+ const int PublicKey = 0x0001;
+ string name = String.Format("{0}, Version={1}.{2}.{3}.{4}, Culture={5}, {6}={7}",
+ GetString(rec.Name),
+ rec.MajorVersion,
+ rec.MinorVersion,
+ rec.BuildNumber,
+ rec.RevisionNumber,
+ rec.Culture == 0 ? "neutral" : GetString(rec.Culture),
+ (rec.Flags & PublicKey) == 0 ? "PublicKeyToken" : "PublicKey",
+ PublicKeyOrTokenToString(rec.PublicKeyOrToken));
+ return universe.Load(name, this.Assembly, true);
+ }
+
+ private string PublicKeyOrTokenToString(int publicKeyOrToken)
+ {
+ if (publicKeyOrToken == 0)
+ {
+ return "null";
+ }
+ ByteReader br = GetBlob(publicKeyOrToken);
+ if (br.Length == 0)
+ {
+ return "null";
+ }
+ StringBuilder sb = new StringBuilder(br.Length * 2);
+ while (br.Length > 0)
+ {
+ sb.AppendFormat("{0:x2}", br.ReadByte());
+ }
+ return sb.ToString();
+ }
+
+ public override Guid ModuleVersionId
+ {
+ get
+ {
+ byte[] buf = new byte[16];
+ Buffer.BlockCopy(guidHeap, 16 * (ModuleTable.records[0].Mvid - 1), buf, 0, 16);
+ return new Guid(buf);
+ }
+ }
+
+ public override string FullyQualifiedName
+ {
+ get { return location ?? "<Unknown>"; }
+ }
+
+ public override string Name
+ {
+ get { return location == null ? "<Unknown>" : System.IO.Path.GetFileName(location); }
+ }
+
+ public override Assembly Assembly
+ {
+ get { return assembly; }
+ }
+
+ internal override Type GetTypeImpl(string typeName)
+ {
+ PopulateTypeDef();
+ Type type;
+ if (!types.TryGetValue(typeName, out type))
+ {
+ LazyForwardedType fw;
+ if (forwardedTypes.TryGetValue(typeName, out fw))
+ {
+ return fw.GetType(this, typeName);
+ }
+ }
+ return type;
+ }
+
+ public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ switch (metadataToken >> 24)
+ {
+ case FieldTable.Index:
+ return ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
+ case MemberRefTable.Index:
+ return GetMemberRef((metadataToken & 0xFFFFFF) - 1, genericTypeArguments, genericMethodArguments);
+ case MethodDefTable.Index:
+ case MethodSpecTable.Index:
+ return ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+
+ internal FieldInfo GetFieldAt(TypeDefImpl owner, int index)
+ {
+ if (fields == null)
+ {
+ fields = new FieldInfo[Field.records.Length];
+ }
+ if (fields[index] == null)
+ {
+ fields[index] = new FieldDefImpl(this, owner ?? FindFieldOwner(index), index);
+ }
+ return fields[index];
+ }
+
+ public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ if ((metadataToken >> 24) == FieldTable.Index)
+ {
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ return GetFieldAt(null, index);
+ }
+ else if ((metadataToken >> 24) == MemberRefTable.Index)
+ {
+ FieldInfo field = GetMemberRef((metadataToken & 0xFFFFFF) - 1, genericTypeArguments, genericMethodArguments) as FieldInfo;
+ if (field != null)
+ {
+ return field;
+ }
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+
+ private TypeDefImpl FindFieldOwner(int fieldIndex)
+ {
+ // TODO use binary search?
+ for (int i = 0; i < TypeDef.records.Length; i++)
+ {
+ int field = TypeDef.records[i].FieldList - 1;
+ int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].FieldList - 1 : Field.records.Length;
+ if (field <= fieldIndex && fieldIndex < end)
+ {
+ PopulateTypeDef();
+ return typeDefs[i];
+ }
+ }
+ throw new InvalidOperationException();
+ }
+
+ internal MethodBase GetMethodAt(TypeDefImpl owner, int index)
+ {
+ if (methods == null)
+ {
+ methods = new MethodBase[MethodDef.records.Length];
+ }
+ if (methods[index] == null)
+ {
+ MethodDefImpl method = new MethodDefImpl(this, owner ?? FindMethodOwner(index), index);
+ methods[index] = method.IsConstructor ? new ConstructorInfoImpl(method) : (MethodBase)method;
+ }
+ return methods[index];
+ }
+
+ private sealed class GenericContext : IGenericContext
+ {
+ private readonly Type[] genericTypeArguments;
+ private readonly Type[] genericMethodArguments;
+
+ internal GenericContext(Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ this.genericTypeArguments = genericTypeArguments;
+ this.genericMethodArguments = genericMethodArguments;
+ }
+
+ public Type GetGenericTypeArgument(int index)
+ {
+ return genericTypeArguments[index];
+ }
+
+ public Type GetGenericMethodArgument(int index)
+ {
+ return genericMethodArguments[index];
+ }
+ }
+
+ public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ if ((metadataToken >> 24) == MethodDefTable.Index)
+ {
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ return GetMethodAt(null, index);
+ }
+ else if ((metadataToken >> 24) == MemberRefTable.Index)
+ {
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ MethodBase method = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as MethodBase;
+ if (method != null)
+ {
+ return method;
+ }
+ }
+ else if ((metadataToken >> 24) == MethodSpecTable.Index)
+ {
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ MethodInfo method = (MethodInfo)ResolveMethod(MethodSpec.records[index].Method, genericTypeArguments, genericMethodArguments);
+ ByteReader instantiation = ByteReader.FromBlob(blobHeap, MethodSpec.records[index].Instantiation);
+ return method.MakeGenericMethod(Signature.ReadMethodSpec(this, instantiation, new GenericContext(genericTypeArguments, genericMethodArguments)));
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+
+ public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+ {
+ if ((metadataToken >> 24) == MemberRefTable.Index)
+ {
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ int sig = MemberRef.records[index].Signature;
+ return Signature.ReadOptionalParameterTypes(this, GetBlob(sig));
+ }
+ else if ((metadataToken >> 24) == MethodDefTable.Index)
+ {
+ // for convenience, we support passing a MethodDef token as well, because in some places
+ // it makes sense to have a vararg method that is referred to by its methoddef (e.g. ldftn).
+ // Note that MethodSpec doesn't make sense, because generic methods cannot be vararg.
+ return Type.EmptyTypes;
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+
+ public override string ScopeName
+ {
+ get { return GetString(ModuleTable.records[0].Name); }
+ }
+
+ private TypeDefImpl FindMethodOwner(int methodIndex)
+ {
+ // TODO use binary search?
+ for (int i = 0; i < TypeDef.records.Length; i++)
+ {
+ int method = TypeDef.records[i].MethodList - 1;
+ int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].MethodList - 1 : MethodDef.records.Length;
+ if (method <= methodIndex && methodIndex < end)
+ {
+ PopulateTypeDef();
+ return typeDefs[i];
+ }
+ }
+ throw new InvalidOperationException();
+ }
+
+ private MemberInfo GetMemberRef(int index, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ if (memberRefs == null)
+ {
+ memberRefs = new MemberInfo[MemberRef.records.Length];
+ }
+ if (memberRefs[index] == null)
+ {
+ int owner = MemberRef.records[index].Class;
+ int sig = MemberRef.records[index].Signature;
+ string name = GetString(MemberRef.records[index].Name);
+ switch (owner >> 24)
+ {
+ case MethodDefTable.Index:
+ return GetMethodAt(null, (owner & 0xFFFFFF) - 1);
+ case ModuleRefTable.Index:
+ memberRefs[index] = ResolveTypeMemberRef(ResolveModuleType(owner), name, ByteReader.FromBlob(blobHeap, sig), genericTypeArguments, genericMethodArguments);
+ break;
+ case TypeDefTable.Index:
+ case TypeRefTable.Index:
+ memberRefs[index] = ResolveTypeMemberRef(ResolveType(owner), name, ByteReader.FromBlob(blobHeap, sig), genericTypeArguments, genericMethodArguments);
+ break;
+ case TypeSpecTable.Index:
+ return ResolveTypeMemberRef(ResolveType(owner, genericTypeArguments, genericMethodArguments), name, ByteReader.FromBlob(blobHeap, sig), genericTypeArguments, genericMethodArguments);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+ return memberRefs[index];
+ }
+
+ private Type ResolveModuleType(int token)
+ {
+ int index = (token & 0xFFFFFF) - 1;
+ string name = GetString(ModuleRef.records[index]);
+ Module module = assembly.GetModule(name);
+ if (module == null || module.IsResource())
+ {
+ throw new BadImageFormatException();
+ }
+ return module.GetModuleType();
+ }
+
+ private MemberInfo ResolveTypeMemberRef(Type type, string name, ByteReader sig, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ IGenericContext context;
+ if ((genericTypeArguments == null && genericMethodArguments == null) || type.IsGenericType)
+ {
+ context = type;
+ }
+ else
+ {
+ context = new GenericContext(genericTypeArguments, genericMethodArguments);
+ }
+ if (sig.PeekByte() == Signature.FIELD)
+ {
+ Type org = type;
+ FieldSignature fieldSig = FieldSignature.ReadSig(this, sig, context);
+ do
+ {
+ FieldInfo field = type.FindField(name, fieldSig);
+ if (field != null)
+ {
+ return field;
+ }
+ type = type.BaseType;
+ } while (type != null);
+ throw new MissingFieldException(org.ToString(), name);
+ }
+ else
+ {
+ Type org = type;
+ MethodSignature methodSig = MethodSignature.ReadSig(this, sig, context);
+ do
+ {
+ MethodBase method = type.FindMethod(name, methodSig);
+ if (method != null)
+ {
+ return method;
+ }
+ type = type.BaseType;
+ } while (type != null);
+ throw new MissingMethodException(org.ToString(), name);
+ }
+ }
+
+ internal new ByteReader ResolveSignature(int metadataToken)
+ {
+ if ((metadataToken >> 24) == StandAloneSigTable.Index)
+ {
+ int index = (metadataToken & 0xFFFFFF) - 1;
+ return ByteReader.FromBlob(blobHeap, StandAloneSig.records[index]);
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+
+ public override __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ return MethodSignature.ReadStandAloneMethodSig(this, ResolveSignature(metadataToken), new GenericContext(genericTypeArguments, genericMethodArguments));
+ }
+
+ internal MethodInfo GetEntryPoint()
+ {
+ if (cliHeader.EntryPointToken != 0 && (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0)
+ {
+ return (MethodInfo)ResolveMethod((int)cliHeader.EntryPointToken);
+ }
+ return null;
+ }
+
+ internal string[] GetManifestResourceNames()
+ {
+ string[] names = new string[ManifestResource.records.Length];
+ for (int i = 0; i < ManifestResource.records.Length; i++)
+ {
+ names[i] = GetString(ManifestResource.records[i].Name);
+ }
+ return names;
+ }
+
+ internal ManifestResourceInfo GetManifestResourceInfo(string resourceName)
+ {
+ for (int i = 0; i < ManifestResource.records.Length; i++)
+ {
+ if (resourceName == GetString(ManifestResource.records[i].Name))
+ {
+ return new ManifestResourceInfo(this, i);
+ }
+ }
+ return null;
+ }
+
+ internal Stream GetManifestResourceStream(string resourceName)
+ {
+ for (int i = 0; i < ManifestResource.records.Length; i++)
+ {
+ if (resourceName == GetString(ManifestResource.records[i].Name))
+ {
+ if (ManifestResource.records[i].Implementation != 0x26000000)
+ {
+ throw new NotImplementedException();
+ }
+ SeekRVA((int)cliHeader.ResourcesRVA + ManifestResource.records[i].Offset);
+ BinaryReader br = new BinaryReader(stream);
+ int length = br.ReadInt32();
+ return new MemoryStream(br.ReadBytes(length));
+ }
+ }
+ throw new FileNotFoundException();
+ }
+
+ public override AssemblyName[] __GetReferencedAssemblies()
+ {
+ List<AssemblyName> list = new List<AssemblyName>();
+ for (int i = 0; i < AssemblyRef.records.Length; i++)
+ {
+ AssemblyName name = new AssemblyName();
+ name.Name = GetString(AssemblyRef.records[i].Name);
+ name.Version = new Version(
+ AssemblyRef.records[i].MajorVersion,
+ AssemblyRef.records[i].MinorVersion,
+ AssemblyRef.records[i].BuildNumber,
+ AssemblyRef.records[i].RevisionNumber);
+ if (AssemblyRef.records[i].PublicKeyOrToken != 0)
+ {
+ byte[] keyOrToken = GetBlobCopy(AssemblyRef.records[i].PublicKeyOrToken);
+ const int PublicKey = 0x0001;
+ if ((AssemblyRef.records[i].Flags & PublicKey) != 0)
+ {
+ name.SetPublicKey(keyOrToken);
+ }
+ else
+ {
+ name.SetPublicKeyToken(keyOrToken);
+ }
+ }
+ if (AssemblyRef.records[i].Culture != 0)
+ {
+ name.CultureInfo = new System.Globalization.CultureInfo(GetString(AssemblyRef.records[i].Culture));
+ }
+ else
+ {
+ name.CultureInfo = System.Globalization.CultureInfo.InvariantCulture;
+ }
+ name.Flags = (AssemblyNameFlags)AssemblyRef.records[i].Flags;
+ list.Add(name);
+ }
+ return list.ToArray();
+ }
+
+ internal override Type GetModuleType()
+ {
+ PopulateTypeDef();
+ return moduleType;
+ }
+
+ internal string ImageRuntimeVersion
+ {
+ get { return imageRuntimeVersion; }
+ }
+
+ public override int MDStreamVersion
+ {
+ get { return metadataStreamVersion; }
+ }
+
+ public override void __GetDataDirectoryEntry(int index, out int rva, out int length)
+ {
+ peFile.GetDataDirectoryEntry(index, out rva, out length);
+ }
+
+ public override long __RelativeVirtualAddressToFileOffset(int rva)
+ {
+ return peFile.RvaToFileOffset((uint)rva);
+ }
+
+ public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
+ {
+ peKind = 0;
+ if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_ILONLY) != 0)
+ {
+ peKind |= PortableExecutableKinds.ILOnly;
+ }
+ if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_32BITREQUIRED) != 0)
+ {
+ peKind |= PortableExecutableKinds.Required32Bit;
+ }
+ if (peFile.OptionalHeader.Magic == IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ {
+ peKind |= PortableExecutableKinds.PE32Plus;
+ }
+
+ machine = (ImageFileMachine)peFile.FileHeader.Machine;
+ }
+
+ public override int __Subsystem
+ {
+ get { return peFile.OptionalHeader.Subsystem; }
+ }
+
+ public override IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
+ {
+ string typeName;
+ switch ((multiple ? 1 : 0) + (security ? 2 : 0))
+ {
+ case 0:
+ typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHere";
+ break;
+ case 1:
+ typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHereM";
+ break;
+ case 2:
+ typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHereS";
+ break;
+ case 3:
+ default:
+ typeName = "System.Runtime.CompilerServices.AssemblyAttributesGoHereSM";
+ break;
+ }
+ List<CustomAttributeData> list = new List<CustomAttributeData>();
+ for (int i = 0; i < CustomAttribute.records.Length; i++)
+ {
+ if ((CustomAttribute.records[i].Parent >> 24) == TypeRefTable.Index)
+ {
+ int index = (CustomAttribute.records[i].Parent & 0xFFFFFF) - 1;
+ if (typeName == GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName))
+ {
+ ConstructorInfo constructor = (ConstructorInfo)ResolveMethod(CustomAttribute.records[i].Type);
+ list.Add(new CustomAttributeData(this.Assembly, constructor, GetBlob(CustomAttribute.records[i].Value)));
+ }
+ }
+ }
+ return list;
+ }
+
+ internal override void Dispose()
+ {
+ stream.Close();
+ }
+
+ internal override void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
+ {
+ PopulateTypeDef();
+ manifestModule.ExportTypes(typeDefs, fileToken);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using BYTE = System.Byte;
+using WORD = System.UInt16;
+using DWORD = System.UInt32;
+using ULONGLONG = System.UInt64;
+using System.IO;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class MSDOS_HEADER
+ {
+ internal const WORD MAGIC_MZ = 0x5A4D;
+
+ internal WORD signature; // 'MZ'
+ // skip 58 bytes
+ internal DWORD peSignatureOffset;
+ }
+
+ sealed class IMAGE_NT_HEADERS
+ {
+ public const DWORD MAGIC_SIGNATURE = 0x00004550; // "PE\0\0"
+
+ public DWORD Signature;
+ public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
+ public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
+
+ internal void Read(BinaryReader br)
+ {
+ Signature = br.ReadUInt32();
+ if (Signature != IMAGE_NT_HEADERS.MAGIC_SIGNATURE)
+ {
+ throw new BadImageFormatException();
+ }
+ FileHeader.Read(br);
+ OptionalHeader.Read(br);
+ }
+ }
+
+ sealed class IMAGE_FILE_HEADER
+ {
+ public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
+ public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
+ public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
+
+ public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
+ public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
+ public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
+ public const WORD IMAGE_FILE_DLL = 0x2000;
+
+ public WORD Machine;
+ public WORD NumberOfSections;
+ public DWORD TimeDateStamp;
+ public DWORD PointerToSymbolTable;
+ public DWORD NumberOfSymbols;
+ public WORD SizeOfOptionalHeader;
+ public WORD Characteristics;
+
+ internal void Read(BinaryReader br)
+ {
+ Machine = br.ReadUInt16();
+ NumberOfSections = br.ReadUInt16();
+ TimeDateStamp = br.ReadUInt32();
+ PointerToSymbolTable = br.ReadUInt32();
+ NumberOfSymbols = br.ReadUInt32();
+ SizeOfOptionalHeader = br.ReadUInt16();
+ Characteristics = br.ReadUInt16();
+ }
+ }
+
+ sealed class IMAGE_OPTIONAL_HEADER
+ {
+ public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
+ public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
+
+ public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
+ public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
+
+ public const WORD IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040;
+ public const WORD IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100;
+ public const WORD IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400;
+ public const WORD IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000;
+
+ public WORD Magic;
+ public BYTE MajorLinkerVersion;
+ public BYTE MinorLinkerVersion;
+ public DWORD SizeOfCode;
+ public DWORD SizeOfInitializedData;
+ public DWORD SizeOfUninitializedData;
+ public DWORD AddressOfEntryPoint;
+ public DWORD BaseOfCode;
+ public DWORD BaseOfData;
+ public ULONGLONG ImageBase;
+ public DWORD SectionAlignment;
+ public DWORD FileAlignment;
+ public WORD MajorOperatingSystemVersion;
+ public WORD MinorOperatingSystemVersion;
+ public WORD MajorImageVersion;
+ public WORD MinorImageVersion;
+ public WORD MajorSubsystemVersion;
+ public WORD MinorSubsystemVersion;
+ public DWORD Win32VersionValue;
+ public DWORD SizeOfImage;
+ public DWORD SizeOfHeaders;
+ public DWORD CheckSum;
+ public WORD Subsystem;
+ public WORD DllCharacteristics;
+ public ULONGLONG SizeOfStackReserve;
+ public ULONGLONG SizeOfStackCommit;
+ public ULONGLONG SizeOfHeapReserve;
+ public ULONGLONG SizeOfHeapCommit;
+ public DWORD LoaderFlags;
+ public DWORD NumberOfRvaAndSizes;
+ public IMAGE_DATA_DIRECTORY[] DataDirectory;
+
+ internal void Read(BinaryReader br)
+ {
+ Magic = br.ReadUInt16();
+ if (Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ {
+ throw new BadImageFormatException();
+ }
+ MajorLinkerVersion = br.ReadByte();
+ MinorLinkerVersion = br.ReadByte();
+ SizeOfCode = br.ReadUInt32();
+ SizeOfInitializedData = br.ReadUInt32();
+ SizeOfUninitializedData = br.ReadUInt32();
+ AddressOfEntryPoint = br.ReadUInt32();
+ BaseOfCode = br.ReadUInt32();
+ if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ BaseOfData = br.ReadUInt32();
+ ImageBase = br.ReadUInt32();
+ }
+ else
+ {
+ ImageBase = br.ReadUInt64();
+ }
+ SectionAlignment = br.ReadUInt32();
+ FileAlignment = br.ReadUInt32();
+ MajorOperatingSystemVersion = br.ReadUInt16();
+ MinorOperatingSystemVersion = br.ReadUInt16();
+ MajorImageVersion = br.ReadUInt16();
+ MinorImageVersion = br.ReadUInt16();
+ MajorSubsystemVersion = br.ReadUInt16();
+ MinorSubsystemVersion = br.ReadUInt16();
+ Win32VersionValue = br.ReadUInt32();
+ SizeOfImage = br.ReadUInt32();
+ SizeOfHeaders = br.ReadUInt32();
+ CheckSum = br.ReadUInt32();
+ Subsystem = br.ReadUInt16();
+ DllCharacteristics = br.ReadUInt16();
+ if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ SizeOfStackReserve = br.ReadUInt32();
+ SizeOfStackCommit = br.ReadUInt32();
+ SizeOfHeapReserve = br.ReadUInt32();
+ SizeOfHeapCommit = br.ReadUInt32();
+ }
+ else
+ {
+ SizeOfStackReserve = br.ReadUInt64();
+ SizeOfStackCommit = br.ReadUInt64();
+ SizeOfHeapReserve = br.ReadUInt64();
+ SizeOfHeapCommit = br.ReadUInt64();
+ }
+ LoaderFlags = br.ReadUInt32();
+ NumberOfRvaAndSizes = br.ReadUInt32();
+ DataDirectory = new IMAGE_DATA_DIRECTORY[NumberOfRvaAndSizes];
+ for (uint i = 0; i < NumberOfRvaAndSizes; i++)
+ {
+ DataDirectory[i] = new IMAGE_DATA_DIRECTORY();
+ DataDirectory[i].Read(br);
+ }
+ }
+ }
+
+ struct IMAGE_DATA_DIRECTORY
+ {
+ public DWORD VirtualAddress;
+ public DWORD Size;
+
+ internal void Read(BinaryReader br)
+ {
+ VirtualAddress = br.ReadUInt32();
+ Size = br.ReadUInt32();
+ }
+ }
+
+ class SectionHeader
+ {
+ public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
+ public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
+ public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
+ public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
+ public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
+ public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
+
+ public string Name; // 8 byte UTF8 encoded 0-padded
+ public DWORD VirtualSize;
+ public DWORD VirtualAddress;
+ public DWORD SizeOfRawData;
+ public DWORD PointerToRawData;
+ public DWORD PointerToRelocations;
+ public DWORD PointerToLinenumbers;
+ public WORD NumberOfRelocations;
+ public WORD NumberOfLinenumbers;
+ public DWORD Characteristics;
+
+ internal void Read(BinaryReader br)
+ {
+ char[] name = new char[8];
+ int len = 8;
+ for (int i = 0; i < 8; i++)
+ {
+ byte b = br.ReadByte();
+ name[i] = (char)b;
+ if (b == 0 && len == 8)
+ {
+ len = i;
+ }
+ }
+ Name = new String(name, 0, len);
+ VirtualSize = br.ReadUInt32();
+ VirtualAddress = br.ReadUInt32();
+ SizeOfRawData = br.ReadUInt32();
+ PointerToRawData = br.ReadUInt32();
+ PointerToRelocations = br.ReadUInt32();
+ PointerToLinenumbers = br.ReadUInt32();
+ NumberOfRelocations = br.ReadUInt16();
+ NumberOfLinenumbers = br.ReadUInt16();
+ Characteristics = br.ReadUInt32();
+ }
+ }
+
+ sealed class PEReader
+ {
+ private MSDOS_HEADER msdos = new MSDOS_HEADER();
+ private IMAGE_NT_HEADERS headers = new IMAGE_NT_HEADERS();
+ private SectionHeader[] sections;
+
+ internal void Read(BinaryReader br)
+ {
+ msdos.signature = br.ReadUInt16();
+ br.BaseStream.Seek(58, SeekOrigin.Current);
+ msdos.peSignatureOffset = br.ReadUInt32();
+
+ if (msdos.signature != MSDOS_HEADER.MAGIC_MZ)
+ {
+ throw new BadImageFormatException();
+ }
+
+ br.BaseStream.Seek(msdos.peSignatureOffset, SeekOrigin.Begin);
+ headers.Read(br);
+ sections = new SectionHeader[headers.FileHeader.NumberOfSections];
+ for (int i = 0; i < sections.Length; i++)
+ {
+ sections[i] = new SectionHeader();
+ sections[i].Read(br);
+ }
+ }
+
+ internal IMAGE_FILE_HEADER FileHeader
+ {
+ get { return headers.FileHeader; }
+ }
+
+ internal IMAGE_OPTIONAL_HEADER OptionalHeader
+ {
+ get { return headers.OptionalHeader; }
+ }
+
+ internal DWORD GetComDescriptorVirtualAddress()
+ {
+ return headers.OptionalHeader.DataDirectory[14].VirtualAddress;
+ }
+
+ internal void GetDataDirectoryEntry(int index, out int rva, out int length)
+ {
+ rva = (int)headers.OptionalHeader.DataDirectory[index].VirtualAddress;
+ length = (int)headers.OptionalHeader.DataDirectory[index].Size;
+ }
+
+ internal long RvaToFileOffset(DWORD rva)
+ {
+ for (int i = 0; i < sections.Length; i++)
+ {
+ if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize)
+ {
+ return sections[i].PointerToRawData + rva - sections[i].VirtualAddress;
+ }
+ }
+ throw new BadImageFormatException();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class PropertyInfoImpl : PropertyInfo
+ {
+ private readonly ModuleReader module;
+ private readonly Type declaringType;
+ private readonly int index;
+ private PropertySignature sig;
+ private bool isPublic;
+ private bool isStatic;
+ private bool flagsCached;
+
+ internal PropertyInfoImpl(ModuleReader module, Type declaringType, int index)
+ {
+ this.module = module;
+ this.declaringType = declaringType;
+ this.index = index;
+ }
+
+ public override bool Equals(object obj)
+ {
+ PropertyInfoImpl other = obj as PropertyInfoImpl;
+ return other != null && other.DeclaringType == declaringType && other.index == index;
+ }
+
+ public override int GetHashCode()
+ {
+ return declaringType.GetHashCode() * 77 + index;
+ }
+
+ internal override PropertySignature PropertySignature
+ {
+ get
+ {
+ if (sig == null)
+ {
+ sig = PropertySignature.ReadSig(module, module.GetBlob(module.Property.records[index].Type), declaringType);
+ }
+ return sig;
+ }
+ }
+
+ public override PropertyAttributes Attributes
+ {
+ get { return (PropertyAttributes)module.Property.records[index].Flags; }
+ }
+
+ public override object GetRawConstantValue()
+ {
+ return module.Constant.GetRawConstantValue(module, this.MetadataToken);
+ }
+
+ public override bool CanRead
+ {
+ get { return GetGetMethod(true) != null; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return GetSetMethod(true) != null; }
+ }
+
+ public override MethodInfo GetGetMethod(bool nonPublic)
+ {
+ return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Getter);
+ }
+
+ public override MethodInfo GetSetMethod(bool nonPublic)
+ {
+ return module.MethodSemantics.GetMethod(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Setter);
+ }
+
+ public override MethodInfo[] GetAccessors(bool nonPublic)
+ {
+ return module.MethodSemantics.GetMethods(module, this.MetadataToken, nonPublic, MethodSemanticsTable.Getter | MethodSemanticsTable.Setter | MethodSemanticsTable.Other);
+ }
+
+ public override Type DeclaringType
+ {
+ get { return declaringType; }
+ }
+
+ public override Module Module
+ {
+ get { return module; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return (PropertyTable.Index << 24) + index + 1; }
+ }
+
+ public override string Name
+ {
+ get { return module.GetString(module.Property.records[index].Name); }
+ }
+
+ internal override bool IsPublic
+ {
+ get
+ {
+ if (!flagsCached)
+ {
+ ComputeFlags();
+ }
+ return isPublic;
+ }
+ }
+
+ internal override bool IsStatic
+ {
+ get
+ {
+ if (!flagsCached)
+ {
+ ComputeFlags();
+ }
+ return isStatic;
+ }
+ }
+
+ private void ComputeFlags()
+ {
+ module.MethodSemantics.ComputeFlags(module, this.MetadataToken, out isPublic, out isStatic);
+ flagsCached = true;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class ResourceModule : Module
+ {
+ private readonly Assembly assembly;
+ private readonly string scopeName;
+ private readonly string location;
+
+ internal ResourceModule(Assembly assembly, string scopeName, string location)
+ : base(assembly.universe)
+ {
+ this.assembly = assembly;
+ this.scopeName = scopeName;
+ this.location = location;
+ }
+
+ public override int MDStreamVersion
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override bool IsResource()
+ {
+ return true;
+ }
+
+ public override Assembly Assembly
+ {
+ get { return assembly; }
+ }
+
+ public override string FullyQualifiedName
+ {
+ get { return location ?? "<Unknown>"; }
+ }
+
+ public override string Name
+ {
+ get { return location == null ? "<Unknown>" : System.IO.Path.GetFileName(location); }
+ }
+
+ public override string ScopeName
+ {
+ get { return scopeName; }
+ }
+
+ public override Guid ModuleVersionId
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override string ResolveString(int metadataToken)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override AssemblyName[] __GetReferencedAssemblies()
+ {
+ throw new NotSupportedException();
+ }
+
+ internal override Type GetTypeImpl(string typeName)
+ {
+ return null;
+ }
+
+ internal override void GetTypesImpl(List<Type> list)
+ {
+ }
+
+ internal override Type GetModuleType()
+ {
+ throw new InvalidOperationException();
+ }
+
+ internal override ByteReader GetBlob(int blobIndex)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Reader
+{
+ sealed class TypeDefImpl : Type
+ {
+ private readonly ModuleReader module;
+ private readonly int index;
+ private readonly string typeName;
+ private readonly string typeNamespace;
+ private Type[] typeArgs;
+
+ internal TypeDefImpl(ModuleReader module, int index)
+ {
+ this.module = module;
+ this.index = index;
+ this.typeName = TypeNameParser.Escape(module.GetString(module.TypeDef.records[index].TypeName));
+ this.typeNamespace = TypeNameParser.Escape(module.GetString(module.TypeDef.records[index].TypeNamespace));
+ }
+
+ public override Type BaseType
+ {
+ get
+ {
+ int extends = module.TypeDef.records[index].Extends;
+ if ((extends & 0xFFFFFF) == 0)
+ {
+ return null;
+ }
+ return module.ResolveType(extends, this);
+ }
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return (TypeAttributes)module.TypeDef.records[index].Flags; }
+ }
+
+ public override EventInfo[] __GetDeclaredEvents()
+ {
+ int token = this.MetadataToken;
+ // TODO use binary search?
+ for (int i = 0; i < module.EventMap.records.Length; i++)
+ {
+ if (module.EventMap.records[i].Parent == token)
+ {
+ int evt = module.EventMap.records[i].EventList - 1;
+ int end = module.EventMap.records.Length > i + 1 ? module.EventMap.records[i + 1].EventList - 1 : module.Event.records.Length;
+ EventInfo[] events = new EventInfo[end - evt];
+ for (int j = 0; evt < end; evt++, j++)
+ {
+ events[j] = new EventInfoImpl(module, this, evt);
+ }
+ return events;
+ }
+ }
+ return Empty<EventInfo>.Array;
+ }
+
+ public override FieldInfo[] __GetDeclaredFields()
+ {
+ int field = module.TypeDef.records[index].FieldList - 1;
+ int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].FieldList - 1 : module.Field.records.Length;
+ FieldInfo[] fields = new FieldInfo[end - field];
+ for (int i = 0; field < end; i++, field++)
+ {
+ fields[i] = module.GetFieldAt(this, field);
+ }
+ return fields;
+ }
+
+ public override Type[] __GetDeclaredInterfaces()
+ {
+ int token = this.MetadataToken;
+ List<Type> list = new List<Type>();
+ // TODO use binary search?
+ for (int i = 0; i < module.InterfaceImpl.records.Length; i++)
+ {
+ if (module.InterfaceImpl.records[i].Class == token)
+ {
+ list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this));
+ }
+ }
+ return list.ToArray();
+ }
+
+ public override MethodBase[] __GetDeclaredMethods()
+ {
+ int method = module.TypeDef.records[index].MethodList - 1;
+ int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length;
+ MethodBase[] methods = new MethodBase[end - method];
+ for (int i = 0; method < end; method++, i++)
+ {
+ methods[i] = module.GetMethodAt(this, method);
+ }
+ return methods;
+ }
+
+ public override __MethodImplMap __GetMethodImplMap()
+ {
+ List<MethodInfo> bodies = new List<MethodInfo>();
+ List<List<MethodInfo>> declarations = new List<List<MethodInfo>>();
+ int token = this.MetadataToken;
+ // TODO use binary search?
+ for (int i = 0; i < module.MethodImpl.records.Length; i++)
+ {
+ if (module.MethodImpl.records[i].Class == token)
+ {
+ MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null);
+ int index = bodies.IndexOf(body);
+ if (index == -1)
+ {
+ index = bodies.Count;
+ bodies.Add(body);
+ declarations.Add(new List<MethodInfo>());
+ }
+ MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null);
+ declarations[index].Add(declaration);
+ }
+ }
+ __MethodImplMap map = new __MethodImplMap();
+ map.TargetType = this;
+ map.MethodBodies = bodies.ToArray();
+ map.MethodDeclarations = new MethodInfo[declarations.Count][];
+ for (int i = 0; i < map.MethodDeclarations.Length; i++)
+ {
+ map.MethodDeclarations[i] = declarations[i].ToArray();
+ }
+ return map;
+ }
+
+ public override Type[] __GetDeclaredTypes()
+ {
+ int token = this.MetadataToken;
+ List<Type> list = new List<Type>();
+ // TODO use binary search?
+ for (int i = 0; i < module.NestedClass.records.Length; i++)
+ {
+ if (module.NestedClass.records[i].EnclosingClass == token)
+ {
+ list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass));
+ }
+ }
+ return list.ToArray();
+ }
+
+ public override PropertyInfo[] __GetDeclaredProperties()
+ {
+ int token = this.MetadataToken;
+ // TODO use binary search?
+ for (int i = 0; i < module.PropertyMap.records.Length; i++)
+ {
+ if (module.PropertyMap.records[i].Parent == token)
+ {
+ int property = module.PropertyMap.records[i].PropertyList - 1;
+ int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length;
+ PropertyInfo[] properties = new PropertyInfo[end - property];
+ for (int j = 0; property < end; property++, j++)
+ {
+ properties[j] = new PropertyInfoImpl(module, this, property);
+ }
+ return properties;
+ }
+ }
+ return Empty<PropertyInfo>.Array;
+ }
+
+ public override string Name
+ {
+ get { return typeName; }
+ }
+
+ public override string Namespace
+ {
+ get { return typeNamespace; }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get { return this; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return (TypeDefTable.Index << 24) + index + 1; }
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ PopulateGenericArguments();
+ return Util.Copy(typeArgs);
+ }
+
+ private void PopulateGenericArguments()
+ {
+ if (typeArgs == null)
+ {
+ int token = this.MetadataToken;
+ int first = module.GenericParam.FindFirstByOwner(token);
+ if (first == -1)
+ {
+ typeArgs = Type.EmptyTypes;
+ }
+ else
+ {
+ List<Type> list = new List<Type>();
+ int len = module.GenericParam.records.Length;
+ for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
+ {
+ list.Add(new GenericTypeParameter(module, i));
+ }
+ typeArgs = list.ToArray();
+ }
+ }
+ }
+
+ internal override Type GetGenericTypeArgument(int index)
+ {
+ PopulateGenericArguments();
+ return typeArgs[index];
+ }
+
+ public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+ {
+ PopulateGenericArguments();
+ return Util.Copy(new Type[typeArgs.Length][]);
+ }
+
+ public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+ {
+ PopulateGenericArguments();
+ return Util.Copy(new Type[typeArgs.Length][]);
+ }
+
+ public override bool IsGenericType
+ {
+ get { return IsGenericTypeDefinition; }
+ }
+
+ public override bool IsGenericTypeDefinition
+ {
+ get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
+ }
+
+ public override Type GetGenericTypeDefinition()
+ {
+ if (IsGenericTypeDefinition)
+ {
+ return this;
+ }
+ throw new InvalidOperationException();
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(this.FullName);
+ string sep = "[";
+ foreach (Type arg in GetGenericArguments())
+ {
+ sb.Append(sep);
+ sb.Append(arg);
+ sep = ",";
+ }
+ if (sep != "[")
+ {
+ sb.Append(']');
+ }
+ return sb.ToString();
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ // note that we cannot use Type.IsNested for this, because that calls DeclaringType
+ if ((this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) == 0)
+ {
+ return null;
+ }
+ // TODO use binary search (if sorted)
+ int token = this.MetadataToken;
+ for (int i = 0; i < module.NestedClass.records.Length; i++)
+ {
+ if (module.NestedClass.records[i].NestedClass == token)
+ {
+ return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
+ }
+ }
+ throw new InvalidOperationException();
+ }
+ }
+
+ public override StructLayoutAttribute StructLayoutAttribute
+ {
+ get
+ {
+ StructLayoutAttribute layout;
+ switch (this.Attributes & TypeAttributes.LayoutMask)
+ {
+ case TypeAttributes.AutoLayout:
+ return null;
+ case TypeAttributes.SequentialLayout:
+ layout = new StructLayoutAttribute(LayoutKind.Sequential);
+ break;
+ case TypeAttributes.ExplicitLayout:
+ layout = new StructLayoutAttribute(LayoutKind.Explicit);
+ break;
+ default:
+ throw new BadImageFormatException();
+ }
+ int token = this.MetadataToken;
+ // TODO use binary search?
+ for (int i = 0; i < module.ClassLayout.records.Length; i++)
+ {
+ if (module.ClassLayout.records[i].Parent == token)
+ {
+ layout.Pack = module.ClassLayout.records[i].PackingSize;
+ layout.Size = module.ClassLayout.records[i].ClassSize;
+ switch (this.Attributes & TypeAttributes.StringFormatMask)
+ {
+ case TypeAttributes.AnsiClass:
+ layout.CharSet = CharSet.Ansi;
+ break;
+ case TypeAttributes.UnicodeClass:
+ layout.CharSet = CharSet.Unicode;
+ break;
+ case TypeAttributes.AutoClass:
+ layout.CharSet = CharSet.Auto;
+ break;
+ default:
+ layout.CharSet = CharSet.None;
+ break;
+ }
+ return layout;
+ }
+ }
+ return null;
+ }
+ }
+
+ public override Module Module
+ {
+ get { return module; }
+ }
+
+ internal override bool IsModulePseudoType
+ {
+ get { return index == 0; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using CallingConvention = System.Runtime.InteropServices.CallingConvention;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Writer;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection
+{
+ abstract class Signature
+ {
+ internal const byte DEFAULT = 0x00;
+ internal const byte VARARG = 0x05;
+ internal const byte GENERIC = 0x10;
+ internal const byte HASTHIS = 0x20;
+ internal const byte EXPLICITTHIS = 0x40;
+ internal const byte FIELD = 0x06;
+ internal const byte LOCAL_SIG = 0x07;
+ internal const byte PROPERTY = 0x08;
+ internal const byte GENERICINST = 0x0A;
+ internal const byte SENTINEL = 0x41;
+ internal const byte ELEMENT_TYPE_VOID = 0x01;
+ internal const byte ELEMENT_TYPE_BOOLEAN = 0x02;
+ internal const byte ELEMENT_TYPE_CHAR = 0x03;
+ internal const byte ELEMENT_TYPE_I1 = 0x04;
+ internal const byte ELEMENT_TYPE_U1 = 0x05;
+ internal const byte ELEMENT_TYPE_I2 = 0x06;
+ internal const byte ELEMENT_TYPE_U2 = 0x07;
+ internal const byte ELEMENT_TYPE_I4 = 0x08;
+ internal const byte ELEMENT_TYPE_U4 = 0x09;
+ internal const byte ELEMENT_TYPE_I8 = 0x0a;
+ internal const byte ELEMENT_TYPE_U8 = 0x0b;
+ internal const byte ELEMENT_TYPE_R4 = 0x0c;
+ internal const byte ELEMENT_TYPE_R8 = 0x0d;
+ internal const byte ELEMENT_TYPE_STRING = 0x0e;
+ internal const byte ELEMENT_TYPE_PTR = 0x0f;
+ internal const byte ELEMENT_TYPE_BYREF = 0x10;
+ internal const byte ELEMENT_TYPE_VALUETYPE = 0x11;
+ internal const byte ELEMENT_TYPE_CLASS = 0x12;
+ internal const byte ELEMENT_TYPE_VAR = 0x13;
+ internal const byte ELEMENT_TYPE_ARRAY = 0x14;
+ internal const byte ELEMENT_TYPE_GENERICINST = 0x15;
+ internal const byte ELEMENT_TYPE_TYPEDBYREF = 0x16;
+ internal const byte ELEMENT_TYPE_I = 0x18;
+ internal const byte ELEMENT_TYPE_U = 0x19;
+ internal const byte ELEMENT_TYPE_FNPTR = 0x1b;
+ internal const byte ELEMENT_TYPE_OBJECT = 0x1c;
+ internal const byte ELEMENT_TYPE_SZARRAY = 0x1d;
+ internal const byte ELEMENT_TYPE_MVAR = 0x1e;
+ internal const byte ELEMENT_TYPE_CMOD_REQD = 0x1f;
+ internal const byte ELEMENT_TYPE_CMOD_OPT = 0x20;
+ internal const byte ELEMENT_TYPE_PINNED = 0x45;
+
+ internal abstract void WriteSig(ModuleBuilder module, ByteBuffer bb);
+
+ private static Type ReadGenericInst(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ switch (br.ReadByte())
+ {
+ case ELEMENT_TYPE_CLASS:
+ case ELEMENT_TYPE_VALUETYPE:
+ break;
+ default:
+ throw new BadImageFormatException();
+ }
+ Type type = ReadTypeDefOrRefEncoded(module, br, context);
+ if (!type.IsGenericTypeDefinition)
+ {
+ throw new BadImageFormatException();
+ }
+ int genArgCount = br.ReadCompressedInt();
+ Type[] args = new Type[genArgCount];
+ Type[][] reqmod = null;
+ Type[][] optmod = null;
+ for (int i = 0; i < genArgCount; i++)
+ {
+ // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for genericinst, but C++ uses it, the verifier allows it and ildasm also supports it
+ CustomModifiers mods = ReadCustomModifiers(module, br, context);
+ if (mods.required != null || mods.optional != null)
+ {
+ if (reqmod == null)
+ {
+ reqmod = new Type[genArgCount][];
+ optmod = new Type[genArgCount][];
+ }
+ reqmod[i] = mods.required;
+ optmod[i] = mods.optional;
+ }
+ args[i] = ReadType(module, br, context);
+ }
+ return GenericTypeInstance.Make(type, args, reqmod, optmod);
+ }
+
+ internal static Type ReadTypeSpec(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ // LAMESPEC a TypeSpec can contain custom modifiers (C++/CLI generates "newarr (TypeSpec with custom modifiers)")
+ SkipCustomModifiers(br);
+ // LAMESPEC anything can be adorned by (useless) custom modifiers
+ // also, VAR and MVAR are also used in TypeSpec (contrary to what the spec says)
+ return ReadType(module, br, context);
+ }
+
+ private static Type ReadFunctionPointer(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ // TODO like .NET we return System.IntPtr here, but ideally we should fire an event in Universe that
+ // the user can hook to provide a custom type (or we simply should build in full support for function pointer types)
+ MethodSignature.ReadStandAloneMethodSig(module, br, context);
+ return module.universe.System_IntPtr;
+ }
+
+ internal static Type[] ReadMethodSpec(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ if (br.ReadByte() != GENERICINST)
+ {
+ throw new BadImageFormatException();
+ }
+ Type[] args = new Type[br.ReadCompressedInt()];
+ for (int i = 0; i < args.Length; i++)
+ {
+ args[i] = ReadType(module, br, context);
+ }
+ return args;
+ }
+
+ private static int ReadArrayShape(ByteReader br)
+ {
+ int rank = br.ReadCompressedInt();
+ int numSizes = br.ReadCompressedInt();
+ for (int i = 0; i < numSizes; i++)
+ {
+ br.ReadCompressedInt();
+ }
+ int numLoBounds = br.ReadCompressedInt();
+ for (int i = 0; i < numLoBounds; i++)
+ {
+ br.ReadCompressedInt();
+ }
+ return rank;
+ }
+
+ private static Type ReadTypeOrVoid(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ if (br.PeekByte() == ELEMENT_TYPE_VOID)
+ {
+ br.ReadByte();
+ return module.universe.System_Void;
+ }
+ else
+ {
+ return ReadType(module, br, context);
+ }
+ }
+
+ // see ECMA 335 CLI spec June 2006 section 23.2.12 for this production
+ protected static Type ReadType(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ CustomModifiers mods;
+ switch (br.ReadByte())
+ {
+ case ELEMENT_TYPE_CLASS:
+ case ELEMENT_TYPE_VALUETYPE:
+ return ReadTypeDefOrRefEncoded(module, br, context);
+ case ELEMENT_TYPE_BOOLEAN:
+ return module.universe.System_Boolean;
+ case ELEMENT_TYPE_CHAR:
+ return module.universe.System_Char;
+ case ELEMENT_TYPE_I1:
+ return module.universe.System_SByte;
+ case ELEMENT_TYPE_U1:
+ return module.universe.System_Byte;
+ case ELEMENT_TYPE_I2:
+ return module.universe.System_Int16;
+ case ELEMENT_TYPE_U2:
+ return module.universe.System_UInt16;
+ case ELEMENT_TYPE_I4:
+ return module.universe.System_Int32;
+ case ELEMENT_TYPE_U4:
+ return module.universe.System_UInt32;
+ case ELEMENT_TYPE_I8:
+ return module.universe.System_Int64;
+ case ELEMENT_TYPE_U8:
+ return module.universe.System_UInt64;
+ case ELEMENT_TYPE_R4:
+ return module.universe.System_Single;
+ case ELEMENT_TYPE_R8:
+ return module.universe.System_Double;
+ case ELEMENT_TYPE_I:
+ return module.universe.System_IntPtr;
+ case ELEMENT_TYPE_U:
+ return module.universe.System_UIntPtr;
+ case ELEMENT_TYPE_STRING:
+ return module.universe.System_String;
+ case ELEMENT_TYPE_OBJECT:
+ return module.universe.System_Object;
+ case ELEMENT_TYPE_VAR:
+ return context.GetGenericTypeArgument(br.ReadCompressedInt());
+ case ELEMENT_TYPE_MVAR:
+ return context.GetGenericMethodArgument(br.ReadCompressedInt());
+ case ELEMENT_TYPE_GENERICINST:
+ return ReadGenericInst(module, br, context);
+ case ELEMENT_TYPE_SZARRAY:
+ mods = ReadCustomModifiers(module, br, context);
+ return ReadType(module, br, context).__MakeArrayType(mods.required, mods.optional);
+ case ELEMENT_TYPE_ARRAY:
+ mods = ReadCustomModifiers(module, br, context);
+ return ReadType(module, br, context).__MakeArrayType(ReadArrayShape(br), mods.required, mods.optional);
+ case ELEMENT_TYPE_PTR:
+ mods = ReadCustomModifiers(module, br, context);
+ return ReadTypeOrVoid(module, br, context).__MakePointerType(mods.required, mods.optional);
+ case ELEMENT_TYPE_FNPTR:
+ return ReadFunctionPointer(module, br, context);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ internal static void ReadLocalVarSig(ModuleReader module, ByteReader br, IGenericContext context, List<LocalVariableInfo> list)
+ {
+ if (br.Length < 2 || br.ReadByte() != LOCAL_SIG)
+ {
+ throw new BadImageFormatException("Invalid local variable signature");
+ }
+ int count = br.ReadCompressedInt();
+ for (int i = 0; i < count; i++)
+ {
+ if (br.PeekByte() == ELEMENT_TYPE_TYPEDBYREF)
+ {
+ br.ReadByte();
+ list.Add(new LocalVariableInfo(i, module.universe.System_TypedReference, false));
+ }
+ else
+ {
+ SkipCustomModifiers(br);
+ bool pinned = false;
+ if (br.PeekByte() == ELEMENT_TYPE_PINNED)
+ {
+ br.ReadByte();
+ pinned = true;
+ }
+ SkipCustomModifiers(br);
+ Type type = ReadTypeOrByRef(module, br, context);
+ list.Add(new LocalVariableInfo(i, type, pinned));
+ }
+ }
+ }
+
+ private static Type ReadTypeOrByRef(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ if (br.PeekByte() == ELEMENT_TYPE_BYREF)
+ {
+ br.ReadByte();
+ // LAMESPEC it is allowed (by C++/CLI, ilasm and peverify) to have custom modifiers after the BYREF
+ // (which makes sense, as it is analogous to pointers)
+ CustomModifiers mods = ReadCustomModifiers(module, br, context);
+ // C++/CLI generates void& local variables, so we need to use ReadTypeOrVoid here
+ return ReadTypeOrVoid(module, br, context).__MakeByRefType(mods.required, mods.optional);
+ }
+ else
+ {
+ return ReadType(module, br, context);
+ }
+ }
+
+ protected static Type ReadRetType(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ switch (br.PeekByte())
+ {
+ case ELEMENT_TYPE_VOID:
+ br.ReadByte();
+ return module.universe.System_Void;
+ case ELEMENT_TYPE_TYPEDBYREF:
+ br.ReadByte();
+ return module.universe.System_TypedReference;
+ default:
+ return ReadTypeOrByRef(module, br, context);
+ }
+ }
+
+ protected static Type ReadParam(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ switch (br.PeekByte())
+ {
+ case ELEMENT_TYPE_TYPEDBYREF:
+ br.ReadByte();
+ return module.universe.System_TypedReference;
+ default:
+ return ReadTypeOrByRef(module, br, context);
+ }
+ }
+
+ protected static void WriteType(ModuleBuilder module, ByteBuffer bb, Type type)
+ {
+ while (type.HasElementType)
+ {
+ if (type.__IsVector)
+ {
+ bb.Write(ELEMENT_TYPE_SZARRAY);
+ }
+ else if (type.IsArray)
+ {
+ int rank = type.GetArrayRank();
+ bb.Write(ELEMENT_TYPE_ARRAY);
+ // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for arrays, but the verifier allows it and ildasm also supports it
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers());
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers());
+ WriteType(module, bb, type.GetElementType());
+ bb.WriteCompressedInt(rank);
+ // since a Type doesn't contain the lower/upper bounds
+ // (they act like a custom modifier, so they are part of the signature, but not of the Type),
+ // we set them to the C# compatible values and hope for the best
+ bb.WriteCompressedInt(0); // boundsCount
+ bb.WriteCompressedInt(rank); // loCount
+ for (int i = 0; i < rank; i++)
+ {
+ bb.WriteCompressedInt(0);
+ }
+ return;
+ }
+ else if (type.IsByRef)
+ {
+ bb.Write(ELEMENT_TYPE_BYREF);
+ }
+ else if (type.IsPointer)
+ {
+ bb.Write(ELEMENT_TYPE_PTR);
+ }
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers());
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers());
+ type = type.GetElementType();
+ }
+ Universe u = module.universe;
+ if (type == u.System_Void)
+ {
+ bb.Write(ELEMENT_TYPE_VOID);
+ }
+ else if (type == u.System_Boolean)
+ {
+ bb.Write(ELEMENT_TYPE_BOOLEAN);
+ }
+ else if (type == u.System_Char)
+ {
+ bb.Write(ELEMENT_TYPE_CHAR);
+ }
+ else if (type == u.System_SByte)
+ {
+ bb.Write(ELEMENT_TYPE_I1);
+ }
+ else if (type == u.System_Byte)
+ {
+ bb.Write(ELEMENT_TYPE_U1);
+ }
+ else if (type == u.System_Int16)
+ {
+ bb.Write(ELEMENT_TYPE_I2);
+ }
+ else if (type == u.System_UInt16)
+ {
+ bb.Write(ELEMENT_TYPE_U2);
+ }
+ else if (type == u.System_Int32)
+ {
+ bb.Write(ELEMENT_TYPE_I4);
+ }
+ else if (type == u.System_UInt32)
+ {
+ bb.Write(ELEMENT_TYPE_U4);
+ }
+ else if (type == u.System_Int64)
+ {
+ bb.Write(ELEMENT_TYPE_I8);
+ }
+ else if (type == u.System_UInt64)
+ {
+ bb.Write(ELEMENT_TYPE_U8);
+ }
+ else if (type == u.System_Single)
+ {
+ bb.Write(ELEMENT_TYPE_R4);
+ }
+ else if (type == u.System_Double)
+ {
+ bb.Write(ELEMENT_TYPE_R8);
+ }
+ else if (type == u.System_String)
+ {
+ bb.Write(ELEMENT_TYPE_STRING);
+ }
+ else if (type == u.System_IntPtr)
+ {
+ bb.Write(ELEMENT_TYPE_I);
+ }
+ else if (type == u.System_UIntPtr)
+ {
+ bb.Write(ELEMENT_TYPE_U);
+ }
+ else if (type == u.System_TypedReference)
+ {
+ bb.Write(ELEMENT_TYPE_TYPEDBYREF);
+ }
+ else if (type == u.System_Object)
+ {
+ bb.Write(ELEMENT_TYPE_OBJECT);
+ }
+ else if (type.IsGenericParameter)
+ {
+ if (type is UnboundGenericMethodParameter || type.DeclaringMethod != null)
+ {
+ bb.Write(ELEMENT_TYPE_MVAR);
+ }
+ else
+ {
+ bb.Write(ELEMENT_TYPE_VAR);
+ }
+ bb.WriteCompressedInt(type.GenericParameterPosition);
+ }
+ else if (type.IsGenericType)
+ {
+ WriteGenericSignature(module, bb, type);
+ }
+ else
+ {
+ if (type.IsValueType)
+ {
+ bb.Write(ELEMENT_TYPE_VALUETYPE);
+ }
+ else
+ {
+ bb.Write(ELEMENT_TYPE_CLASS);
+ }
+ bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token);
+ }
+ }
+
+ private static void WriteGenericSignature(ModuleBuilder module, ByteBuffer bb, Type type)
+ {
+ Type[] typeArguments = type.GetGenericArguments();
+ Type[][] requiredCustomModifiers = type.__GetGenericArgumentsRequiredCustomModifiers();
+ Type[][] optionalCustomModifiers = type.__GetGenericArgumentsOptionalCustomModifiers();
+ if (!type.IsGenericTypeDefinition)
+ {
+ type = type.GetGenericTypeDefinition();
+ }
+ bb.Write(ELEMENT_TYPE_GENERICINST);
+ if (type.IsValueType)
+ {
+ bb.Write(ELEMENT_TYPE_VALUETYPE);
+ }
+ else
+ {
+ bb.Write(ELEMENT_TYPE_CLASS);
+ }
+ bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token);
+ bb.WriteCompressedInt(typeArguments.Length);
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers[i]);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers[i]);
+ WriteType(module, bb, typeArguments[i]);
+ }
+ }
+
+ protected static void WriteCustomModifiers(ModuleBuilder module, ByteBuffer bb, byte mod, Type[] modifiers)
+ {
+ if (modifiers != null)
+ {
+ foreach (Type type in modifiers)
+ {
+ bb.Write(mod);
+ bb.WriteTypeDefOrRefEncoded(module.GetTypeTokenForMemberRef(type));
+ }
+ }
+ }
+
+ protected static bool IsCustomModifier(byte b)
+ {
+ return b == ELEMENT_TYPE_CMOD_OPT || b == ELEMENT_TYPE_CMOD_REQD;
+ }
+
+ struct CustomModifiers
+ {
+ internal Type[] required;
+ internal Type[] optional;
+ }
+
+ private static CustomModifiers ReadCustomModifiers(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ CustomModifiers mods = new CustomModifiers();
+ byte b = br.PeekByte();
+ if (IsCustomModifier(b))
+ {
+ List<Type> required = new List<Type>();
+ List<Type> optional = new List<Type>();
+ while (IsCustomModifier(b))
+ {
+ bool req = br.ReadByte() == ELEMENT_TYPE_CMOD_REQD;
+ Type type = ReadTypeDefOrRefEncoded(module, br, context);
+ (req ? required : optional).Add(type);
+ b = br.PeekByte();
+ }
+ mods.required = required.ToArray();
+ mods.optional = optional.ToArray();
+ }
+ return mods;
+ }
+
+ protected static void SkipCustomModifiers(ByteReader br)
+ {
+ byte b = br.PeekByte();
+ while (IsCustomModifier(b))
+ {
+ br.ReadByte();
+ br.ReadCompressedInt();
+ b = br.PeekByte();
+ }
+ }
+
+ private static Type ReadTypeDefOrRefEncoded(ModuleReader module, ByteReader br, IGenericContext context)
+ {
+ int encoded = br.ReadCompressedInt();
+ switch (encoded & 3)
+ {
+ case 0:
+ return module.ResolveType((TypeDefTable.Index << 24) + (encoded >> 2), null, null);
+ case 1:
+ return module.ResolveType((TypeRefTable.Index << 24) + (encoded >> 2), null, null);
+ case 2:
+ return module.ResolveType((TypeSpecTable.Index << 24) + (encoded >> 2), context);
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ protected static void ReadCustomModifiers(ModuleReader module, ByteReader br, IGenericContext context, out Type[] requiredCustomModifiers, out Type[] optionalCustomModifiers)
+ {
+ byte b = br.PeekByte();
+ if (IsCustomModifier(b))
+ {
+ List<Type> required = new List<Type>();
+ List<Type> optional = new List<Type>();
+ while (IsCustomModifier(b))
+ {
+ br.ReadByte();
+ Type type = ReadTypeDefOrRefEncoded(module, br, context);
+ if (b == ELEMENT_TYPE_CMOD_REQD)
+ {
+ required.Add(type);
+ }
+ else
+ {
+ optional.Add(type);
+ }
+ b = br.PeekByte();
+ }
+ requiredCustomModifiers = required.ToArray();
+ optionalCustomModifiers = optional.ToArray();
+ }
+ else
+ {
+ requiredCustomModifiers = null;
+ optionalCustomModifiers = null;
+ }
+ }
+
+ // unmanaged calling convention
+ internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConvention callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ switch (callingConvention)
+ {
+ case CallingConvention.Cdecl:
+ bb.Write((byte)0x01); // C
+ break;
+ case CallingConvention.StdCall:
+ case CallingConvention.Winapi:
+ bb.Write((byte)0x02); // STDCALL
+ break;
+ case CallingConvention.ThisCall:
+ bb.Write((byte)0x03); // THISCALL
+ break;
+ case CallingConvention.FastCall:
+ bb.Write((byte)0x04); // FASTCALL
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("callingConvention");
+ }
+ bb.WriteCompressedInt(parameterTypes.Length);
+ WriteType(module, bb, returnType);
+ foreach (Type t in parameterTypes)
+ {
+ WriteType(module, bb, t);
+ }
+ }
+
+ // managed calling convention
+ internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+ {
+ byte flags = 0;
+ if ((callingConvention & CallingConventions.HasThis) != 0)
+ {
+ flags |= HASTHIS;
+ }
+ if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+ {
+ flags |= EXPLICITTHIS;
+ }
+ if ((callingConvention & CallingConventions.VarArgs) != 0)
+ {
+ flags |= VARARG;
+ }
+ bb.Write(flags);
+ bb.WriteCompressedInt(parameterTypes.Length + optionalParameterTypes.Length);
+ WriteType(module, bb, returnType);
+ foreach (Type t in parameterTypes)
+ {
+ WriteType(module, bb, t);
+ }
+ if (optionalParameterTypes.Length > 0)
+ {
+ bb.Write(SENTINEL);
+ foreach (Type t in optionalParameterTypes)
+ {
+ WriteType(module, bb, t);
+ }
+ }
+ }
+
+ internal static void WriteLocalVarSig(ModuleBuilder module, ByteBuffer bb, IList<LocalBuilder> locals)
+ {
+ bb.Write(LOCAL_SIG);
+ bb.WriteCompressedInt(locals.Count);
+ foreach (LocalBuilder local in locals)
+ {
+ if (local.IsPinned)
+ {
+ bb.Write(ELEMENT_TYPE_PINNED);
+ }
+ WriteType(module, bb, local.LocalType);
+ }
+ }
+
+ internal static void WritePropertySig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ byte flags = PROPERTY;
+ if ((callingConvention & CallingConventions.HasThis) != 0)
+ {
+ flags |= HASTHIS;
+ }
+ if ((callingConvention & CallingConventions.ExplicitThis) != 0)
+ {
+ flags |= EXPLICITTHIS;
+ }
+ if ((callingConvention & CallingConventions.VarArgs) != 0)
+ {
+ flags |= VARARG;
+ }
+ bb.Write(flags);
+ bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, returnTypeRequiredCustomModifiers);
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, returnTypeOptionalCustomModifiers);
+ WriteType(module, bb, returnType);
+ if (parameterTypes != null)
+ {
+ for (int i = 0; i < parameterTypes.Length; i++)
+ {
+ if (parameterTypeRequiredCustomModifiers != null)
+ {
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, parameterTypeRequiredCustomModifiers[i]);
+ }
+ if (parameterTypeOptionalCustomModifiers != null)
+ {
+ WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, parameterTypeOptionalCustomModifiers[i]);
+ }
+ WriteType(module, bb, parameterTypes[i]);
+ }
+ }
+ }
+
+ internal static void WriteTypeSpec(ModuleBuilder module, ByteBuffer bb, Type type)
+ {
+ WriteType(module, bb, type);
+ }
+
+ internal static void WriteMethodSpec(ModuleBuilder module, ByteBuffer bb, Type[] genArgs)
+ {
+ bb.Write(GENERICINST);
+ bb.WriteCompressedInt(genArgs.Length);
+ foreach (Type arg in genArgs)
+ {
+ WriteType(module, bb, arg);
+ }
+ }
+
+ // this reads just the optional parameter types, from a MethodRefSig
+ internal static Type[] ReadOptionalParameterTypes(ModuleReader module, ByteReader br)
+ {
+ br.ReadByte();
+ int paramCount = br.ReadCompressedInt();
+ SkipCustomModifiers(br);
+ ReadRetType(module, br, null);
+ for (int i = 0; i < paramCount; i++)
+ {
+ if (br.PeekByte() == SENTINEL)
+ {
+ br.ReadByte();
+ Type[] types = new Type[paramCount - i];
+ for (int j = 0; j < types.Length; j++)
+ {
+ SkipCustomModifiers(br);
+ types[j] = ReadType(module, br, null);
+ }
+ return types;
+ }
+ SkipCustomModifiers(br);
+ ReadType(module, br, null);
+ }
+ return Type.EmptyTypes;
+ }
+
+ protected static Type[] BindTypeParameters(IGenericBinder binder, Type[] types)
+ {
+ if (types == null || types.Length == 0)
+ {
+ return Type.EmptyTypes;
+ }
+ Type[] expanded = new Type[types.Length];
+ for (int i = 0; i < types.Length; i++)
+ {
+ expanded[i] = types[i].BindTypeParameters(binder);
+ }
+ return expanded;
+ }
+
+ protected static Type[][] BindTypeParameters(IGenericBinder binder, Type[][] types)
+ {
+ if (types == null)
+ {
+ return null;
+ }
+ Type[][] expanded = new Type[types.Length][];
+ for (int i = 0; i < types.Length; i++)
+ {
+ expanded[i] = BindTypeParameters(binder, types[i]);
+ }
+ return expanded;
+ }
+
+ protected static Type[][][] BindTypeParameters(IGenericBinder binder, Type[][][] types)
+ {
+ if (types == null)
+ {
+ return null;
+ }
+ Type[][][] expanded = new Type[types.Length][][];
+ for (int i = 0; i < types.Length; i++)
+ {
+ expanded[i] = BindTypeParameters(binder, types[i]);
+ }
+ return expanded;
+ }
+
+ protected static Type[] BindTypeParameters(IGenericBinder binder, Type[][][] types, int index, int optOrReq)
+ {
+ if (types == null || types[index] == null)
+ {
+ return null;
+ }
+ return BindTypeParameters(binder, types[index][optOrReq]);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Runtime.InteropServices;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection
+{
+ public sealed class __StandAloneMethodSig
+ {
+ private readonly bool unmanaged;
+ private readonly CallingConvention unmanagedCallingConvention;
+ private readonly CallingConventions callingConvention;
+ private readonly Type returnType;
+ private readonly Type[] parameterTypes;
+ private readonly Type[] optionalParameterTypes;
+
+ internal __StandAloneMethodSig(bool unmanaged, CallingConvention unmanagedCallingConvention, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+ {
+ this.unmanaged = unmanaged;
+ this.unmanagedCallingConvention = unmanagedCallingConvention;
+ this.callingConvention = callingConvention;
+ this.returnType = returnType;
+ this.parameterTypes = parameterTypes;
+ this.optionalParameterTypes = optionalParameterTypes;
+ }
+
+ public bool IsUnmanaged
+ {
+ get { return unmanaged; }
+ }
+
+ public CallingConventions CallingConvention
+ {
+ get { return callingConvention; }
+ }
+
+ public CallingConvention UnmanagedCallingConvention
+ {
+ get { return unmanagedCallingConvention; }
+ }
+
+ public Type ReturnType
+ {
+ get { return returnType; }
+ }
+
+ public Type[] ParameterTypes
+ {
+ get { return Util.Copy(parameterTypes); }
+ }
+
+ public Type[] OptionalParameterTypes
+ {
+ get { return Util.Copy(optionalParameterTypes); }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ public class StrongNameKeyPair
+ {
+ internal readonly System.Reflection.StrongNameKeyPair keyPair;
+
+ internal StrongNameKeyPair(System.Reflection.StrongNameKeyPair keyPair)
+ {
+ this.keyPair = keyPair;
+ }
+
+ public StrongNameKeyPair(string keyPairContainer)
+ {
+ this.keyPair = new System.Reflection.StrongNameKeyPair(keyPairContainer);
+ }
+
+ public StrongNameKeyPair(byte[] keyPairArray)
+ {
+ this.keyPair = new System.Reflection.StrongNameKeyPair(keyPairArray);
+ }
+
+ public StrongNameKeyPair(System.IO.FileStream fs)
+ {
+ this.keyPair = new System.Reflection.StrongNameKeyPair(fs);
+ }
+
+ public byte[] PublicKey
+ {
+ get { return keyPair.PublicKey; }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Collections.Generic;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection
+{
+ interface IGenericContext
+ {
+ Type GetGenericTypeArgument(int index);
+ Type GetGenericMethodArgument(int index);
+ }
+
+ interface IGenericBinder
+ {
+ Type BindTypeParameter(Type type);
+ Type BindMethodParameter(Type type);
+ }
+
+ public abstract class Type : MemberInfo, IGenericContext, IGenericBinder
+ {
+ public static readonly Type[] EmptyTypes = Empty<Type>.Array;
+
+ public static Binder DefaultBinder
+ {
+ get { return null; }
+ }
+
+ public sealed override MemberTypes MemberType
+ {
+ get { return IsNested ? MemberTypes.NestedType : MemberTypes.TypeInfo; }
+ }
+
+ public virtual string AssemblyQualifiedName
+ {
+ // NOTE the assembly name is not escaped here, only when used in a generic type instantiation
+ get { return this.FullName + ", " + this.Assembly.FullName; }
+ }
+
+ public abstract Type BaseType
+ {
+ get;
+ }
+
+ public abstract TypeAttributes Attributes
+ {
+ get;
+ }
+
+ public virtual Type GetElementType()
+ {
+ return null;
+ }
+
+ internal virtual void CheckBaked()
+ {
+ }
+
+ public virtual Type[] __GetDeclaredTypes()
+ {
+ return Type.EmptyTypes;
+ }
+
+ public virtual Type[] __GetDeclaredInterfaces()
+ {
+ return Type.EmptyTypes;
+ }
+
+ public virtual MethodBase[] __GetDeclaredMethods()
+ {
+ return Empty<MethodBase>.Array;
+ }
+
+ public virtual __MethodImplMap __GetMethodImplMap()
+ {
+ throw new NotSupportedException();
+ }
+
+ public virtual FieldInfo[] __GetDeclaredFields()
+ {
+ return Empty<FieldInfo>.Array;
+ }
+
+ public virtual EventInfo[] __GetDeclaredEvents()
+ {
+ return Empty<EventInfo>.Array;
+ }
+
+ public virtual PropertyInfo[] __GetDeclaredProperties()
+ {
+ return Empty<PropertyInfo>.Array;
+ }
+
+ public virtual Type[] __GetRequiredCustomModifiers()
+ {
+ return Type.EmptyTypes;
+ }
+
+ public virtual Type[] __GetOptionalCustomModifiers()
+ {
+ return Type.EmptyTypes;
+ }
+
+ public virtual bool HasElementType
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsArray
+ {
+ get { return false; }
+ }
+
+ public virtual bool __IsVector
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsByRef
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsPointer
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsValueType
+ {
+ get
+ {
+ Type baseType = this.BaseType;
+ return baseType == this.Module.universe.System_Enum
+ || (baseType == this.Module.universe.System_ValueType && this != this.Module.universe.System_Enum);
+ }
+ }
+
+ public virtual bool IsGenericParameter
+ {
+ get { return false; }
+ }
+
+ public virtual int GenericParameterPosition
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public virtual MethodBase DeclaringMethod
+ {
+ get { return null; }
+ }
+
+ public virtual Type UnderlyingSystemType
+ {
+ get { return this; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return null; }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ string fullname = FullName;
+ return fullname.Substring(fullname.LastIndexOf('.') + 1);
+ }
+ }
+
+ public virtual string Namespace
+ {
+ get
+ {
+ if (IsNested)
+ {
+ return null;
+ }
+ string fullname = FullName;
+ int index = fullname.LastIndexOf('.');
+ return index < 0 ? null : fullname.Substring(0, index);
+ }
+ }
+
+ internal virtual int GetModuleBuilderToken()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public bool Equals(Type type)
+ {
+ return !ReferenceEquals(type, null) && ReferenceEquals(type.UnderlyingSystemType, this.UnderlyingSystemType);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as Type);
+ }
+
+ public override int GetHashCode()
+ {
+ Type type = this.UnderlyingSystemType;
+ return ReferenceEquals(type, this) ? base.GetHashCode() : type.GetHashCode();
+ }
+
+ public virtual Type[] GetGenericArguments()
+ {
+ return Type.EmptyTypes;
+ }
+
+ public virtual Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+ {
+ return Empty<Type[]>.Array;
+ }
+
+ public virtual Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+ {
+ return Empty<Type[]>.Array;
+ }
+
+ public virtual Type GetGenericTypeDefinition()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public virtual StructLayoutAttribute StructLayoutAttribute
+ {
+ get { return null; }
+ }
+
+ public virtual bool IsGenericType
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsGenericTypeDefinition
+ {
+ get { return false; }
+ }
+
+ public virtual bool ContainsGenericParameters
+ {
+ get
+ {
+ if (this.IsGenericParameter)
+ {
+ return true;
+ }
+ foreach (Type arg in this.GetGenericArguments())
+ {
+ if (arg.ContainsGenericParameters)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public virtual Type[] GetGenericParameterConstraints()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public virtual GenericParameterAttributes GenericParameterAttributes
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public virtual int GetArrayRank()
+ {
+ throw new NotSupportedException();
+ }
+
+ // .NET 4.0 API
+ public virtual Type GetEnumUnderlyingType()
+ {
+ if (!this.IsEnum)
+ {
+ throw new ArgumentException();
+ }
+ CheckBaked();
+ return GetEnumUnderlyingTypeImpl();
+ }
+
+ internal Type GetEnumUnderlyingTypeImpl()
+ {
+ foreach (FieldInfo field in __GetDeclaredFields())
+ {
+ if (!field.IsStatic)
+ {
+ // the CLR assumes that an enum has only one instance field, so we can do the same
+ return field.FieldType;
+ }
+ }
+ throw new InvalidOperationException();
+ }
+
+ public override string ToString()
+ {
+ return FullName;
+ }
+
+ public virtual string FullName
+ {
+ get
+ {
+ Type decl = this.DeclaringType;
+ string ns = this.Namespace;
+ if (ns == null)
+ {
+ if (decl == null)
+ {
+ return this.Name;
+ }
+ else
+ {
+ return decl.FullName + "+" + this.Name;
+ }
+ }
+ else
+ {
+ if (decl == null)
+ {
+ return ns + "." + this.Name;
+ }
+ else
+ {
+ return decl.FullName + "+" + ns + "." + this.Name;
+ }
+ }
+ }
+ }
+
+ internal virtual bool IsModulePseudoType
+ {
+ get { return false; }
+ }
+
+ internal virtual Type GetGenericTypeArgument(int index)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public MemberInfo[] GetDefaultMembers()
+ {
+ Type defaultMemberAttribute = this.Module.universe.Import(typeof(System.Reflection.DefaultMemberAttribute));
+ foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(this))
+ {
+ if (cad.Constructor.DeclaringType.Equals(defaultMemberAttribute))
+ {
+ return GetMember((string)cad.ConstructorArguments[0].Value);
+ }
+ }
+ return Empty<MemberInfo>.Array;
+ }
+
+ public MemberInfo[] GetMember(string name)
+ {
+ return GetMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+ }
+
+ public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
+ {
+ return GetMember(name, MemberTypes.All, bindingAttr);
+ }
+
+ public MemberInfo[] GetMembers()
+ {
+ return GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+ }
+
+ public MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ List<MemberInfo> members = new List<MemberInfo>();
+ members.AddRange(GetConstructors(bindingAttr));
+ members.AddRange(GetMethods(bindingAttr));
+ members.AddRange(GetFields(bindingAttr));
+ members.AddRange(GetProperties(bindingAttr));
+ members.AddRange(GetEvents(bindingAttr));
+ members.AddRange(GetNestedTypes(bindingAttr));
+ return members.ToArray();
+ }
+
+ public MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ MemberFilter filter = delegate(MemberInfo member, object filterCriteria) { return member.Name.Equals(filterCriteria); };
+ return FindMembers(type, bindingAttr, filter, name);
+ }
+
+ private static void AddMembers(List<MemberInfo> list, MemberFilter filter, object filterCriteria, MemberInfo[] members)
+ {
+ foreach (MemberInfo member in members)
+ {
+ if (filter == null || filter(member, filterCriteria))
+ {
+ list.Add(member);
+ }
+ }
+ }
+
+ public MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria)
+ {
+ List<MemberInfo> members = new List<MemberInfo>();
+ if ((memberType & MemberTypes.Constructor) != 0)
+ {
+ AddMembers(members, filter, filterCriteria, GetConstructors(bindingAttr));
+ }
+ if ((memberType & MemberTypes.Method) != 0)
+ {
+ AddMembers(members, filter, filterCriteria, GetMethods(bindingAttr));
+ }
+ if ((memberType & MemberTypes.Field) != 0)
+ {
+ AddMembers(members, filter, filterCriteria, GetFields(bindingAttr));
+ }
+ if ((memberType & MemberTypes.Property) != 0)
+ {
+ AddMembers(members, filter, filterCriteria, GetProperties(bindingAttr));
+ }
+ if ((memberType & MemberTypes.Event) != 0)
+ {
+ AddMembers(members, filter, filterCriteria, GetEvents(bindingAttr));
+ }
+ if ((memberType & MemberTypes.NestedType) != 0)
+ {
+ AddMembers(members, filter, filterCriteria, GetNestedTypes(bindingAttr));
+ }
+ return members.ToArray();
+ }
+
+ public EventInfo GetEvent(string name)
+ {
+ return GetEvent(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+ }
+
+ public EventInfo GetEvent(string name, BindingFlags bindingAttr)
+ {
+ foreach (EventInfo evt in GetEvents(bindingAttr))
+ {
+ if (evt.Name == name)
+ {
+ return evt;
+ }
+ }
+ return null;
+ }
+
+ public EventInfo[] GetEvents()
+ {
+ return GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+ }
+
+ public EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ List<EventInfo> list = new List<EventInfo>();
+ Type type = this;
+ while (type != null)
+ {
+ type.CheckBaked();
+ foreach (EventInfo evt in type.__GetDeclaredEvents())
+ {
+ if (BindingFlagsMatch(evt.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+ && BindingFlagsMatch(evt.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+ {
+ list.Add(evt);
+ }
+ }
+ if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+ {
+ if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
+ {
+ bindingAttr &= ~BindingFlags.Static;
+ }
+ type = type.BaseType;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return list.ToArray();
+ }
+
+ public FieldInfo GetField(string name)
+ {
+ return GetField(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+ }
+
+ public FieldInfo GetField(string name, BindingFlags bindingAttr)
+ {
+ foreach (FieldInfo field in GetFields(bindingAttr))
+ {
+ if (field.Name == name)
+ {
+ return field;
+ }
+ }
+ return null;
+ }
+
+ public FieldInfo[] GetFields()
+ {
+ return GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
+ }
+
+ public FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ List<FieldInfo> list = new List<FieldInfo>();
+ CheckBaked();
+ foreach (FieldInfo field in __GetDeclaredFields())
+ {
+ if (BindingFlagsMatch(field.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+ && BindingFlagsMatch(field.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+ {
+ list.Add(field);
+ }
+ }
+ if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+ {
+ for (Type type = this.BaseType; type != null; type = type.BaseType)
+ {
+ type.CheckBaked();
+ foreach (FieldInfo field in type.__GetDeclaredFields())
+ {
+ if ((field.Attributes & FieldAttributes.FieldAccessMask) > FieldAttributes.Private
+ && BindingFlagsMatch(field.IsStatic, bindingAttr, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance))
+ {
+ list.Add(field);
+ }
+ }
+ }
+ }
+ return list.ToArray();
+ }
+
+ public Type[] GetInterfaces()
+ {
+ List<Type> list = new List<Type>();
+ for (Type type = this; type != null; type = type.BaseType)
+ {
+ AddInterfaces(list, type);
+ }
+ return list.ToArray();
+ }
+
+ private static void AddInterfaces(List<Type> list, Type type)
+ {
+ type.CheckBaked();
+ foreach (Type iface in type.__GetDeclaredInterfaces())
+ {
+ if (!list.Contains(iface))
+ {
+ list.Add(iface);
+ AddInterfaces(list, iface);
+ }
+ }
+ }
+
+ public MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ CheckBaked();
+ List<MethodInfo> list = new List<MethodInfo>();
+ foreach (MethodBase mb in __GetDeclaredMethods())
+ {
+ MethodInfo mi = mb as MethodInfo;
+ if (mi != null
+ && BindingFlagsMatch(mi.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+ && BindingFlagsMatch(mi.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+ {
+ list.Add(mi);
+ }
+ }
+ if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+ {
+ for (Type type = this.BaseType; type != null; type = type.BaseType)
+ {
+ type.CheckBaked();
+ foreach (MethodBase mb in type.__GetDeclaredMethods())
+ {
+ MethodInfo mi = mb as MethodInfo;
+ if (mi != null
+ && (mi.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private
+ && BindingFlagsMatch(mi.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+ && BindingFlagsMatch(mi.IsStatic, bindingAttr, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance)
+ && !FindMethod(list, mi))
+ {
+ list.Add(mi);
+ }
+ }
+ }
+ }
+ return list.ToArray();
+ }
+
+ private static bool FindMethod(List<MethodInfo> methods, MethodInfo method)
+ {
+ foreach (MethodInfo m in methods)
+ {
+ if (m.Name == method.Name && m.MethodSignature.Equals(method.MethodSignature))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public MethodInfo[] GetMethods()
+ {
+ return GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
+ }
+
+ public MethodInfo GetMethod(string name)
+ {
+ return GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+ }
+
+ public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
+ {
+ MethodInfo found = null;
+ foreach (MethodInfo method in GetMethods(bindingAttr))
+ {
+ if (method.Name == name)
+ {
+ if (found != null)
+ {
+ throw new AmbiguousMatchException();
+ }
+ found = method;
+ }
+ }
+ return found;
+ }
+
+ public MethodInfo GetMethod(string name, Type[] types)
+ {
+ return GetMethod(name, types, null);
+ }
+
+ public MethodInfo GetMethod(string name, Type[] types, ParameterModifier[] modifiers)
+ {
+ return GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, types, modifiers);
+ }
+
+ public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+ {
+ MethodInfo found = null;
+ foreach (MethodInfo method in GetMethods(bindingAttr))
+ {
+ if (method.Name == name && method.MethodSignature.MatchParameterTypes(types))
+ {
+ if (found != null)
+ {
+ throw new AmbiguousMatchException();
+ }
+ found = method;
+ }
+ }
+ return found;
+ }
+
+ public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ // FXBUG callConvention seems to be ignored
+ return GetMethod(name, bindingAttr, binder, types, modifiers);
+ }
+
+ public ConstructorInfo[] GetConstructors()
+ {
+ return GetConstructors(BindingFlags.Public | BindingFlags.Instance);
+ }
+
+ public ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ CheckBaked();
+ List<ConstructorInfo> list = new List<ConstructorInfo>();
+ foreach (MethodBase mb in __GetDeclaredMethods())
+ {
+ ConstructorInfo constructor = mb as ConstructorInfo;
+ if (constructor != null
+ && BindingFlagsMatch(constructor.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+ && BindingFlagsMatch(constructor.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+ {
+ list.Add(constructor);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public ConstructorInfo GetConstructor(Type[] types)
+ {
+ return GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Standard, types, null);
+ }
+
+ public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+ {
+ foreach (ConstructorInfo constructor in GetConstructors(bindingAttr))
+ {
+ if (constructor.MethodSignature.MatchParameterTypes(types))
+ {
+ return constructor;
+ }
+ }
+ return null;
+ }
+
+ public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callingConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ // FXBUG callConvention seems to be ignored
+ return GetConstructor(bindingAttr, binder, types, modifiers);
+ }
+
+ public Type GetNestedType(string name)
+ {
+ return GetNestedType(name, BindingFlags.Public);
+ }
+
+ public Type GetNestedType(string name, BindingFlags bindingAttr)
+ {
+ foreach (Type type in GetNestedTypes(bindingAttr))
+ {
+ if (type.Name == name)
+ {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ public Type[] GetNestedTypes()
+ {
+ return GetNestedTypes(BindingFlags.Public);
+ }
+
+ public Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ CheckBaked();
+ List<Type> list = new List<Type>();
+ foreach (Type type in __GetDeclaredTypes())
+ {
+ if (BindingFlagsMatch(type.IsNestedPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic))
+ {
+ list.Add(type);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public PropertyInfo[] GetProperties()
+ {
+ return GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+ }
+
+ public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ List<PropertyInfo> list = new List<PropertyInfo>();
+ Type type = this;
+ while (type != null)
+ {
+ type.CheckBaked();
+ foreach (PropertyInfo property in type.__GetDeclaredProperties())
+ {
+ if (BindingFlagsMatch(property.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
+ && BindingFlagsMatch(property.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+ {
+ list.Add(property);
+ }
+ }
+ if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
+ {
+ if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
+ {
+ bindingAttr &= ~BindingFlags.Static;
+ }
+ type = type.BaseType;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return list.ToArray();
+ }
+
+ public PropertyInfo GetProperty(string name)
+ {
+ return GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+ }
+
+ public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
+ {
+ foreach (PropertyInfo prop in GetProperties(bindingAttr))
+ {
+ if (prop.Name == name)
+ {
+ return prop;
+ }
+ }
+ return null;
+ }
+
+ public PropertyInfo GetProperty(string name, Type returnType)
+ {
+ PropertyInfo found = null;
+ foreach (PropertyInfo prop in GetProperties())
+ {
+ if (prop.Name == name && prop.PropertyType.Equals(returnType))
+ {
+ if (found != null)
+ {
+ throw new AmbiguousMatchException();
+ }
+ found = prop;
+ }
+ }
+ return found;
+ }
+
+ public PropertyInfo GetProperty(string name, Type[] types)
+ {
+ PropertyInfo found = null;
+ foreach (PropertyInfo prop in GetProperties())
+ {
+ if (prop.Name == name && MatchParameterTypes(prop.GetIndexParameters(), types))
+ {
+ if (found != null)
+ {
+ throw new AmbiguousMatchException();
+ }
+ found = prop;
+ }
+ }
+ return found;
+ }
+
+ private static bool MatchParameterTypes(ParameterInfo[] parameters, Type[] types)
+ {
+ if (parameters.Length == types.Length)
+ {
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ if (!parameters[i].ParameterType.Equals(types[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public PropertyInfo GetProperty(string name, Type returnType, Type[] types)
+ {
+ return GetProperty(name, returnType, types, null);
+ }
+
+ public PropertyInfo GetProperty(string name, Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ return GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, null, returnType, types, modifiers);
+ }
+
+ public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ PropertyInfo found = null;
+ foreach (PropertyInfo prop in GetProperties(bindingAttr))
+ {
+ if (prop.Name == name && prop.PropertyType.Equals(returnType) && MatchParameterTypes(prop.GetIndexParameters(), types))
+ {
+ if (found != null)
+ {
+ throw new AmbiguousMatchException();
+ }
+ found = prop;
+ }
+ }
+ return found;
+ }
+
+ public Type GetInterface(string name)
+ {
+ return GetInterface(name, false);
+ }
+
+ public Type GetInterface(string name, bool ignoreCase)
+ {
+ if (ignoreCase)
+ {
+ throw new NotImplementedException();
+ }
+ foreach (Type type in GetInterfaces())
+ {
+ if (type.FullName == name)
+ {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ public Type[] FindInterfaces(TypeFilter filter, object filterCriteria)
+ {
+ List<Type> list = new List<Type>();
+ foreach (Type type in GetInterfaces())
+ {
+ if (filter(type, filterCriteria))
+ {
+ list.Add(type);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public ConstructorInfo TypeInitializer
+ {
+ get { return GetConstructor(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); }
+ }
+
+ public bool IsPrimitive
+ {
+ get
+ {
+ Universe u = this.Module.universe;
+ return this == u.System_Boolean
+ || this == u.System_Byte
+ || this == u.System_SByte
+ || this == u.System_Int16
+ || this == u.System_UInt16
+ || this == u.System_Int32
+ || this == u.System_UInt32
+ || this == u.System_Int64
+ || this == u.System_UInt64
+ || this == u.System_IntPtr
+ || this == u.System_UIntPtr
+ || this == u.System_Char
+ || this == u.System_Double
+ || this == u.System_Single
+ ;
+ }
+ }
+
+ public bool IsEnum
+ {
+ get { return this.BaseType == this.Module.universe.System_Enum; }
+ }
+
+ public bool IsSealed
+ {
+ get { return (Attributes & TypeAttributes.Sealed) != 0; }
+ }
+
+ public bool IsAbstract
+ {
+ get { return (Attributes & TypeAttributes.Abstract) != 0; }
+ }
+
+ private bool CheckVisibility(TypeAttributes access)
+ {
+ return (Attributes & TypeAttributes.VisibilityMask) == access;
+ }
+
+ public bool IsPublic
+ {
+ get { return CheckVisibility(TypeAttributes.Public); }
+ }
+
+ public bool IsNestedPublic
+ {
+ get { return CheckVisibility(TypeAttributes.NestedPublic); }
+ }
+
+ public bool IsNestedPrivate
+ {
+ get { return CheckVisibility(TypeAttributes.NestedPrivate); }
+ }
+
+ public bool IsNestedFamily
+ {
+ get { return CheckVisibility(TypeAttributes.NestedFamily); }
+ }
+
+ public bool IsNestedAssembly
+ {
+ get { return CheckVisibility(TypeAttributes.NestedAssembly); }
+ }
+
+ public bool IsNestedFamANDAssem
+ {
+ get { return CheckVisibility(TypeAttributes.NestedFamANDAssem); }
+ }
+
+ public bool IsNestedFamORAssem
+ {
+ get { return CheckVisibility(TypeAttributes.NestedFamORAssem); }
+ }
+
+ public bool IsNotPublic
+ {
+ get { return CheckVisibility(TypeAttributes.NotPublic); }
+ }
+
+ public bool IsImport
+ {
+ get { return (Attributes & TypeAttributes.Import) != 0; }
+ }
+
+ public bool IsCOMObject
+ {
+ get { return IsClass && IsImport; }
+ }
+
+ public bool IsContextful
+ {
+ get { return IsSubclassOf(this.Module.universe.Import(typeof(ContextBoundObject))); }
+ }
+
+ public bool IsMarshalByRef
+ {
+ get { return IsSubclassOf(this.Module.universe.Import(typeof(MarshalByRefObject))); }
+ }
+
+ public virtual bool IsVisible
+ {
+ get { return IsPublic || (IsNestedPublic && this.DeclaringType.IsVisible); }
+ }
+
+ public bool IsAnsiClass
+ {
+ get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass; }
+ }
+
+ public bool IsUnicodeClass
+ {
+ get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass; }
+ }
+
+ public bool IsAutoClass
+ {
+ get { return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass; }
+ }
+
+ public bool IsAutoLayout
+ {
+ get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout; }
+ }
+
+ public bool IsLayoutSequential
+ {
+ get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout; }
+ }
+
+ public bool IsExplicitLayout
+ {
+ get { return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout; }
+ }
+
+ public bool IsSpecialName
+ {
+ get { return (Attributes & TypeAttributes.SpecialName) != 0; }
+ }
+
+ public bool IsSerializable
+ {
+ get { return (Attributes & TypeAttributes.Serializable) != 0; }
+ }
+
+ public bool IsClass
+ {
+ get { return !IsInterface && !IsValueType; }
+ }
+
+ public bool IsInterface
+ {
+ get { return (Attributes & TypeAttributes.Interface) != 0; }
+ }
+
+ public bool IsNested
+ {
+ // FXBUG we check the declaring type (like .NET) and this results
+ // in IsNested returning true for a generic type parameter
+ get { return this.DeclaringType != null; }
+ }
+
+ public Type MakeArrayType()
+ {
+ return ArrayType.Make(this, null, null);
+ }
+
+ public Type __MakeArrayType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return ArrayType.Make(this, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+ }
+
+ public Type MakeArrayType(int rank)
+ {
+ return MultiArrayType.Make(this, rank, null, null);
+ }
+
+ public Type __MakeArrayType(int rank, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return MultiArrayType.Make(this, rank, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+ }
+
+ public Type MakeByRefType()
+ {
+ return ByRefType.Make(this, null, null);
+ }
+
+ public Type __MakeByRefType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return ByRefType.Make(this, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+ }
+
+ public Type MakePointerType()
+ {
+ return PointerType.Make(this, null, null);
+ }
+
+ public Type __MakePointerType(Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return PointerType.Make(this, Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+ }
+
+ public Type MakeGenericType(params Type[] typeArguments)
+ {
+ return __MakeGenericType(typeArguments, null, null);
+ }
+
+ public Type __MakeGenericType(Type[] typeArguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ if (!this.IsGenericTypeDefinition)
+ {
+ throw new InvalidOperationException();
+ }
+ return GenericTypeInstance.Make(this, Util.Copy(typeArguments), Util.Copy(requiredCustomModifiers), Util.Copy(optionalCustomModifiers));
+ }
+
+ public static System.Type __GetSystemType(TypeCode typeCode)
+ {
+ switch (typeCode)
+ {
+ case TypeCode.Boolean:
+ return typeof(System.Boolean);
+ case TypeCode.Byte:
+ return typeof(System.Byte);
+ case TypeCode.Char:
+ return typeof(System.Char);
+ case TypeCode.DBNull:
+ return typeof(System.DBNull);
+ case TypeCode.DateTime:
+ return typeof(System.DateTime);
+ case TypeCode.Decimal:
+ return typeof(System.Decimal);
+ case TypeCode.Double:
+ return typeof(System.Double);
+ case TypeCode.Empty:
+ return null;
+ case TypeCode.Int16:
+ return typeof(System.Int16);
+ case TypeCode.Int32:
+ return typeof(System.Int32);
+ case TypeCode.Int64:
+ return typeof(System.Int64);
+ case TypeCode.Object:
+ return typeof(System.Object);
+ case TypeCode.SByte:
+ return typeof(System.SByte);
+ case TypeCode.Single:
+ return typeof(System.Single);
+ case TypeCode.String:
+ return typeof(System.String);
+ case TypeCode.UInt16:
+ return typeof(System.UInt16);
+ case TypeCode.UInt32:
+ return typeof(System.UInt32);
+ case TypeCode.UInt64:
+ return typeof(System.UInt64);
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public static TypeCode GetTypeCode(Type type)
+ {
+ if (type == null)
+ {
+ return TypeCode.Empty;
+ }
+ if (type.IsEnum)
+ {
+ type = type.GetEnumUnderlyingType();
+ }
+ Universe u = type.Module.universe;
+ if (type == u.System_Boolean)
+ {
+ return TypeCode.Boolean;
+ }
+ else if (type == u.System_Char)
+ {
+ return TypeCode.Char;
+ }
+ else if (type == u.System_SByte)
+ {
+ return TypeCode.SByte;
+ }
+ else if (type == u.System_Byte)
+ {
+ return TypeCode.Byte;
+ }
+ else if (type == u.System_Int16)
+ {
+ return TypeCode.Int16;
+ }
+ else if (type == u.System_UInt16)
+ {
+ return TypeCode.UInt16;
+ }
+ else if (type == u.System_Int32)
+ {
+ return TypeCode.Int32;
+ }
+ else if (type == u.System_UInt32)
+ {
+ return TypeCode.UInt32;
+ }
+ else if (type == u.System_Int64)
+ {
+ return TypeCode.Int64;
+ }
+ else if (type == u.System_UInt64)
+ {
+ return TypeCode.UInt64;
+ }
+ else if (type == u.System_Single)
+ {
+ return TypeCode.Single;
+ }
+ else if (type == u.System_Double)
+ {
+ return TypeCode.Double;
+ }
+ else if (type == u.System_DateTime)
+ {
+ return TypeCode.DateTime;
+ }
+ else if (type == u.System_DBNull)
+ {
+ return TypeCode.DBNull;
+ }
+ else if (type == u.System_Decimal)
+ {
+ return TypeCode.Decimal;
+ }
+ else if (type == u.System_String)
+ {
+ return TypeCode.String;
+ }
+ else
+ {
+ return TypeCode.Object;
+ }
+ }
+
+ public Assembly Assembly
+ {
+ get { return Module.Assembly; }
+ }
+
+ // note that interface/delegate co- and contravariance is not considered
+ public bool IsAssignableFrom(Type type)
+ {
+ if (this.Equals(type))
+ {
+ return true;
+ }
+ else if (type == null)
+ {
+ return false;
+ }
+ else if (this.IsArray && type.IsArray)
+ {
+ if (this.GetArrayRank() != type.GetArrayRank())
+ {
+ return false;
+ }
+ else if (this.__IsVector && !type.__IsVector)
+ {
+ return false;
+ }
+ Type e1 = this.GetElementType();
+ Type e2 = type.GetElementType();
+ return e1.IsValueType == e2.IsValueType && e1.IsAssignableFrom(e2);
+ }
+ else if (this.IsSealed)
+ {
+ return false;
+ }
+ else if (this.IsInterface)
+ {
+ return Array.IndexOf(type.GetInterfaces(), this) != -1;
+ }
+ else if (type.IsInterface)
+ {
+ return this == this.Module.universe.System_Object;
+ }
+ else if (type.IsPointer)
+ {
+ return this == this.Module.universe.System_Object || this == this.Module.universe.System_ValueType;
+ }
+ else
+ {
+ return type.IsSubclassOf(this);
+ }
+ }
+
+ public bool IsSubclassOf(Type type)
+ {
+ Type thisType = this.BaseType;
+ while (thisType != null)
+ {
+ if (thisType.Equals(type))
+ {
+ return true;
+ }
+ thisType = thisType.BaseType;
+ }
+ return false;
+ }
+
+ // This returns true if this type directly (i.e. not inherited from the base class) implements the interface.
+ // Note that a complicating factor is that the interface itself can be implemented by an interface that extends it.
+ private bool IsDirectlyImplementedInterface(Type interfaceType)
+ {
+ foreach (Type iface in __GetDeclaredInterfaces())
+ {
+ if (interfaceType.IsAssignableFrom(iface))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ CheckBaked();
+ InterfaceMapping map = new InterfaceMapping();
+ if (!IsDirectlyImplementedInterface(interfaceType))
+ {
+ Type baseType = this.BaseType;
+ if (baseType == null)
+ {
+ throw new ArgumentException();
+ }
+ else
+ {
+ map = baseType.GetInterfaceMap(interfaceType);
+ }
+ }
+ else
+ {
+ map.InterfaceMethods = interfaceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
+ map.InterfaceType = interfaceType;
+ map.TargetMethods = new MethodInfo[map.InterfaceMethods.Length];
+ FillInExplicitInterfaceMethods(map.InterfaceMethods, map.TargetMethods);
+ MethodInfo[] methods = GetMethods(BindingFlags.Instance | BindingFlags.Public);
+ for (int i = 0; i < map.TargetMethods.Length; i++)
+ {
+ if (map.TargetMethods[i] == null)
+ {
+ // TODO use proper method resolution (also take into account that no implicit base class implementation is used across assembly boundaries)
+ for (int j = 0; j < methods.Length; j++)
+ {
+ if (methods[j].Name == map.InterfaceMethods[i].Name
+ && methods[j].MethodSignature.Equals(map.InterfaceMethods[i].MethodSignature))
+ {
+ map.TargetMethods[i] = methods[j];
+ }
+ }
+ }
+ }
+ for (Type baseType = this.BaseType; baseType != null && interfaceType.IsAssignableFrom(baseType); baseType = baseType.BaseType)
+ {
+ baseType.FillInExplicitInterfaceMethods(map.InterfaceMethods, map.TargetMethods);
+ }
+ }
+ map.TargetType = this;
+ return map;
+ }
+
+ internal void FillInExplicitInterfaceMethods(MethodInfo[] interfaceMethods, MethodInfo[] targetMethods)
+ {
+ __MethodImplMap impl = __GetMethodImplMap();
+ for (int i = 0; i < impl.MethodDeclarations.Length; i++)
+ {
+ for (int j = 0; j < impl.MethodDeclarations[i].Length; j++)
+ {
+ int index = Array.IndexOf(interfaceMethods, impl.MethodDeclarations[i][j]);
+ if (index != -1 && targetMethods[index] == null)
+ {
+ targetMethods[index] = impl.MethodBodies[i];
+ }
+ }
+ }
+ }
+
+ Type IGenericContext.GetGenericTypeArgument(int index)
+ {
+ return GetGenericTypeArgument(index);
+ }
+
+ Type IGenericContext.GetGenericMethodArgument(int index)
+ {
+ throw new BadImageFormatException();
+ }
+
+ Type IGenericBinder.BindTypeParameter(Type type)
+ {
+ return GetGenericTypeArgument(type.GenericParameterPosition);
+ }
+
+ Type IGenericBinder.BindMethodParameter(Type type)
+ {
+ throw new BadImageFormatException();
+ }
+
+ internal virtual Type BindTypeParameters(IGenericBinder binder)
+ {
+ if (IsGenericTypeDefinition)
+ {
+ Type[] args = GetGenericArguments();
+ Type.InplaceBindTypeParameters(binder, args);
+ return GenericTypeInstance.Make(this, args, null, null);
+ }
+ else
+ {
+ return this;
+ }
+ }
+
+ internal static void InplaceBindTypeParameters(IGenericBinder binder, Type[] types)
+ {
+ for (int i = 0; i < types.Length; i++)
+ {
+ types[i] = types[i].BindTypeParameters(binder);
+ }
+ }
+
+ internal MethodBase FindMethod(string name, MethodSignature signature)
+ {
+ foreach (MethodBase method in __GetDeclaredMethods())
+ {
+ if (method.Name == name && method.MethodSignature.Equals(signature))
+ {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ internal FieldInfo FindField(string name, FieldSignature signature)
+ {
+ foreach (FieldInfo field in __GetDeclaredFields())
+ {
+ if (field.Name == name && field.FieldSignature.Equals(signature))
+ {
+ return field;
+ }
+ }
+ return null;
+ }
+
+ internal bool IsAllowMultipleCustomAttribute
+ {
+ get
+ {
+ IList<CustomAttributeData> cad = GetCustomAttributesData(this.Module.universe.System_AttributeUsageAttribute);
+ if (cad.Count == 1)
+ {
+ foreach (CustomAttributeNamedArgument arg in cad[0].NamedArguments)
+ {
+ if (arg.MemberInfo.Name == "AllowMultiple")
+ {
+ return (bool)arg.TypedValue.Value;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ internal bool IsPseudoCustomAttribute
+ {
+ get
+ {
+ Universe u = this.Module.universe;
+ return this == u.System_NonSerializedAttribute
+ || this == u.System_SerializableAttribute
+ || this == u.System_Runtime_InteropServices_DllImportAttribute
+ || this == u.System_Runtime_InteropServices_FieldOffsetAttribute
+ || this == u.System_Runtime_InteropServices_InAttribute
+ || this == u.System_Runtime_InteropServices_MarshalAsAttribute
+ || this == u.System_Runtime_InteropServices_OutAttribute
+ || this == u.System_Runtime_InteropServices_StructLayoutAttribute
+ || this == u.System_Runtime_InteropServices_OptionalAttribute
+ || this == u.System_Runtime_InteropServices_PreserveSigAttribute
+ || this == u.System_Runtime_InteropServices_ComImportAttribute
+ || this == u.System_Runtime_CompilerServices_SpecialNameAttribute
+ || this == u.System_Runtime_CompilerServices_MethodImplAttribute
+ ;
+ }
+ }
+ }
+
+ abstract class ElementHolderType : Type
+ {
+ protected readonly Type elementType;
+ private int token;
+ private readonly Type[] requiredCustomModifiers;
+ private readonly Type[] optionalCustomModifiers;
+
+ protected ElementHolderType(Type elementType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ this.elementType = elementType;
+ this.requiredCustomModifiers = requiredCustomModifiers;
+ this.optionalCustomModifiers = optionalCustomModifiers;
+ }
+
+ protected bool EqualsHelper(ElementHolderType other)
+ {
+ return other != null
+ && other.elementType.Equals(elementType)
+ && Util.ArrayEquals(other.requiredCustomModifiers, requiredCustomModifiers)
+ && Util.ArrayEquals(other.optionalCustomModifiers, optionalCustomModifiers);
+ }
+
+ public override Type[] __GetRequiredCustomModifiers()
+ {
+ return Util.Copy(requiredCustomModifiers);
+ }
+
+ public override Type[] __GetOptionalCustomModifiers()
+ {
+ return Util.Copy(optionalCustomModifiers);
+ }
+
+ public sealed override string Name
+ {
+ get { return elementType.Name + GetSuffix(); }
+ }
+
+ public sealed override string FullName
+ {
+ get { return elementType.FullName + GetSuffix(); }
+ }
+
+ public sealed override string ToString()
+ {
+ return elementType.ToString() + GetSuffix();
+ }
+
+ public sealed override Type GetElementType()
+ {
+ return elementType;
+ }
+
+ public sealed override bool HasElementType
+ {
+ get { return true; }
+ }
+
+ public sealed override Module Module
+ {
+ get { return elementType.Module; }
+ }
+
+ internal sealed override int GetModuleBuilderToken()
+ {
+ if (token == 0)
+ {
+ token = ((ModuleBuilder)elementType.Module).ImportType(this);
+ }
+ return token;
+ }
+
+ public sealed override bool ContainsGenericParameters
+ {
+ get
+ {
+ Type type = elementType;
+ while (type.HasElementType)
+ {
+ type = type.GetElementType();
+ }
+ return type.ContainsGenericParameters;
+ }
+ }
+
+ internal sealed override Type BindTypeParameters(IGenericBinder binder)
+ {
+ Type type = elementType.BindTypeParameters(binder);
+ Type[] req = BindArray(requiredCustomModifiers, binder);
+ Type[] opt = BindArray(optionalCustomModifiers, binder);
+ if (ReferenceEquals(type, elementType)
+ && ReferenceEquals(req, requiredCustomModifiers)
+ && ReferenceEquals(opt, optionalCustomModifiers))
+ {
+ return this;
+ }
+ return Wrap(type, req, opt);
+ }
+
+ internal override void CheckBaked()
+ {
+ elementType.CheckBaked();
+ }
+
+ private static Type[] BindArray(Type[] array, IGenericBinder binder)
+ {
+ if (array ==null || array.Length == 0)
+ {
+ return array;
+ }
+ Type[] result = array;
+ for (int i = 0; i < array.Length; i++)
+ {
+ Type type = array[i].BindTypeParameters(binder);
+ if (!ReferenceEquals(type, array[i]))
+ {
+ if (result == array)
+ {
+ result = (Type[])array.Clone();
+ }
+ result[i] = type;
+ }
+ }
+ return result;
+ }
+
+ internal sealed override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return CustomAttributeData.EmptyList;
+ }
+
+ protected abstract string GetSuffix();
+
+ protected abstract Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers);
+ }
+
+ sealed class ArrayType : ElementHolderType
+ {
+ internal static Type Make(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return type.Module.CanonicalizeType(new ArrayType(type, requiredCustomModifiers, optionalCustomModifiers));
+ }
+
+ private ArrayType(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ : base(type, requiredCustomModifiers, optionalCustomModifiers)
+ {
+ }
+
+ public override Type BaseType
+ {
+ get { return elementType.Module.universe.System_Array; }
+ }
+
+ public override Type[] __GetDeclaredInterfaces()
+ {
+ return new Type[] {
+ this.Module.universe.Import(typeof(IList<>)).MakeGenericType(elementType),
+ this.Module.universe.Import(typeof(ICollection<>)).MakeGenericType(elementType),
+ this.Module.universe.Import(typeof(IEnumerable<>)).MakeGenericType(elementType)
+ };
+ }
+
+ public override MethodBase[] __GetDeclaredMethods()
+ {
+ Type[] int32 = new Type[] { this.Module.universe.System_Int32 };
+ List<MethodBase> list = new List<MethodBase>();
+ list.Add(new BuiltinArrayMethod(this.Module, this, "Set", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, new Type[] { this.Module.universe.System_Int32, elementType }));
+ list.Add(new BuiltinArrayMethod(this.Module, this, "Address", CallingConventions.Standard | CallingConventions.HasThis, elementType.MakeByRefType(), int32));
+ list.Add(new BuiltinArrayMethod(this.Module, this, "Get", CallingConventions.Standard | CallingConventions.HasThis, elementType, int32));
+ list.Add(new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, int32)));
+ for (Type type = elementType; type.__IsVector; type = type.GetElementType())
+ {
+ Array.Resize(ref int32, int32.Length + 1);
+ int32[int32.Length - 1] = int32[0];
+ list.Add(new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, int32)));
+ }
+ return list.ToArray();
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable; }
+ }
+
+ public override bool IsArray
+ {
+ get { return true; }
+ }
+
+ public override bool __IsVector
+ {
+ get { return true; }
+ }
+
+ public override int GetArrayRank()
+ {
+ return 1;
+ }
+
+ public override bool Equals(object o)
+ {
+ return EqualsHelper(o as ArrayType);
+ }
+
+ public override int GetHashCode()
+ {
+ return elementType.GetHashCode() * 5;
+ }
+
+ protected override string GetSuffix()
+ {
+ return "[]";
+ }
+
+ protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return Make(type, requiredCustomModifiers, optionalCustomModifiers);
+ }
+ }
+
+ sealed class MultiArrayType : ElementHolderType
+ {
+ private readonly int rank;
+
+ internal static Type Make(Type type, int rank, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return type.Module.CanonicalizeType(new MultiArrayType(type, rank, requiredCustomModifiers, optionalCustomModifiers));
+ }
+
+ private MultiArrayType(Type type, int rank, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ : base(type, requiredCustomModifiers, optionalCustomModifiers)
+ {
+ this.rank = rank;
+ }
+
+ public override Type BaseType
+ {
+ get { return elementType.Module.universe.System_Array; }
+ }
+
+ public override MethodBase[] __GetDeclaredMethods()
+ {
+ Type int32 = this.Module.universe.System_Int32;
+ Type[] setArgs = new Type[rank + 1];
+ Type[] getArgs = new Type[rank];
+ Type[] ctorArgs = new Type[rank * 2];
+ for (int i = 0; i < rank; i++)
+ {
+ setArgs[i] = int32;
+ getArgs[i] = int32;
+ ctorArgs[i * 2 + 0] = int32;
+ ctorArgs[i * 2 + 1] = int32;
+ }
+ setArgs[rank] = elementType;
+ return new MethodBase[] {
+ new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, getArgs)),
+ new ConstructorInfoImpl(new BuiltinArrayMethod(this.Module, this, ".ctor", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, ctorArgs)),
+ new BuiltinArrayMethod(this.Module, this, "Set", CallingConventions.Standard | CallingConventions.HasThis, this.Module.universe.System_Void, setArgs),
+ new BuiltinArrayMethod(this.Module, this, "Address", CallingConventions.Standard | CallingConventions.HasThis, elementType.MakeByRefType(), getArgs),
+ new BuiltinArrayMethod(this.Module, this, "Get", CallingConventions.Standard | CallingConventions.HasThis, elementType, getArgs),
+ };
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable; }
+ }
+
+ public override bool IsArray
+ {
+ get { return true; }
+ }
+
+ public override int GetArrayRank()
+ {
+ return rank;
+ }
+
+ public override bool Equals(object o)
+ {
+ MultiArrayType at = o as MultiArrayType;
+ return EqualsHelper(at) && at.rank == rank;
+ }
+
+ public override int GetHashCode()
+ {
+ return elementType.GetHashCode() * 9 + rank;
+ }
+
+ protected override string GetSuffix()
+ {
+ if (rank == 1)
+ {
+ return "[*]";
+ }
+ else
+ {
+ return "[" + new String(',', rank - 1) + "]";
+ }
+ }
+
+ protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return Make(type, rank, requiredCustomModifiers, optionalCustomModifiers);
+ }
+ }
+
+ sealed class BuiltinArrayMethod : ArrayMethod
+ {
+ internal BuiltinArrayMethod(Module module, Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ : base(module, arrayClass, methodName, callingConvention, returnType, parameterTypes)
+ {
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return this.Name == ".ctor" ? MethodAttributes.RTSpecialName | MethodAttributes.Public : MethodAttributes.Public; }
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return MethodImplAttributes.IL;
+ }
+
+ public override int MetadataToken
+ {
+ get { return 0x06000000; }
+ }
+
+ public override MethodBody GetMethodBody()
+ {
+ return null;
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ ParameterInfo[] parameterInfos = new ParameterInfo[parameterTypes.Length];
+ for (int i = 0; i < parameterInfos.Length; i++)
+ {
+ parameterInfos[i] = new ParameterInfoImpl(this, parameterTypes[i], i);
+ }
+ return parameterInfos;
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get { return new ParameterInfoImpl(this, this.ReturnType, -1); }
+ }
+
+ private sealed class ParameterInfoImpl : ParameterInfo
+ {
+ private readonly MethodInfo method;
+ private readonly Type type;
+ private readonly int pos;
+
+ internal ParameterInfoImpl(MethodInfo method, Type type, int pos)
+ {
+ this.method = method;
+ this.type = type;
+ this.pos = pos;
+ }
+
+ public override Type ParameterType
+ {
+ get { return type; }
+ }
+
+ public override string Name
+ {
+ get { return null; }
+ }
+
+ public override ParameterAttributes Attributes
+ {
+ get { return ParameterAttributes.None; }
+ }
+
+ public override int Position
+ {
+ get { return pos; }
+ }
+
+ public override object RawDefaultValue
+ {
+ get { return null; }
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return Empty<Type>.Array;
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return Empty<Type>.Array;
+ }
+
+ public override MemberInfo Member
+ {
+ get { return method.IsConstructor ? (MethodBase)new ConstructorInfoImpl(method) : method; }
+ }
+
+ public override int MetadataToken
+ {
+ get { return 0x8000000; }
+ }
+
+ internal override Module Module
+ {
+ get { return method.Module; }
+ }
+ }
+ }
+
+ sealed class ByRefType : ElementHolderType
+ {
+ internal static Type Make(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return type.Module.CanonicalizeType(new ByRefType(type, requiredCustomModifiers, optionalCustomModifiers));
+ }
+
+ private ByRefType(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ : base(type, requiredCustomModifiers, optionalCustomModifiers)
+ {
+ }
+
+ public override bool Equals(object o)
+ {
+ return EqualsHelper(o as ByRefType);
+ }
+
+ public override int GetHashCode()
+ {
+ return elementType.GetHashCode() * 3;
+ }
+
+ public override Type BaseType
+ {
+ get { return null; }
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return 0; }
+ }
+
+ public override bool IsByRef
+ {
+ get { return true; }
+ }
+
+ protected override string GetSuffix()
+ {
+ return "&";
+ }
+
+ protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return Make(type, requiredCustomModifiers, optionalCustomModifiers);
+ }
+ }
+
+ sealed class PointerType : ElementHolderType
+ {
+ internal static Type Make(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return type.Module.CanonicalizeType(new PointerType(type, requiredCustomModifiers, optionalCustomModifiers));
+ }
+
+ private PointerType(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ : base(type, requiredCustomModifiers, optionalCustomModifiers)
+ {
+ }
+
+ public override bool Equals(object o)
+ {
+ return EqualsHelper(o as PointerType);
+ }
+
+ public override int GetHashCode()
+ {
+ return elementType.GetHashCode() * 7;
+ }
+
+ public override Type BaseType
+ {
+ get { return null; }
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return 0; }
+ }
+
+ public override bool IsPointer
+ {
+ get { return true; }
+ }
+
+ protected override string GetSuffix()
+ {
+ return "*";
+ }
+
+ protected override Type Wrap(Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ return Make(type, requiredCustomModifiers, optionalCustomModifiers);
+ }
+ }
+
+ sealed class GenericTypeInstance : Type
+ {
+ private readonly Type type;
+ private readonly Type[] args;
+ private readonly Type[][] requiredCustomModifiers;
+ private readonly Type[][] optionalCustomModifiers;
+ private Type baseType;
+ private int token;
+
+ internal static Type Make(Type type, Type[] typeArguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ bool identity = true;
+ if (type is TypeBuilder || type is BakedType)
+ {
+ // a TypeBuiler identity must be instantiated
+ identity = false;
+ }
+ else
+ {
+ // we must not instantiate the identity instance, because typeof(Foo<>).MakeGenericType(typeof(Foo<>).GetGenericArguments()) == typeof(Foo<>)
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ if (typeArguments[i] != type.GetGenericTypeArgument(i)
+ || !IsEmpty(requiredCustomModifiers, i)
+ || !IsEmpty(optionalCustomModifiers, i))
+ {
+ identity = false;
+ break;
+ }
+ }
+ }
+ if (identity)
+ {
+ return type;
+ }
+ else
+ {
+ return type.Module.CanonicalizeType(new GenericTypeInstance(type, typeArguments, requiredCustomModifiers, optionalCustomModifiers));
+ }
+ }
+
+ private static bool IsEmpty(Type[][] mods, int i)
+ {
+ // we need to be extra careful, because mods doesn't not need to be in canonical format
+ // (Signature.ReadGenericInst() calls Make() directly, without copying the modifier arrays)
+ return mods == null || mods[i] == null || mods[i].Length == 0;
+ }
+
+ private GenericTypeInstance(Type type, Type[] args, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ this.type = type;
+ this.args = args;
+ this.requiredCustomModifiers = requiredCustomModifiers;
+ this.optionalCustomModifiers = optionalCustomModifiers;
+ }
+
+ public override bool Equals(object o)
+ {
+ GenericTypeInstance gt = o as GenericTypeInstance;
+ return gt != null && gt.type.Equals(type) && Util.ArrayEquals(gt.args, args)
+ && Util.ArrayEquals(gt.requiredCustomModifiers, requiredCustomModifiers)
+ && Util.ArrayEquals(gt.optionalCustomModifiers, optionalCustomModifiers);
+ }
+
+ public override int GetHashCode()
+ {
+ return type.GetHashCode() * 3 ^ Util.GetHashCode(args);
+ }
+
+ public override string AssemblyQualifiedName
+ {
+ get
+ {
+ string fn = FullName;
+ return fn == null ? null : fn + ", " + type.Assembly.FullName;
+ }
+ }
+
+ public override Type BaseType
+ {
+ get
+ {
+ if (baseType == null)
+ {
+ Type rawBaseType = type.BaseType;
+ if (rawBaseType == null)
+ {
+ baseType = rawBaseType;
+ }
+ else
+ {
+ baseType = rawBaseType.BindTypeParameters(this);
+ }
+ }
+ return baseType;
+ }
+ }
+
+ public override bool IsValueType
+ {
+ get { return type.IsValueType; }
+ }
+
+ public override bool IsVisible
+ {
+ get
+ {
+ if (base.IsVisible)
+ {
+ foreach (Type arg in args)
+ {
+ if (!arg.IsVisible)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return type.DeclaringType; }
+ }
+
+ public override TypeAttributes Attributes
+ {
+ get { return type.Attributes; }
+ }
+
+ internal override void CheckBaked()
+ {
+ type.CheckBaked();
+ }
+
+ public override FieldInfo[] __GetDeclaredFields()
+ {
+ FieldInfo[] fields = type.__GetDeclaredFields();
+ for (int i = 0; i < fields.Length; i++)
+ {
+ fields[i] = fields[i].BindTypeParameters(this);
+ }
+ return fields;
+ }
+
+ public override Type[] __GetDeclaredInterfaces()
+ {
+ Type[] interfaces = type.__GetDeclaredInterfaces();
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ interfaces[i] = interfaces[i].BindTypeParameters(this);
+ }
+ return interfaces;
+ }
+
+ public override MethodBase[] __GetDeclaredMethods()
+ {
+ MethodBase[] methods = type.__GetDeclaredMethods();
+ for (int i = 0; i < methods.Length; i++)
+ {
+ methods[i] = methods[i].BindTypeParameters(this);
+ }
+ return methods;
+ }
+
+ public override Type[] __GetDeclaredTypes()
+ {
+ return type.__GetDeclaredTypes();
+ }
+
+ public override EventInfo[] __GetDeclaredEvents()
+ {
+ EventInfo[] events = type.__GetDeclaredEvents();
+ for (int i = 0; i < events.Length; i++)
+ {
+ events[i] = events[i].BindTypeParameters(this);
+ }
+ return events;
+ }
+
+ public override PropertyInfo[] __GetDeclaredProperties()
+ {
+ PropertyInfo[] properties = type.__GetDeclaredProperties();
+ for (int i = 0; i < properties.Length; i++)
+ {
+ properties[i] = properties[i].BindTypeParameters(this);
+ }
+ return properties;
+ }
+
+ public override __MethodImplMap __GetMethodImplMap()
+ {
+ __MethodImplMap map = type.__GetMethodImplMap();
+ map.TargetType = this;
+ for (int i = 0; i < map.MethodBodies.Length; i++)
+ {
+ map.MethodBodies[i] = (MethodInfo)map.MethodBodies[i].BindTypeParameters(this);
+ for (int j = 0; j < map.MethodDeclarations[i].Length; j++)
+ {
+ Type interfaceType = map.MethodDeclarations[i][j].DeclaringType;
+ if (interfaceType.IsGenericType)
+ {
+ map.MethodDeclarations[i][j] = (MethodInfo)map.MethodDeclarations[i][j].BindTypeParameters(this);
+ }
+ }
+ }
+ return map;
+ }
+
+ public override string Namespace
+ {
+ get { return type.Namespace; }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get { return this; }
+ }
+
+ public override string Name
+ {
+ get { return type.Name; }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ if (this.ContainsGenericParameters)
+ {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder(base.FullName);
+ sb.Append('[');
+ foreach (Type type in args)
+ {
+ sb.Append('[').Append(type.AssemblyQualifiedName.Replace("]", "\\]")).Append(']');
+ }
+ sb.Append(']');
+ return sb.ToString();
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(type.FullName);
+ sb.Append('[');
+ string sep = "";
+ foreach (Type arg in args)
+ {
+ sb.Append(sep);
+ sb.Append(arg);
+ sep = ",";
+ }
+ sb.Append(']');
+ return sb.ToString();
+ }
+
+ public override Module Module
+ {
+ get { return type.Module; }
+ }
+
+ public override bool IsGenericType
+ {
+ get { return true; }
+ }
+
+ public override Type GetGenericTypeDefinition()
+ {
+ return type;
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ return Util.Copy(args);
+ }
+
+ public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
+ {
+ return Util.Copy(requiredCustomModifiers ?? new Type[args.Length][]);
+ }
+
+ public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+ {
+ return Util.Copy(optionalCustomModifiers ?? new Type[args.Length][]);
+ }
+
+ internal override Type GetGenericTypeArgument(int index)
+ {
+ return args[index];
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ foreach (Type type in args)
+ {
+ if (type.ContainsGenericParameters)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public override StructLayoutAttribute StructLayoutAttribute
+ {
+ get { return type.StructLayoutAttribute; }
+ }
+
+ internal override int GetModuleBuilderToken()
+ {
+ if (token == 0)
+ {
+ token = ((ModuleBuilder)type.Module).ImportType(this);
+ }
+ return token;
+ }
+
+ internal override Type BindTypeParameters(IGenericBinder binder)
+ {
+ for (int i = 0; i < args.Length; i++)
+ {
+ Type xarg = args[i].BindTypeParameters(binder);
+ if (!ReferenceEquals(xarg, args[i]))
+ {
+ Type[] xargs = new Type[args.Length];
+ Array.Copy(args, xargs, i);
+ xargs[i++] = xarg;
+ for (; i < args.Length; i++)
+ {
+ xargs[i] = args[i].BindTypeParameters(binder);
+ }
+ return Make(type, xargs, null, null);
+ }
+ }
+ return this;
+ }
+
+ internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+ {
+ return type.GetCustomAttributesData(attributeType);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace IKVM.Reflection
+{
+ struct TypeNameParser
+ {
+ private const string SpecialChars = "\\+,[]*&";
+ private const short SZARRAY = -1;
+ private const short BYREF = -2;
+ private const short POINTER = -3;
+ private readonly string name;
+ private readonly string[] nested;
+ private readonly string assemblyName;
+ private readonly short[] modifiers;
+ private readonly TypeNameParser[] genericParameters;
+
+ internal static string Escape(string name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+ StringBuilder sb = null;
+ for (int pos = 0; pos < name.Length; pos++)
+ {
+ char c = name[pos];
+ if (SpecialChars.IndexOf(c) != -1)
+ {
+ if (sb == null)
+ {
+ sb = new StringBuilder(name, 0, pos, name.Length + 3);
+ }
+ sb.Append('\\').Append(c);
+ }
+ else if (sb != null)
+ {
+ sb.Append(c);
+ }
+ }
+ return sb != null ? sb.ToString() : name;
+ }
+
+ internal static string Unescape(string name)
+ {
+ int pos = name.IndexOf('\\');
+ if (pos == -1)
+ {
+ return name;
+ }
+ StringBuilder sb = new StringBuilder(name, 0, pos, name.Length - 1);
+ for (; pos < name.Length; pos++)
+ {
+ char c = name[pos];
+ if (c == '\\')
+ {
+ c = name[++pos];
+ }
+ sb.Append(c);
+ }
+ return sb.ToString();
+ }
+
+ internal static TypeNameParser Parse(string typeName, bool throwOnError)
+ {
+ if (throwOnError)
+ {
+ Parser parser = new Parser(typeName);
+ return new TypeNameParser(ref parser, true);
+ }
+ else
+ {
+ try
+ {
+ Parser parser = new Parser(typeName);
+ return new TypeNameParser(ref parser, true);
+ }
+ catch (ArgumentException)
+ {
+ return new TypeNameParser();
+ }
+ }
+ }
+
+ private TypeNameParser(ref Parser parser, bool withAssemblyName)
+ {
+ bool genericParameter = parser.pos != 0;
+ name = parser.NextNamePart();
+ nested = null;
+ parser.ParseNested(ref nested);
+ genericParameters = null;
+ parser.ParseGenericParameters(ref genericParameters);
+ modifiers = null;
+ parser.ParseModifiers(ref modifiers);
+ assemblyName = null;
+ if (withAssemblyName)
+ {
+ parser.ParseAssemblyName(genericParameter, ref assemblyName);
+ }
+ }
+
+ internal bool Error
+ {
+ get { return name == null; }
+ }
+
+ internal string FirstNamePart
+ {
+ get { return name; }
+ }
+
+ internal string AssemblyName
+ {
+ get { return assemblyName; }
+ }
+
+ private struct Parser
+ {
+ private readonly string typeName;
+ internal int pos;
+
+ internal Parser(string typeName)
+ {
+ this.typeName = typeName;
+ this.pos = 0;
+ }
+
+ private void Check(bool condition)
+ {
+ if (!condition)
+ {
+ throw new ArgumentException("Invalid type name '" + typeName + "'");
+ }
+ }
+
+ private void Consume(char c)
+ {
+ Check(pos < typeName.Length && typeName[pos++] == c);
+ }
+
+ private bool TryConsume(char c)
+ {
+ if (pos < typeName.Length && typeName[pos] == c)
+ {
+ pos++;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ internal string NextNamePart()
+ {
+ SkipWhiteSpace();
+ int start = pos;
+ for (; pos < typeName.Length; pos++)
+ {
+ char c = typeName[pos];
+ if (c == '\\')
+ {
+ pos++;
+ Check(pos < typeName.Length && SpecialChars.IndexOf(typeName[pos]) != -1);
+ }
+ else if (SpecialChars.IndexOf(c) != -1)
+ {
+ break;
+ }
+ }
+ Check(pos - start != 0);
+ if (start == 0 && pos == typeName.Length)
+ {
+ return typeName;
+ }
+ else
+ {
+ return typeName.Substring(start, pos - start);
+ }
+ }
+
+ internal void ParseNested(ref string[] nested)
+ {
+ while (TryConsume('+'))
+ {
+ Add(ref nested, NextNamePart());
+ }
+ }
+
+ internal void ParseGenericParameters(ref TypeNameParser[] genericParameters)
+ {
+ int saved = pos;
+ if (TryConsume('['))
+ {
+ SkipWhiteSpace();
+ if (TryConsume(']') || TryConsume('*') || TryConsume(','))
+ {
+ // it's not a generic parameter list, but an array instead
+ pos = saved;
+ return;
+ }
+ do
+ {
+ SkipWhiteSpace();
+ if (TryConsume('['))
+ {
+ Add(ref genericParameters, new TypeNameParser(ref this, true));
+ Consume(']');
+ }
+ else
+ {
+ Add(ref genericParameters, new TypeNameParser(ref this, false));
+ }
+ }
+ while (TryConsume(','));
+ Consume(']');
+ SkipWhiteSpace();
+ }
+ }
+
+ internal void ParseModifiers(ref short[] modifiers)
+ {
+ while (pos < typeName.Length)
+ {
+ switch (typeName[pos])
+ {
+ case '*':
+ pos++;
+ Add(ref modifiers, POINTER);
+ break;
+ case '&':
+ pos++;
+ Add(ref modifiers, BYREF);
+ break;
+ case '[':
+ pos++;
+ Add(ref modifiers, ParseArray());
+ Consume(']');
+ break;
+ default:
+ return;
+ }
+ SkipWhiteSpace();
+ }
+ }
+
+ internal void ParseAssemblyName(bool genericParameter, ref string assemblyName)
+ {
+ if (pos < typeName.Length)
+ {
+ if (typeName[pos] == ']' && genericParameter)
+ {
+ // ok
+ }
+ else
+ {
+ Consume(',');
+ SkipWhiteSpace();
+ if (genericParameter)
+ {
+ int start = pos;
+ while (pos < typeName.Length)
+ {
+ char c = typeName[pos];
+ if (c == '\\')
+ {
+ pos++;
+ // a backslash itself is not legal in an assembly name, so we don't need to check for an escaped backslash
+ Check(pos < typeName.Length && typeName[pos++] == ']');
+ }
+ else if (c == ']')
+ {
+ break;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+ Check(pos < typeName.Length && typeName[pos] == ']');
+ assemblyName = typeName.Substring(start, pos - start).Replace("\\]", "]");
+ }
+ else
+ {
+ // only when an assembly name is used in a generic type parameter, will it be escaped
+ assemblyName = typeName.Substring(pos);
+ }
+ Check(assemblyName.Length != 0);
+ }
+ }
+ else
+ {
+ Check(!genericParameter);
+ }
+ }
+
+ private short ParseArray()
+ {
+ SkipWhiteSpace();
+ Check(pos < typeName.Length);
+ char c = typeName[pos];
+ if (c == ']')
+ {
+ return SZARRAY;
+ }
+ else if (c == '*')
+ {
+ pos++;
+ SkipWhiteSpace();
+ return 1;
+ }
+ else
+ {
+ short rank = 1;
+ while (TryConsume(','))
+ {
+ Check(rank < short.MaxValue);
+ rank++;
+ SkipWhiteSpace();
+ }
+ return rank;
+ }
+ }
+
+ private void SkipWhiteSpace()
+ {
+ while (pos < typeName.Length && Char.IsWhiteSpace(typeName[pos]))
+ {
+ pos++;
+ }
+ }
+
+ private static void Add<T>(ref T[] array, T elem)
+ {
+ if (array == null)
+ {
+ array = new T[] { elem };
+ return;
+ }
+ Array.Resize(ref array, array.Length + 1);
+ array[array.Length - 1] = elem;
+ }
+ }
+
+ internal Type GetType(Universe universe, Assembly context, bool throwOnError, string originalName)
+ {
+ Type type;
+ if (assemblyName != null)
+ {
+ Assembly asm = universe.Load(assemblyName, context, throwOnError);
+ if (asm == null)
+ {
+ return null;
+ }
+ type = asm.GetTypeImpl(name);
+ }
+ else if (context == null)
+ {
+ type = universe.Mscorlib.GetTypeImpl(name);
+ }
+ else
+ {
+ type = context.GetTypeImpl(name);
+ if (type == null && context != universe.Mscorlib)
+ {
+ type = universe.Mscorlib.GetTypeImpl(name);
+ }
+ }
+ return Expand(type, context, throwOnError, originalName);
+ }
+
+ internal Type Expand(Type type, Assembly context, bool throwOnError, string originalName)
+ {
+ if (type == null)
+ {
+ if (throwOnError)
+ {
+ throw new TypeLoadException(originalName);
+ }
+ return null;
+ }
+ if (nested != null)
+ {
+ foreach (string nest in nested)
+ {
+ type = type.GetNestedType(nest, BindingFlags.Public | BindingFlags.NonPublic);
+ if (type == null)
+ {
+ if (throwOnError)
+ {
+ throw new TypeLoadException(originalName);
+ }
+ return null;
+ }
+ }
+ }
+ if (genericParameters != null)
+ {
+ Type[] typeArgs = new Type[genericParameters.Length];
+ for (int i = 0; i < typeArgs.Length; i++)
+ {
+ typeArgs[i] = genericParameters[i].GetType(type.Assembly.universe, context, throwOnError, originalName);
+ if (typeArgs[i] == null)
+ {
+ return null;
+ }
+ }
+ type = type.MakeGenericType(typeArgs);
+ }
+ if (modifiers != null)
+ {
+ foreach (short modifier in modifiers)
+ {
+ switch (modifier)
+ {
+ case SZARRAY:
+ type = type.MakeArrayType();
+ break;
+ case BYREF:
+ type = type.MakeByRefType();
+ break;
+ case POINTER:
+ type = type.MakePointerType();
+ break;
+ default:
+ type = type.MakeArrayType(modifier);
+ break;
+ }
+ }
+ }
+ return type;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2009-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security;
+using System.Text;
+using System.Diagnostics;
+using IKVM.Reflection.Reader;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection
+{
+ public class ResolveEventArgs : EventArgs
+ {
+ private readonly string name;
+ private readonly Assembly requestingAssembly;
+
+ public ResolveEventArgs(string name)
+ : this(name, null)
+ {
+ }
+
+ public ResolveEventArgs(string name, Assembly requestingAssembly)
+ {
+ this.name = name;
+ this.requestingAssembly = requestingAssembly;
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public Assembly RequestingAssembly
+ {
+ get { return requestingAssembly; }
+ }
+ }
+
+ public enum AssemblyComparisonResult
+ {
+ Unknown = 0,
+ EquivalentFullMatch = 1,
+ EquivalentWeakNamed = 2,
+ EquivalentFXUnified = 3,
+ EquivalentUnified = 4,
+ NonEquivalentVersion = 5,
+ NonEquivalent = 6,
+ EquivalentPartialMatch = 7,
+ EquivalentPartialWeakNamed = 8,
+ EquivalentPartialUnified = 9,
+ EquivalentPartialFXUnified = 10,
+ NonEquivalentPartialVersion = 11,
+ }
+
+ public delegate Assembly ResolveEventHandler(object sender, ResolveEventArgs args);
+
+ public sealed class Universe : IDisposable
+ {
+ internal readonly Dictionary<Type, Type> canonicalizedTypes = new Dictionary<Type, Type>();
+ private readonly List<Assembly> assemblies = new List<Assembly>();
+ private readonly List<AssemblyBuilder> dynamicAssemblies = new List<AssemblyBuilder>();
+ private readonly Dictionary<string, Assembly> assembliesByName = new Dictionary<string, Assembly>();
+ private readonly Dictionary<System.Type, Type> importedTypes = new Dictionary<System.Type, Type>();
+ private Type typeof_System_Object;
+ private Type typeof_System_ValueType;
+ private Type typeof_System_Enum;
+ private Type typeof_System_Void;
+ private Type typeof_System_Boolean;
+ private Type typeof_System_Char;
+ private Type typeof_System_SByte;
+ private Type typeof_System_Byte;
+ private Type typeof_System_Int16;
+ private Type typeof_System_UInt16;
+ private Type typeof_System_Int32;
+ private Type typeof_System_UInt32;
+ private Type typeof_System_Int64;
+ private Type typeof_System_UInt64;
+ private Type typeof_System_Single;
+ private Type typeof_System_Double;
+ private Type typeof_System_String;
+ private Type typeof_System_IntPtr;
+ private Type typeof_System_UIntPtr;
+ private Type typeof_System_TypedReference;
+ private Type typeof_System_Type;
+ private Type typeof_System_Array;
+ private Type typeof_System_DateTime;
+ private Type typeof_System_DBNull;
+ private Type typeof_System_Decimal;
+ private Type typeof_System_NonSerializedAttribute;
+ private Type typeof_System_SerializableAttribute;
+ private Type typeof_System_AttributeUsageAttribute;
+ private Type typeof_System_Reflection_AssemblyCultureAttribute;
+ private Type typeof_System_Runtime_InteropServices_DllImportAttribute;
+ private Type typeof_System_Runtime_InteropServices_FieldOffsetAttribute;
+ private Type typeof_System_Runtime_InteropServices_InAttribute;
+ private Type typeof_System_Runtime_InteropServices_MarshalAsAttribute;
+ private Type typeof_System_Runtime_InteropServices_UnmanagedType;
+ private Type typeof_System_Runtime_InteropServices_VarEnum;
+ private Type typeof_System_Runtime_InteropServices_OutAttribute;
+ private Type typeof_System_Runtime_InteropServices_StructLayoutAttribute;
+ private Type typeof_System_Runtime_InteropServices_OptionalAttribute;
+ private Type typeof_System_Runtime_InteropServices_PreserveSigAttribute;
+ private Type typeof_System_Runtime_InteropServices_ComImportAttribute;
+ private Type typeof_System_Runtime_CompilerServices_DecimalConstantAttribute;
+ private Type typeof_System_Runtime_CompilerServices_SpecialNameAttribute;
+ private Type typeof_System_Runtime_CompilerServices_MethodImplAttribute;
+ private Type typeof_System_Security_SuppressUnmanagedCodeSecurityAttribute;
+ private Type typeof_System_Reflection_AssemblyCopyrightAttribute;
+ private Type typeof_System_Reflection_AssemblyTrademarkAttribute;
+ private Type typeof_System_Reflection_AssemblyProductAttribute;
+ private Type typeof_System_Reflection_AssemblyCompanyAttribute;
+ private Type typeof_System_Reflection_AssemblyDescriptionAttribute;
+ private Type typeof_System_Reflection_AssemblyTitleAttribute;
+ private Type typeof_System_Reflection_AssemblyInformationalVersionAttribute;
+ private Type typeof_System_Reflection_AssemblyFileVersionAttribute;
+ private Type typeof_System_Security_Permissions_CodeAccessSecurityAttribute;
+ private Type typeof_System_Security_Permissions_HostProtectionAttribute;
+ private Type typeof_System_Security_Permissions_PermissionSetAttribute;
+ private Type typeof_System_Security_Permissions_SecurityAction;
+ private List<ResolveEventHandler> resolvers = new List<ResolveEventHandler>();
+
+ internal Assembly Mscorlib
+ {
+ get { return Load("mscorlib"); }
+ }
+
+ private Type ImportMscorlibType(System.Type type)
+ {
+ return Mscorlib.GetTypeImpl(type.FullName);
+ }
+
+ internal Type System_Object
+ {
+ get { return typeof_System_Object ?? (typeof_System_Object = ImportMscorlibType(typeof(System.Object))); }
+ }
+
+ internal Type System_ValueType
+ {
+ get { return typeof_System_ValueType ?? (typeof_System_ValueType = ImportMscorlibType(typeof(System.ValueType))); }
+ }
+
+ internal Type System_Enum
+ {
+ get { return typeof_System_Enum ?? (typeof_System_Enum = ImportMscorlibType(typeof(System.Enum))); }
+ }
+
+ internal Type System_Void
+ {
+ get { return typeof_System_Void ?? (typeof_System_Void = ImportMscorlibType(typeof(void))); }
+ }
+
+ internal Type System_Boolean
+ {
+ get { return typeof_System_Boolean ?? (typeof_System_Boolean = ImportMscorlibType(typeof(System.Boolean))); }
+ }
+
+ internal Type System_Char
+ {
+ get { return typeof_System_Char ?? (typeof_System_Char = ImportMscorlibType(typeof(System.Char))); }
+ }
+
+ internal Type System_SByte
+ {
+ get { return typeof_System_SByte ?? (typeof_System_SByte = ImportMscorlibType(typeof(System.SByte))); }
+ }
+
+ internal Type System_Byte
+ {
+ get { return typeof_System_Byte ?? (typeof_System_Byte = ImportMscorlibType(typeof(System.Byte))); }
+ }
+
+ internal Type System_Int16
+ {
+ get { return typeof_System_Int16 ?? (typeof_System_Int16 = ImportMscorlibType(typeof(System.Int16))); }
+ }
+
+ internal Type System_UInt16
+ {
+ get { return typeof_System_UInt16 ?? (typeof_System_UInt16 = ImportMscorlibType(typeof(System.UInt16))); }
+ }
+
+ internal Type System_Int32
+ {
+ get { return typeof_System_Int32 ?? (typeof_System_Int32 = ImportMscorlibType(typeof(System.Int32))); }
+ }
+
+ internal Type System_UInt32
+ {
+ get { return typeof_System_UInt32 ?? (typeof_System_UInt32 = ImportMscorlibType(typeof(System.UInt32))); }
+ }
+
+ internal Type System_Int64
+ {
+ get { return typeof_System_Int64 ?? (typeof_System_Int64 = ImportMscorlibType(typeof(System.Int64))); }
+ }
+
+ internal Type System_UInt64
+ {
+ get { return typeof_System_UInt64 ?? (typeof_System_UInt64 = ImportMscorlibType(typeof(System.UInt64))); }
+ }
+
+ internal Type System_Single
+ {
+ get { return typeof_System_Single ?? (typeof_System_Single = ImportMscorlibType(typeof(System.Single))); }
+ }
+
+ internal Type System_Double
+ {
+ get { return typeof_System_Double ?? (typeof_System_Double = ImportMscorlibType(typeof(System.Double))); }
+ }
+
+ internal Type System_String
+ {
+ get { return typeof_System_String ?? (typeof_System_String = ImportMscorlibType(typeof(System.String))); }
+ }
+
+ internal Type System_IntPtr
+ {
+ get { return typeof_System_IntPtr ?? (typeof_System_IntPtr = ImportMscorlibType(typeof(System.IntPtr))); }
+ }
+
+ internal Type System_UIntPtr
+ {
+ get { return typeof_System_UIntPtr ?? (typeof_System_UIntPtr = ImportMscorlibType(typeof(System.UIntPtr))); }
+ }
+
+ internal Type System_TypedReference
+ {
+ get { return typeof_System_TypedReference ?? (typeof_System_TypedReference = ImportMscorlibType(typeof(System.TypedReference))); }
+ }
+
+ internal Type System_Type
+ {
+ get { return typeof_System_Type ?? (typeof_System_Type = ImportMscorlibType(typeof(System.Type))); }
+ }
+
+ internal Type System_Array
+ {
+ get { return typeof_System_Array ?? (typeof_System_Array = ImportMscorlibType(typeof(System.Array))); }
+ }
+
+ internal Type System_DateTime
+ {
+ get { return typeof_System_DateTime ?? (typeof_System_DateTime = ImportMscorlibType(typeof(System.DateTime))); }
+ }
+
+ internal Type System_DBNull
+ {
+ get { return typeof_System_DBNull ?? (typeof_System_DBNull = ImportMscorlibType(typeof(System.DBNull))); }
+ }
+
+ internal Type System_Decimal
+ {
+ get { return typeof_System_Decimal ?? (typeof_System_Decimal = ImportMscorlibType(typeof(System.Decimal))); }
+ }
+
+ internal Type System_NonSerializedAttribute
+ {
+ get { return typeof_System_NonSerializedAttribute ?? (typeof_System_NonSerializedAttribute = ImportMscorlibType(typeof(System.NonSerializedAttribute))); }
+ }
+
+ internal Type System_SerializableAttribute
+ {
+ get { return typeof_System_SerializableAttribute ?? (typeof_System_SerializableAttribute = ImportMscorlibType(typeof(System.SerializableAttribute))); }
+ }
+
+ internal Type System_AttributeUsageAttribute
+ {
+ get { return typeof_System_AttributeUsageAttribute ?? (typeof_System_AttributeUsageAttribute = ImportMscorlibType(typeof(System.AttributeUsageAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyCultureAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyCultureAttribute ?? (typeof_System_Reflection_AssemblyCultureAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyCultureAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_DllImportAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_DllImportAttribute ?? (typeof_System_Runtime_InteropServices_DllImportAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.DllImportAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_FieldOffsetAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_FieldOffsetAttribute ?? (typeof_System_Runtime_InteropServices_FieldOffsetAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.FieldOffsetAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_InAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_InAttribute ?? (typeof_System_Runtime_InteropServices_InAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.InAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_MarshalAsAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_MarshalAsAttribute ?? (typeof_System_Runtime_InteropServices_MarshalAsAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.MarshalAsAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_UnmanagedType
+ {
+ get { return typeof_System_Runtime_InteropServices_UnmanagedType ?? (typeof_System_Runtime_InteropServices_UnmanagedType = ImportMscorlibType(typeof(System.Runtime.InteropServices.UnmanagedType))); }
+ }
+
+ internal Type System_Runtime_InteropServices_VarEnum
+ {
+ get { return typeof_System_Runtime_InteropServices_VarEnum ?? (typeof_System_Runtime_InteropServices_VarEnum = ImportMscorlibType(typeof(System.Runtime.InteropServices.VarEnum))); }
+ }
+
+ internal Type System_Runtime_InteropServices_OutAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_OutAttribute ?? (typeof_System_Runtime_InteropServices_OutAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.OutAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_StructLayoutAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_StructLayoutAttribute ?? (typeof_System_Runtime_InteropServices_StructLayoutAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.StructLayoutAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_OptionalAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_OptionalAttribute ?? (typeof_System_Runtime_InteropServices_OptionalAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.OptionalAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_PreserveSigAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_PreserveSigAttribute ?? (typeof_System_Runtime_InteropServices_PreserveSigAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.PreserveSigAttribute))); }
+ }
+
+ internal Type System_Runtime_InteropServices_ComImportAttribute
+ {
+ get { return typeof_System_Runtime_InteropServices_ComImportAttribute ?? (typeof_System_Runtime_InteropServices_ComImportAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.ComImportAttribute))); }
+ }
+
+ internal Type System_Runtime_CompilerServices_DecimalConstantAttribute
+ {
+ get { return typeof_System_Runtime_CompilerServices_DecimalConstantAttribute ?? (typeof_System_Runtime_CompilerServices_DecimalConstantAttribute = ImportMscorlibType(typeof(System.Runtime.CompilerServices.DecimalConstantAttribute))); }
+ }
+
+ internal Type System_Runtime_CompilerServices_SpecialNameAttribute
+ {
+ get { return typeof_System_Runtime_CompilerServices_SpecialNameAttribute ?? (typeof_System_Runtime_CompilerServices_SpecialNameAttribute = ImportMscorlibType(typeof(System.Runtime.CompilerServices.SpecialNameAttribute))); }
+ }
+
+ internal Type System_Runtime_CompilerServices_MethodImplAttribute
+ {
+ get { return typeof_System_Runtime_CompilerServices_MethodImplAttribute ?? (typeof_System_Runtime_CompilerServices_MethodImplAttribute = ImportMscorlibType(typeof(System.Runtime.CompilerServices.MethodImplAttribute))); }
+ }
+
+ internal Type System_Security_SuppressUnmanagedCodeSecurityAttribute
+ {
+ get { return typeof_System_Security_SuppressUnmanagedCodeSecurityAttribute ?? (typeof_System_Security_SuppressUnmanagedCodeSecurityAttribute = ImportMscorlibType(typeof(System.Security.SuppressUnmanagedCodeSecurityAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyCopyrightAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyCopyrightAttribute ?? (typeof_System_Reflection_AssemblyCopyrightAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyCopyrightAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyTrademarkAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyTrademarkAttribute ?? (typeof_System_Reflection_AssemblyTrademarkAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyTrademarkAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyProductAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyProductAttribute ?? (typeof_System_Reflection_AssemblyProductAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyProductAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyCompanyAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyCompanyAttribute ?? (typeof_System_Reflection_AssemblyCompanyAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyCompanyAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyDescriptionAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyDescriptionAttribute ?? (typeof_System_Reflection_AssemblyDescriptionAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyDescriptionAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyTitleAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyTitleAttribute ?? (typeof_System_Reflection_AssemblyTitleAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyTitleAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyInformationalVersionAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyInformationalVersionAttribute ?? (typeof_System_Reflection_AssemblyInformationalVersionAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyInformationalVersionAttribute))); }
+ }
+
+ internal Type System_Reflection_AssemblyFileVersionAttribute
+ {
+ get { return typeof_System_Reflection_AssemblyFileVersionAttribute ?? (typeof_System_Reflection_AssemblyFileVersionAttribute = ImportMscorlibType(typeof(System.Reflection.AssemblyFileVersionAttribute))); }
+ }
+
+ internal Type System_Security_Permissions_CodeAccessSecurityAttribute
+ {
+ get { return typeof_System_Security_Permissions_CodeAccessSecurityAttribute ?? (typeof_System_Security_Permissions_CodeAccessSecurityAttribute = ImportMscorlibType(typeof(System.Security.Permissions.CodeAccessSecurityAttribute))); }
+ }
+
+ internal Type System_Security_Permissions_HostProtectionAttribute
+ {
+ get { return typeof_System_Security_Permissions_HostProtectionAttribute ?? (typeof_System_Security_Permissions_HostProtectionAttribute = ImportMscorlibType(typeof(System.Security.Permissions.HostProtectionAttribute))); }
+ }
+
+ internal Type System_Security_Permissions_PermissionSetAttribute
+ {
+ get { return typeof_System_Security_Permissions_PermissionSetAttribute ?? (typeof_System_Security_Permissions_PermissionSetAttribute = ImportMscorlibType(typeof(System.Security.Permissions.PermissionSetAttribute))); }
+ }
+
+ internal Type System_Security_Permissions_SecurityAction
+ {
+ get { return typeof_System_Security_Permissions_SecurityAction ?? (typeof_System_Security_Permissions_SecurityAction = ImportMscorlibType(typeof(System.Security.Permissions.SecurityAction))); }
+ }
+
+ internal bool HasMscorlib
+ {
+ get { return GetLoadedAssembly("mscorlib") != null; }
+ }
+
+ public event ResolveEventHandler AssemblyResolve
+ {
+ add { resolvers.Add(value); }
+ remove { resolvers.Remove(value); }
+ }
+
+ public Type Import(System.Type type)
+ {
+ Type imported;
+ if (!importedTypes.TryGetValue(type, out imported))
+ {
+ imported = ImportImpl(type);
+ if (imported != null)
+ {
+ importedTypes.Add(type, imported);
+ }
+ }
+ return imported;
+ }
+
+ private Type ImportImpl(System.Type type)
+ {
+ if (type.Assembly == typeof(IKVM.Reflection.Type).Assembly)
+ {
+ throw new ArgumentException("Did you really want to import " + type.FullName + "?");
+ }
+ if (type.HasElementType)
+ {
+ if (type.IsArray)
+ {
+ if (type.Name.EndsWith("[]"))
+ {
+ return Import(type.GetElementType()).MakeArrayType();
+ }
+ else
+ {
+ return Import(type.GetElementType()).MakeArrayType(type.GetArrayRank());
+ }
+ }
+ else if (type.IsByRef)
+ {
+ return Import(type.GetElementType()).MakeByRefType();
+ }
+ else if (type.IsPointer)
+ {
+ return Import(type.GetElementType()).MakePointerType();
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ else if (type.IsGenericParameter)
+ {
+ if (type.DeclaringMethod != null)
+ {
+ throw new NotImplementedException();
+ }
+ else
+ {
+ return Import(type.DeclaringType).GetGenericArguments()[type.GenericParameterPosition];
+ }
+ }
+ else if (type.IsGenericType && !type.IsGenericTypeDefinition)
+ {
+ System.Type[] args = type.GetGenericArguments();
+ Type[] importedArgs = new Type[args.Length];
+ for (int i = 0; i < args.Length; i++)
+ {
+ importedArgs[i] = Import(args[i]);
+ }
+ return Import(type.GetGenericTypeDefinition()).MakeGenericType(importedArgs);
+ }
+ else
+ {
+ return Import(type.Assembly).GetType(type.FullName);
+ }
+ }
+
+ private Assembly Import(System.Reflection.Assembly asm)
+ {
+ return Load(asm.FullName);
+ }
+
+ public RawModule OpenRawModule(string path)
+ {
+ path = Path.GetFullPath(path);
+ return OpenRawModule(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read), path);
+ }
+
+ public RawModule OpenRawModule(Stream stream, string location)
+ {
+ if (!stream.CanRead || !stream.CanSeek)
+ {
+ throw new NotSupportedException();
+ }
+ return new RawModule(new ModuleReader(null, this, stream, location));
+ }
+
+ public Assembly LoadAssembly(RawModule module)
+ {
+ string refname = module.GetAssemblyName().FullName;
+ Assembly asm = GetLoadedAssembly(refname);
+ if (asm == null)
+ {
+ asm = module.ToAssembly();
+ assemblies.Add(asm);
+ }
+ return asm;
+ }
+
+ public Assembly LoadFile(string path)
+ {
+ try
+ {
+ using (RawModule module = OpenRawModule(path))
+ {
+ return LoadAssembly(module);
+ }
+ }
+ catch (IOException x)
+ {
+ throw new FileNotFoundException(x.Message, x);
+ }
+ catch (UnauthorizedAccessException x)
+ {
+ throw new FileNotFoundException(x.Message, x);
+ }
+ }
+
+ private Assembly GetLoadedAssembly(string refname)
+ {
+ Assembly asm;
+ if (!assembliesByName.TryGetValue(refname, out asm))
+ {
+ for (int i = 0; i < assemblies.Count; i++)
+ {
+ AssemblyComparisonResult result;
+ // We won't allow FX unification here, because our own (non-Fusion) implementation of CompareAssemblyIdentity doesn't support it and
+ // we don't want to create a fundamental functional difference based on that.
+ if (CompareAssemblyIdentity(refname, false, assemblies[i].FullName, false, out result) && result != AssemblyComparisonResult.EquivalentFXUnified)
+ {
+ asm = assemblies[i];
+ assembliesByName.Add(refname, asm);
+ break;
+ }
+ }
+ }
+ return asm;
+ }
+
+ private Assembly GetDynamicAssembly(string refname)
+ {
+ foreach (AssemblyBuilder asm in dynamicAssemblies)
+ {
+ AssemblyComparisonResult result;
+ // We won't allow FX unification here, because our own (non-Fusion) implementation of CompareAssemblyIdentity doesn't support it and
+ // we don't want to create a fundamental functional difference based on that.
+ if (CompareAssemblyIdentity(refname, false, asm.FullName, false, out result) && result != AssemblyComparisonResult.EquivalentFXUnified)
+ {
+ return asm;
+ }
+ }
+ return null;
+ }
+
+ public Assembly Load(string refname)
+ {
+ return Load(refname, null, true);
+ }
+
+ internal Assembly Load(string refname, Assembly requestingAssembly, bool throwOnError)
+ {
+ Assembly asm = GetLoadedAssembly(refname);
+ if (asm != null)
+ {
+ return asm;
+ }
+ if (resolvers.Count == 0)
+ {
+ asm = DefaultResolver(refname, throwOnError);
+ }
+ else
+ {
+ ResolveEventArgs args = new ResolveEventArgs(refname, requestingAssembly);
+ foreach (ResolveEventHandler evt in resolvers)
+ {
+ asm = evt(this, args);
+ if (asm != null)
+ {
+ break;
+ }
+ }
+ if (asm == null)
+ {
+ asm = GetDynamicAssembly(refname);
+ }
+ }
+ if (asm != null)
+ {
+ string defname = asm.FullName;
+ if (refname != defname)
+ {
+ assembliesByName.Add(refname, asm);
+ }
+ return asm;
+ }
+ if (throwOnError)
+ {
+ throw new FileNotFoundException(refname);
+ }
+ return null;
+ }
+
+ private Assembly DefaultResolver(string refname, bool throwOnError)
+ {
+ Assembly asm = GetDynamicAssembly(refname);
+ if (asm != null)
+ {
+ return asm;
+ }
+ string fileName;
+ if (throwOnError)
+ {
+ try
+ {
+ fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location;
+ }
+ catch (System.BadImageFormatException x)
+ {
+ throw new BadImageFormatException(x.Message, x);
+ }
+ }
+ else
+ {
+ try
+ {
+ fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location;
+ }
+ catch (System.BadImageFormatException x)
+ {
+ throw new BadImageFormatException(x.Message, x);
+ }
+ catch (FileNotFoundException)
+ {
+ // we intentionally only swallow the FileNotFoundException, if the file exists but isn't a valid assembly,
+ // we should throw an exception
+ return null;
+ }
+ }
+ return LoadFile(fileName);
+ }
+
+ public Type GetType(string assemblyQualifiedTypeName)
+ {
+ // to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(),
+ // import that assembly and pass it as the context, but implicitly importing is considered evil
+ return GetType(null, assemblyQualifiedTypeName, false);
+ }
+
+ public Type GetType(string assemblyQualifiedTypeName, bool throwOnError)
+ {
+ // to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(),
+ // import that assembly and pass it as the context, but implicitly importing is considered evil
+ return GetType(null, assemblyQualifiedTypeName, throwOnError);
+ }
+
+ // note that context is slightly different from the calling assembly (System.Type.GetType),
+ // because context is passed to the AssemblyResolve event as the RequestingAssembly
+ public Type GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError)
+ {
+ TypeNameParser parser = TypeNameParser.Parse(assemblyQualifiedTypeName, throwOnError);
+ if (parser.Error)
+ {
+ return null;
+ }
+ return parser.GetType(this, context, throwOnError, assemblyQualifiedTypeName);
+ }
+
+ public Assembly[] GetAssemblies()
+ {
+ Assembly[] array = new Assembly[assemblies.Count + dynamicAssemblies.Count];
+ assemblies.CopyTo(array);
+ for (int i = 0, j = assemblies.Count; j < array.Length; i++, j++)
+ {
+ array[j] = dynamicAssemblies[i];
+ }
+ return array;
+ }
+
+ // this is equivalent to the Fusion CompareAssemblyIdentity API
+ public bool CompareAssemblyIdentity(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
+ {
+ return Fusion.CompareAssemblyIdentity(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out result);
+ }
+
+ public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)
+ {
+ return DefineDynamicAssemblyImpl(name, access, null, null, null, null);
+ }
+
+ public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, string dir)
+ {
+ return DefineDynamicAssemblyImpl(name, access, dir, null, null, null);
+ }
+
+#if NET_4_0
+ [Obsolete]
+#endif
+ public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
+ {
+ return DefineDynamicAssemblyImpl(name, access, dir, requiredPermissions, optionalPermissions, refusedPermissions);
+ }
+
+ private AssemblyBuilder DefineDynamicAssemblyImpl(AssemblyName name, AssemblyBuilderAccess access, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
+ {
+ AssemblyBuilder asm = new AssemblyBuilder(this, name, dir, requiredPermissions, optionalPermissions, refusedPermissions);
+ dynamicAssemblies.Add(asm);
+ return asm;
+ }
+
+ internal void RenameAssembly(Assembly assembly, AssemblyName oldName)
+ {
+ List<string> remove = new List<string>();
+ foreach (KeyValuePair<string, Assembly> kv in assembliesByName)
+ {
+ if (kv.Value == assembly)
+ {
+ remove.Add(kv.Key);
+ }
+ }
+ foreach (string key in remove)
+ {
+ assembliesByName.Remove(key);
+ }
+ }
+
+ public void Dispose()
+ {
+ foreach (Assembly asm in assemblies)
+ {
+ foreach (Module mod in asm.GetLoadedModules())
+ {
+ mod.Dispose();
+ }
+ }
+ foreach (AssemblyBuilder asm in dynamicAssemblies)
+ {
+ foreach (Module mod in asm.GetLoadedModules())
+ {
+ mod.Dispose();
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008-2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace IKVM.Reflection
+{
+ public interface ICustomAttributeProvider
+ {
+ bool IsDefined(Type attributeType, bool inherit);
+ IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit);
+ }
+
+ [Serializable]
+ public sealed class FileFormatLimitationExceededException : InvalidOperationException
+ {
+ public const int META_E_STRINGSPACE_FULL = unchecked((int)0x80131198);
+
+ public FileFormatLimitationExceededException(string message, int hresult)
+ : base(message)
+ {
+ this.HResult = hresult;
+ }
+
+ private FileFormatLimitationExceededException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+ : base(info, context)
+ {
+ }
+
+ public int ErrorCode
+ {
+ get { return this.HResult; }
+ }
+ }
+
+ [Serializable]
+ public sealed class Missing : ISerializable
+ {
+ public static readonly Missing Value = new Missing();
+
+ private Missing() { }
+
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.SetType(typeof(SingletonSerializationHelper));
+ }
+
+ [Serializable]
+ private sealed class SingletonSerializationHelper : IObjectReference
+ {
+ public object GetRealObject(StreamingContext context)
+ {
+ return Value;
+ }
+ }
+ }
+
+ static class Empty<T>
+ {
+ internal static readonly T[] Array = new T[0];
+ }
+
+ static class Util
+ {
+ internal static Type[] Copy(Type[] array)
+ {
+ if (array == null || array.Length == 0)
+ {
+ return Type.EmptyTypes;
+ }
+ Type[] copy = new Type[array.Length];
+ Array.Copy(array, copy, array.Length);
+ return copy;
+ }
+
+ internal static Type[][] Copy(Type[][] types)
+ {
+ if (types == null || types.Length == 0)
+ {
+ return types;
+ }
+ Type[][] newArray = new Type[types.Length][];
+ for (int i = 0; i < newArray.Length; i++)
+ {
+ newArray[i] = Copy(types[i]);
+ }
+ return newArray;
+ }
+
+ internal static T[] ToArray<T, V>(List<V> list, T[] empty) where V : T
+ {
+ if (list == null || list.Count == 0)
+ {
+ return empty;
+ }
+ T[] array = new T[list.Count];
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i] = list[i];
+ }
+ return array;
+ }
+
+ // note that an empty array matches a null reference
+ internal static bool ArrayEquals(Type[] t1, Type[] t2)
+ {
+ if (t1 == t2)
+ {
+ return true;
+ }
+ if (t1 == null)
+ {
+ return t2.Length == 0;
+ }
+ else if (t2 == null)
+ {
+ return t1.Length == 0;
+ }
+ if (t1.Length == t2.Length)
+ {
+ for (int i = 0; i < t1.Length; i++)
+ {
+ if (!TypeEquals(t1[i], t2[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool ArrayEquals(Type[][] t1, Type[][] t2)
+ {
+ if (t1 == t2)
+ {
+ return true;
+ }
+ if (t1 == null)
+ {
+ return t2.Length == 0;
+ }
+ else if (t2 == null)
+ {
+ return t1.Length == 0;
+ }
+ if (t1.Length == t2.Length)
+ {
+ for (int i = 0; i < t1.Length; i++)
+ {
+ if (!ArrayEquals(t1[i], t2[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool ArrayEquals(Type[][][] t1, Type[][][] t2)
+ {
+ if (t1 == t2)
+ {
+ return true;
+ }
+ if (t1 == null)
+ {
+ return t2.Length == 0;
+ }
+ else if (t2 == null)
+ {
+ return t1.Length == 0;
+ }
+ if (t1.Length == t2.Length)
+ {
+ for (int i = 0; i < t1.Length; i++)
+ {
+ if (!ArrayEquals(t1[i], t2[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool TypeEquals(Type t1, Type t2)
+ {
+ if (t1 == t2)
+ {
+ return true;
+ }
+ if (t1 == null)
+ {
+ return false;
+ }
+ return t1.Equals(t2);
+ }
+
+ internal static int GetHashCode(Type[] types)
+ {
+ if (types == null)
+ {
+ return 0;
+ }
+ int h = 0;
+ foreach (Type t in types)
+ {
+ if (t != null)
+ {
+ h *= 3;
+ h ^= t.GetHashCode();
+ }
+ }
+ return h;
+ }
+
+ internal static int GetHashCode(Type[][] types)
+ {
+ int h = 0;
+ if (types != null)
+ {
+ foreach (Type[] array in types)
+ {
+ h ^= GetHashCode(array);
+ }
+ }
+ return h;
+ }
+
+ internal static int GetHashCode(Type[][][] types)
+ {
+ int h = 0;
+ if (types != null)
+ {
+ foreach (Type[][] array in types)
+ {
+ h ^= GetHashCode(array);
+ }
+ }
+ return h;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+ sealed class ByteBuffer
+ {
+ private byte[] buffer;
+ private int pos;
+ private int __length; // __length is only valid if > pos, otherwise pos is the current length
+
+ internal ByteBuffer(int initialCapacity)
+ {
+ buffer = new byte[initialCapacity];
+ }
+
+ private ByteBuffer(byte[] wrap, int length)
+ {
+ this.buffer = wrap;
+ this.pos = length;
+ }
+
+ internal int Position
+ {
+ get { return pos; }
+ set
+ {
+ if (value > this.Length || value > buffer.Length)
+ throw new ArgumentOutOfRangeException();
+ __length = Math.Max(__length, pos);
+ pos = value;
+ }
+ }
+
+ internal int Length
+ {
+ get { return Math.Max(pos, __length); }
+ }
+
+ private void Grow(int minGrow)
+ {
+ byte[] newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)];
+ Buffer.BlockCopy(buffer, 0, newbuf, 0, buffer.Length);
+ buffer = newbuf;
+ }
+
+ // NOTE this does not advance the position
+ internal int GetInt32AtCurrentPosition()
+ {
+ return buffer[pos]
+ + (buffer[pos + 1] << 8)
+ + (buffer[pos + 2] << 16)
+ + (buffer[pos + 3] << 24);
+ }
+
+ // NOTE this does not advance the position
+ internal byte GetByteAtCurrentPosition()
+ {
+ return buffer[pos];
+ }
+
+ internal void Write(byte[] value)
+ {
+ if (pos + value.Length > buffer.Length)
+ Grow(value.Length);
+ Buffer.BlockCopy(value, 0, buffer, pos, value.Length);
+ pos += value.Length;
+ }
+
+ internal void Write(byte value)
+ {
+ if (pos == buffer.Length)
+ Grow(1);
+ buffer[pos++] = value;
+ }
+
+ internal void Write(sbyte value)
+ {
+ Write((byte)value);
+ }
+
+ internal void Write(ushort value)
+ {
+ Write((short)value);
+ }
+
+ internal void Write(short value)
+ {
+ if (pos + 2 > buffer.Length)
+ Grow(2);
+ buffer[pos++] = (byte)value;
+ buffer[pos++] = (byte)(value >> 8);
+ }
+
+ internal void Write(uint value)
+ {
+ Write((int)value);
+ }
+
+ internal void Write(int value)
+ {
+ if (pos + 4 > buffer.Length)
+ Grow(4);
+ buffer[pos++] = (byte)value;
+ buffer[pos++] = (byte)(value >> 8);
+ buffer[pos++] = (byte)(value >> 16);
+ buffer[pos++] = (byte)(value >> 24);
+ }
+
+ internal void Write(ulong value)
+ {
+ Write((long)value);
+ }
+
+ internal void Write(long value)
+ {
+ if (pos + 8 > buffer.Length)
+ Grow(8);
+ buffer[pos++] = (byte)value;
+ buffer[pos++] = (byte)(value >> 8);
+ buffer[pos++] = (byte)(value >> 16);
+ buffer[pos++] = (byte)(value >> 24);
+ buffer[pos++] = (byte)(value >> 32);
+ buffer[pos++] = (byte)(value >> 40);
+ buffer[pos++] = (byte)(value >> 48);
+ buffer[pos++] = (byte)(value >> 56);
+ }
+
+ internal void Write(float value)
+ {
+ Write(BitConverter.GetBytes(value));
+ }
+
+ internal void Write(double value)
+ {
+ Write(BitConverter.DoubleToInt64Bits(value));
+ }
+
+ internal void Write(string str)
+ {
+ if (str == null)
+ {
+ Write((byte)0xFF);
+ }
+ else
+ {
+ byte[] buf = Encoding.UTF8.GetBytes(str);
+ WriteCompressedInt(buf.Length);
+ Write(buf);
+ }
+ }
+
+ internal void WriteCompressedInt(int value)
+ {
+ if (value <= 0x7F)
+ {
+ Write((byte)value);
+ }
+ else if (value <= 0x3FFF)
+ {
+ Write((byte)(0x80 | (value >> 8)));
+ Write((byte)value);
+ }
+ else
+ {
+ Write((byte)(0xC0 | (value >> 24)));
+ Write((byte)(value >> 16));
+ Write((byte)(value >> 8));
+ Write((byte)value);
+ }
+ }
+
+ internal void Write(ByteBuffer bb)
+ {
+ if (pos + bb.Length > buffer.Length)
+ Grow(bb.Length);
+ Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length);
+ pos += bb.Length;
+ }
+
+ internal void WriteTo(System.IO.Stream stream)
+ {
+ stream.Write(buffer, 0, this.Length);
+ }
+
+ internal void Clear()
+ {
+ pos = 0;
+ __length = 0;
+ }
+
+ internal void Align(int alignment)
+ {
+ if (pos + alignment > buffer.Length)
+ Grow(alignment);
+ int newpos = (pos + alignment - 1) & ~(alignment - 1);
+ while (pos < newpos)
+ buffer[pos++] = 0;
+ }
+
+ internal void WriteTypeDefOrRefEncoded(int token)
+ {
+ switch (token >> 24)
+ {
+ case TypeDefTable.Index:
+ WriteCompressedInt((token & 0xFFFFFF) << 2 | 0);
+ break;
+ case TypeRefTable.Index:
+ WriteCompressedInt((token & 0xFFFFFF) << 2 | 1);
+ break;
+ case TypeSpecTable.Index:
+ WriteCompressedInt((token & 0xFFFFFF) << 2 | 2);
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+
+ internal void Write(System.IO.Stream stream)
+ {
+ const int chunkSize = 8192;
+ for (; ; )
+ {
+ if (pos + chunkSize > buffer.Length)
+ Grow(chunkSize);
+ int read = stream.Read(buffer, pos, chunkSize);
+ if (read <= 0)
+ {
+ break;
+ }
+ pos += read;
+ }
+ }
+
+ internal byte[] ToArray()
+ {
+ byte[] buf = new byte[pos];
+ Buffer.BlockCopy(buffer, 0, buf, 0, pos);
+ return buf;
+ }
+
+ internal static ByteBuffer Wrap(byte[] buf)
+ {
+ return new ByteBuffer(buf, buf.Length);
+ }
+
+ internal static ByteBuffer Wrap(byte[] buf, int length)
+ {
+ return new ByteBuffer(buf, length);
+ }
+
+ internal bool Match(int pos, ByteBuffer bb2, int pos2, int len)
+ {
+ for (int i = 0; i < len; i++)
+ {
+ if (buffer[pos + i] != bb2.buffer[pos2 + i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ internal int Hash()
+ {
+ int hash = 0;
+ int len = this.Length;
+ for (int i = 0; i < len; i++)
+ {
+ hash *= 37;
+ hash ^= buffer[i];
+ }
+ return hash;
+ }
+
+ internal IKVM.Reflection.Reader.ByteReader GetBlob(int offset)
+ {
+ return IKVM.Reflection.Reader.ByteReader.FromBlob(buffer, offset);
+ }
+
+ internal void Patch(int offset, byte b)
+ {
+ buffer[offset] = b;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+ abstract class Heap
+ {
+ protected bool frozen;
+ protected int unalignedlength;
+
+ internal void Write(MetadataWriter mw)
+ {
+ int pos = mw.Position;
+ WriteImpl(mw);
+ Debug.Assert(mw.Position == pos + unalignedlength);
+ int align = Length - unalignedlength;
+ for (int i = 0; i < align; i++)
+ {
+ mw.Write((byte)0);
+ }
+ }
+
+ internal bool IsBig
+ {
+ get { return Length > 65535; }
+ }
+
+ internal int Length
+ {
+ get
+ {
+ if (!frozen)
+ throw new InvalidOperationException();
+ return (unalignedlength + 3) & ~3;
+ }
+ }
+
+ protected abstract void WriteImpl(MetadataWriter mw);
+ }
+
+ abstract class SimpleHeap : Heap
+ {
+ internal void Freeze()
+ {
+ if (frozen)
+ throw new InvalidOperationException();
+ frozen = true;
+ unalignedlength = GetLength();
+ }
+
+ protected abstract int GetLength();
+ }
+
+ sealed class TableHeap : Heap
+ {
+ internal void Freeze(MetadataWriter mw)
+ {
+ if (frozen)
+ throw new InvalidOperationException();
+ frozen = true;
+ unalignedlength = GetLength(mw);
+ }
+
+ protected override void WriteImpl(MetadataWriter mw)
+ {
+ Table[] tables = mw.ModuleBuilder.GetTables();
+ // Header
+ mw.Write(0); // Reserved
+ int ver = mw.ModuleBuilder.MDStreamVersion;
+ mw.Write((byte)(ver >> 16)); // MajorVersion
+ mw.Write((byte)ver); // MinorVersion
+ byte heapSizes = 0;
+ if (mw.ModuleBuilder.Strings.IsBig)
+ {
+ heapSizes |= 0x01;
+ }
+ if (mw.ModuleBuilder.Guids.IsBig)
+ {
+ heapSizes |= 0x02;
+ }
+ if (mw.ModuleBuilder.Blobs.IsBig)
+ {
+ heapSizes |= 0x04;
+ }
+ mw.Write(heapSizes);// HeapSizes
+ // LAMESPEC spec says reserved, but .NET 2.0 Ref.Emit sets it to 0x10
+ mw.Write((byte)0x10); // Reserved
+ long bit = 1;
+ long valid = 0;
+ foreach (Table table in tables)
+ {
+ if (table != null && table.RowCount > 0)
+ {
+ valid |= bit;
+ }
+ bit <<= 1;
+ }
+ mw.Write(valid); // Valid
+ mw.Write(0x0016003301FA00L); // Sorted
+ // Rows
+ foreach (Table table in tables)
+ {
+ if (table != null && table.RowCount > 0)
+ {
+ mw.Write(table.RowCount);
+ }
+ }
+ // Tables
+ foreach (Table table in tables)
+ {
+ if (table != null && table.RowCount > 0)
+ {
+ int pos = mw.Position;
+ table.Write(mw);
+ Debug.Assert(mw.Position - pos == table.GetLength(mw));
+ }
+ }
+ // unexplained extra padding
+ mw.Write((byte)0);
+ }
+
+ private int GetLength(MetadataWriter mw)
+ {
+ int len = 4 + 4 + 8 + 8;
+ foreach (Table table in mw.ModuleBuilder.GetTables())
+ {
+ if (table != null && table.RowCount > 0)
+ {
+ len += 4; // row count
+ len += table.GetLength(mw);
+ }
+ }
+ // note that we pad one extra (unexplained) byte
+ return len + 1;
+ }
+ }
+
+ sealed class StringHeap : SimpleHeap
+ {
+ private List<string> list = new List<string>();
+ private Dictionary<string, int> strings = new Dictionary<string, int>();
+ private int nextOffset;
+
+ internal StringHeap()
+ {
+ Add("");
+ }
+
+ internal int Add(string str)
+ {
+ Debug.Assert(!frozen);
+ int offset;
+ if (!strings.TryGetValue(str, out offset))
+ {
+ offset = nextOffset;
+ nextOffset += System.Text.Encoding.UTF8.GetByteCount(str) + 1;
+ list.Add(str);
+ strings.Add(str, offset);
+ }
+ return offset;
+ }
+
+ protected override int GetLength()
+ {
+ return nextOffset;
+ }
+
+ protected override void WriteImpl(MetadataWriter mw)
+ {
+ foreach (string str in list)
+ {
+ mw.Write(System.Text.Encoding.UTF8.GetBytes(str));
+ mw.Write((byte)0);
+ }
+ }
+ }
+
+ sealed class UserStringHeap : SimpleHeap
+ {
+ private List<string> list = new List<string>();
+ private Dictionary<string, int> strings = new Dictionary<string, int>();
+ private int nextOffset;
+
+ internal UserStringHeap()
+ {
+ nextOffset = 1;
+ }
+
+ internal bool IsEmpty
+ {
+ get { return nextOffset == 1; }
+ }
+
+ internal int Add(string str)
+ {
+ Debug.Assert(!frozen);
+ int offset;
+ if (!strings.TryGetValue(str, out offset))
+ {
+ int length = str.Length * 2 + 1 + MetadataWriter.GetCompressedIntLength(str.Length * 2 + 1);
+ if (nextOffset + length > 0xFFFFFF)
+ {
+ throw new FileFormatLimitationExceededException("No logical space left to create more user strings.", FileFormatLimitationExceededException.META_E_STRINGSPACE_FULL);
+ }
+ offset = nextOffset;
+ nextOffset += length;
+ list.Add(str);
+ strings.Add(str, offset);
+ }
+ return offset;
+ }
+
+ protected override int GetLength()
+ {
+ return nextOffset;
+ }
+
+ protected override void WriteImpl(MetadataWriter mw)
+ {
+ mw.Write((byte)0);
+ foreach (string str in list)
+ {
+ mw.WriteCompressedInt(str.Length * 2 + 1);
+ byte hasSpecialChars = 0;
+ foreach (char ch in str)
+ {
+ mw.Write((ushort)ch);
+ if (hasSpecialChars == 0 && (ch < 0x20 || ch > 0x7E))
+ {
+ if (ch > 0x7E
+ || (ch >= 0x01 && ch <= 0x08)
+ || (ch >= 0x0E && ch <= 0x1F)
+ || ch == 0x27
+ || ch == 0x2D)
+ {
+ hasSpecialChars = 1;
+ }
+ }
+ }
+ mw.Write(hasSpecialChars);
+ }
+ }
+ }
+
+ sealed class GuidHeap : SimpleHeap
+ {
+ private List<Guid> list = new List<Guid>();
+
+ internal GuidHeap()
+ {
+ }
+
+ internal int Add(Guid guid)
+ {
+ Debug.Assert(!frozen);
+ list.Add(guid);
+ return list.Count;
+ }
+
+ protected override int GetLength()
+ {
+ return list.Count * 16;
+ }
+
+ protected override void WriteImpl(MetadataWriter mw)
+ {
+ foreach (Guid guid in list)
+ {
+ mw.Write(guid.ToByteArray());
+ }
+ }
+ }
+
+ sealed class BlobHeap : SimpleHeap
+ {
+ private Key[] map = new Key[8179];
+ private readonly ByteBuffer buf = new ByteBuffer(32);
+
+ private struct Key
+ {
+ internal Key[] next;
+ internal int len;
+ internal int hash;
+ internal int offset;
+ }
+
+ internal BlobHeap()
+ {
+ buf.Write((byte)0);
+ }
+
+ internal int Add(ByteBuffer bb)
+ {
+ Debug.Assert(!frozen);
+ if (bb.Length == 0)
+ {
+ return 0;
+ }
+ int lenlen = MetadataWriter.GetCompressedIntLength(bb.Length);
+ int hash = bb.Hash();
+ int index = (hash & 0x7FFFFFFF) % map.Length;
+ Key[] keys = map;
+ int last = index;
+ while (keys[index].offset != 0)
+ {
+ if (keys[index].hash == hash
+ && keys[index].len == bb.Length
+ && buf.Match(keys[index].offset + lenlen, bb, 0, bb.Length))
+ {
+ return keys[index].offset;
+ }
+ if (index == last)
+ {
+ if (keys[index].next == null)
+ {
+ keys[index].next = new Key[4];
+ keys = keys[index].next;
+ index = 0;
+ break;
+ }
+ keys = keys[index].next;
+ index = -1;
+ last = keys.Length - 1;
+ }
+ index++;
+ }
+ int offset = buf.Position;
+ buf.WriteCompressedInt(bb.Length);
+ buf.Write(bb);
+ keys[index].len = bb.Length;
+ keys[index].hash = hash;
+ keys[index].offset = offset;
+ return offset;
+ }
+
+ protected override int GetLength()
+ {
+ return buf.Position;
+ }
+
+ protected override void WriteImpl(MetadataWriter mw)
+ {
+ mw.Write(buf);
+ }
+
+ internal bool IsEmpty
+ {
+ get { return buf.Position == 1; }
+ }
+
+ internal IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+ {
+ return buf.GetBlob(blobIndex);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+ sealed class MetadataWriter : MetadataRW
+ {
+ private readonly ModuleBuilder moduleBuilder;
+ private readonly Stream stream;
+ private readonly byte[] buffer = new byte[8];
+
+ internal MetadataWriter(ModuleBuilder module, Stream stream)
+ : base(module, module.Strings.IsBig, module.Guids.IsBig, module.Blobs.IsBig)
+ {
+ this.moduleBuilder = module;
+ this.stream = stream;
+ }
+
+ internal ModuleBuilder ModuleBuilder
+ {
+ get { return moduleBuilder; }
+ }
+
+ internal int Position
+ {
+ get { return (int)stream.Position; }
+ }
+
+ internal void Write(ByteBuffer bb)
+ {
+ bb.WriteTo(stream);
+ }
+
+ internal void Write(byte[] value)
+ {
+ stream.Write(value, 0, value.Length);
+ }
+
+ internal void Write(byte value)
+ {
+ stream.WriteByte(value);
+ }
+
+ internal void Write(ushort value)
+ {
+ Write((short)value);
+ }
+
+ internal void Write(short value)
+ {
+ buffer[0] = (byte)value;
+ buffer[1] = (byte)(value >> 8);
+ stream.Write(buffer, 0, 2);
+ }
+
+ internal void Write(uint value)
+ {
+ Write((int)value);
+ }
+
+ internal void Write(int value)
+ {
+ buffer[0] = (byte)value;
+ buffer[1] = (byte)(value >> 8);
+ buffer[2] = (byte)(value >> 16);
+ buffer[3] = (byte)(value >> 24);
+ stream.Write(buffer, 0, 4);
+ }
+
+ internal void Write(ulong value)
+ {
+ Write((long)value);
+ }
+
+ internal void Write(long value)
+ {
+ buffer[0] = (byte)value;
+ buffer[1] = (byte)(value >> 8);
+ buffer[2] = (byte)(value >> 16);
+ buffer[3] = (byte)(value >> 24);
+ buffer[4] = (byte)(value >> 32);
+ buffer[5] = (byte)(value >> 40);
+ buffer[6] = (byte)(value >> 48);
+ buffer[7] = (byte)(value >> 56);
+ stream.Write(buffer, 0, 8);
+ }
+
+ internal void WriteCompressedInt(int value)
+ {
+ if (value <= 0x7F)
+ {
+ Write((byte)value);
+ }
+ else if (value <= 0x3FFF)
+ {
+ Write((byte)(0x80 | (value >> 8)));
+ Write((byte)value);
+ }
+ else
+ {
+ Write((byte)(0xC0 | (value >> 24)));
+ Write((byte)(value >> 16));
+ Write((byte)(value >> 8));
+ Write((byte)value);
+ }
+ }
+
+ internal static int GetCompressedIntLength(int value)
+ {
+ if (value <= 0x7F)
+ {
+ return 1;
+ }
+ else if (value <= 0x3FFF)
+ {
+ return 2;
+ }
+ else
+ {
+ return 4;
+ }
+ }
+
+ internal void WriteStringIndex(int index)
+ {
+ if (bigStrings)
+ {
+ Write(index);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteGuidIndex(int index)
+ {
+ if (bigGuids)
+ {
+ Write(index);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteBlobIndex(int index)
+ {
+ if (bigBlobs)
+ {
+ Write(index);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteTypeDefOrRef(int token)
+ {
+ switch (token >> 24)
+ {
+ case 0:
+ break;
+ case TypeDefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 0;
+ break;
+ case TypeRefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 1;
+ break;
+ case TypeSpecTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 2;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ if (bigTypeDefOrRef)
+ {
+ Write(token);
+ }
+ else
+ {
+ Write((short)token);
+ }
+ }
+
+ internal void WriteEncodedTypeDefOrRef(int encodedToken)
+ {
+ if (bigTypeDefOrRef)
+ {
+ Write(encodedToken);
+ }
+ else
+ {
+ Write((short)encodedToken);
+ }
+ }
+
+ internal void WriteHasCustomAttribute(int encodedToken)
+ {
+ // NOTE because we've already had to do the encoding (to be able to sort the table)
+ // here we simple write the value
+ if (bigHasCustomAttribute)
+ {
+ Write(encodedToken);
+ }
+ else
+ {
+ Write((short)encodedToken);
+ }
+ }
+
+ internal void WriteCustomAttributeType(int token)
+ {
+ switch (token >> 24)
+ {
+ case MethodDefTable.Index:
+ token = (token & 0xFFFFFF) << 3 | 2;
+ break;
+ case MemberRefTable.Index:
+ token = (token & 0xFFFFFF) << 3 | 3;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ if (bigCustomAttributeType)
+ {
+ Write(token);
+ }
+ else
+ {
+ Write((short)token);
+ }
+ }
+
+ internal void WriteField(int index)
+ {
+ if (bigField)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteMethodDef(int index)
+ {
+ if (bigMethodDef)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteParam(int index)
+ {
+ if (bigParam)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteTypeDef(int index)
+ {
+ if (bigTypeDef)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteEvent(int index)
+ {
+ if (bigEvent)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteProperty(int index)
+ {
+ if (bigProperty)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteGenericParam(int index)
+ {
+ if (bigGenericParam)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteModuleRef(int index)
+ {
+ if (bigModuleRef)
+ {
+ Write(index & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)index);
+ }
+ }
+
+ internal void WriteResolutionScope(int token)
+ {
+ switch (token >> 24)
+ {
+ case ModuleTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 0;
+ break;
+ case ModuleRefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 1;
+ break;
+ case AssemblyRefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 2;
+ break;
+ case TypeRefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 3;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ if (bigResolutionScope)
+ {
+ Write(token);
+ }
+ else
+ {
+ Write((short)token);
+ }
+ }
+
+ internal void WriteMemberRefParent(int token)
+ {
+ switch (token >> 24)
+ {
+ case TypeDefTable.Index:
+ token = (token & 0xFFFFFF) << 3 | 0;
+ break;
+ case TypeRefTable.Index:
+ token = (token & 0xFFFFFF) << 3 | 1;
+ break;
+ case ModuleRefTable.Index:
+ token = (token & 0xFFFFFF) << 3 | 2;
+ break;
+ case MethodDefTable.Index:
+ token = (token & 0xFFFFFF) << 3 | 3;
+ break;
+ case TypeSpecTable.Index:
+ token = (token & 0xFFFFFF) << 3 | 4;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ if (bigMemberRefParent)
+ {
+ Write(token);
+ }
+ else
+ {
+ Write((short)token);
+ }
+ }
+
+ internal void WriteMethodDefOrRef(int token)
+ {
+ switch (token >> 24)
+ {
+ case MethodDefTable.Index:
+ token = (token & 0xFFFFFF) << 1 | 0;
+ break;
+ case MemberRefTable.Index:
+ token = (token & 0xFFFFFF) << 1 | 1;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ if (bigMethodDefOrRef)
+ {
+ Write(token);
+ }
+ else
+ {
+ Write((short)token);
+ }
+ }
+
+ internal void WriteHasConstant(int encodedToken)
+ {
+ // NOTE because we've already had to do the encoding (to be able to sort the table)
+ // here we simple write the value
+ if (bigHasConstant)
+ {
+ Write(encodedToken);
+ }
+ else
+ {
+ Write((short)encodedToken);
+ }
+ }
+
+ internal void WriteHasSemantics(int encodedToken)
+ {
+ // NOTE because we've already had to do the encoding (to be able to sort the table)
+ // here we simple write the value
+ if (bigHasSemantics)
+ {
+ Write(encodedToken);
+ }
+ else
+ {
+ Write((short)encodedToken);
+ }
+ }
+
+ internal void WriteImplementation(int token)
+ {
+ switch (token >> 24)
+ {
+ case 0:
+ break;
+ case FileTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 0;
+ break;
+ case AssemblyRefTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 1;
+ break;
+ case ExportedTypeTable.Index:
+ token = (token & 0xFFFFFF) << 2 | 2;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ if (bigImplementation)
+ {
+ Write(token);
+ }
+ else
+ {
+ Write((short)token);
+ }
+ }
+
+ internal void WriteTypeOrMethodDef(int encodedToken)
+ {
+ // NOTE because we've already had to do the encoding (to be able to sort the table)
+ // here we simple write the value
+ if (bigTypeOrMethodDef)
+ {
+ Write(encodedToken);
+ }
+ else
+ {
+ Write((short)encodedToken);
+ }
+ }
+
+ internal void WriteHasDeclSecurity(int encodedToken)
+ {
+ // NOTE because we've already had to do the encoding (to be able to sort the table)
+ // here we simple write the value
+ if (bigHasDeclSecurity)
+ {
+ Write(encodedToken);
+ }
+ else
+ {
+ Write((short)encodedToken);
+ }
+ }
+
+ internal void WriteMemberForwarded(int token)
+ {
+ switch (token >> 24)
+ {
+ case FieldTable.Index:
+ token = (token & 0xFFFFFF) << 1 | 0;
+ break;
+ case MethodDefTable.Index:
+ token = (token & 0xFFFFFF) << 1 | 1;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ if (bigMemberForwarded)
+ {
+ Write(token);
+ }
+ else
+ {
+ Write((short)token);
+ }
+ }
+
+ internal void WriteHasFieldMarshal(int encodedToken)
+ {
+ // NOTE because we've already had to do the encoding (to be able to sort the table)
+ // here we simple write the value
+ if (bigHasFieldMarshal)
+ {
+ Write(encodedToken & 0xFFFFFF);
+ }
+ else
+ {
+ Write((short)encodedToken);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Security.Cryptography;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+ static class ModuleWriter
+ {
+ internal static void WriteModule(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder,
+ PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine,
+ ResourceSection resources, int entryPointToken)
+ {
+ moduleBuilder.FixupMethodBodyTokens();
+
+ moduleBuilder.ModuleTable.Add(0, moduleBuilder.Strings.Add(moduleBuilder.moduleName), moduleBuilder.Guids.Add(moduleBuilder.ModuleVersionId), 0, 0);
+
+ if (moduleBuilder.UserStrings.IsEmpty)
+ {
+ // for compat with Ref.Emit, if there aren't any user strings, we add one
+ moduleBuilder.UserStrings.Add(" ");
+ }
+
+ if (resources != null)
+ {
+ resources.Finish();
+ }
+
+ using (FileStream fs = new FileStream(moduleBuilder.FullyQualifiedName, FileMode.Create))
+ {
+ PEWriter writer = new PEWriter(fs);
+ switch (imageFileMachine)
+ {
+ case ImageFileMachine.I386:
+ writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386;
+ writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE;
+ break;
+ case ImageFileMachine.AMD64:
+ writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64;
+ writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
+ writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
+ writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ writer.Headers.OptionalHeader.SizeOfStackReserve = 0x400000;
+ writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
+ writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
+ break;
+ case ImageFileMachine.IA64:
+ writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64;
+ writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
+ writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
+ writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ writer.Headers.OptionalHeader.SizeOfStackReserve = 0x400000;
+ writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
+ writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("imageFileMachine");
+ }
+ if (fileKind == PEFileKinds.Dll)
+ {
+ writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_DLL;
+ }
+
+ switch (fileKind)
+ {
+ case PEFileKinds.WindowApplication:
+ writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_GUI;
+ break;
+ default:
+ writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_CUI;
+ break;
+ }
+ writer.Headers.OptionalHeader.DllCharacteristics =
+ IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
+ IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_NO_SEH |
+ IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_NX_COMPAT |
+ IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
+
+ CliHeader cliHeader = new CliHeader();
+ cliHeader.Cb = 0x48;
+ cliHeader.MajorRuntimeVersion = 2;
+ cliHeader.MinorRuntimeVersion = moduleBuilder.MDStreamVersion < 0x20000 ? (ushort)0 : (ushort)5;
+ if ((portableExecutableKind & PortableExecutableKinds.ILOnly) != 0)
+ {
+ cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_ILONLY;
+ }
+ if ((portableExecutableKind & PortableExecutableKinds.Required32Bit) != 0)
+ {
+ cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED;
+ }
+ if (keyPair != null)
+ {
+ cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_STRONGNAMESIGNED;
+ }
+ if (moduleBuilder.IsPseudoToken(entryPointToken))
+ {
+ entryPointToken = moduleBuilder.ResolvePseudoToken(entryPointToken);
+ }
+ cliHeader.EntryPointToken = (uint)entryPointToken;
+
+ moduleBuilder.Strings.Freeze();
+ moduleBuilder.UserStrings.Freeze();
+ moduleBuilder.Guids.Freeze();
+ moduleBuilder.Blobs.Freeze();
+ MetadataWriter mw = new MetadataWriter(moduleBuilder, fs);
+ moduleBuilder.Tables.Freeze(mw);
+ TextSection code = new TextSection(writer, cliHeader, moduleBuilder, ComputeStrongNameSignatureLength(publicKey));
+
+ // Import Directory
+ writer.Headers.OptionalHeader.DataDirectory[1].VirtualAddress = code.ImportDirectoryRVA;
+ writer.Headers.OptionalHeader.DataDirectory[1].Size = code.ImportDirectoryLength;
+
+ // Import Address Table Directory
+ writer.Headers.OptionalHeader.DataDirectory[12].VirtualAddress = code.ImportAddressTableRVA;
+ writer.Headers.OptionalHeader.DataDirectory[12].Size = code.ImportAddressTableLength;
+
+ // COM Descriptor Directory
+ writer.Headers.OptionalHeader.DataDirectory[14].VirtualAddress = code.ComDescriptorRVA;
+ writer.Headers.OptionalHeader.DataDirectory[14].Size = code.ComDescriptorLength;
+
+ // Debug Directory
+ if (code.DebugDirectoryLength != 0)
+ {
+ writer.Headers.OptionalHeader.DataDirectory[6].VirtualAddress = code.DebugDirectoryRVA;
+ writer.Headers.OptionalHeader.DataDirectory[6].Size = code.DebugDirectoryLength;
+ }
+
+ writer.Headers.FileHeader.NumberOfSections = 2;
+
+ if (moduleBuilder.initializedData.Length != 0)
+ {
+ writer.Headers.FileHeader.NumberOfSections++;
+ }
+
+ if (resources != null && resources.Length != 0)
+ {
+ writer.Headers.FileHeader.NumberOfSections++;
+ }
+
+ SectionHeader text = new SectionHeader();
+ text.Name = ".text";
+ text.VirtualAddress = code.BaseRVA;
+ text.VirtualSize = (uint)code.Length;
+ text.PointerToRawData = code.PointerToRawData;
+ text.SizeOfRawData = writer.ToFileAlignment((uint)code.Length);
+ text.Characteristics = SectionHeader.IMAGE_SCN_CNT_CODE | SectionHeader.IMAGE_SCN_MEM_EXECUTE | SectionHeader.IMAGE_SCN_MEM_READ;
+
+ SectionHeader sdata = new SectionHeader();
+ sdata.Name = ".sdata";
+ sdata.VirtualAddress = text.VirtualAddress + writer.ToSectionAlignment(text.VirtualSize);
+ sdata.VirtualSize = (uint)moduleBuilder.initializedData.Length;
+ sdata.PointerToRawData = text.PointerToRawData + text.SizeOfRawData;
+ sdata.SizeOfRawData = writer.ToFileAlignment((uint)moduleBuilder.initializedData.Length);
+ sdata.Characteristics = SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_MEM_WRITE;
+
+ SectionHeader rsrc = new SectionHeader();
+ rsrc.Name = ".rsrc";
+ rsrc.VirtualAddress = sdata.VirtualAddress + writer.ToSectionAlignment(sdata.VirtualSize);
+ rsrc.PointerToRawData = sdata.PointerToRawData + sdata.SizeOfRawData;
+ rsrc.VirtualSize = resources == null ? 0 : (uint)resources.Length;
+ rsrc.SizeOfRawData = writer.ToFileAlignment(rsrc.VirtualSize);
+ rsrc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA;
+
+ if (rsrc.SizeOfRawData != 0)
+ {
+ // Resource Directory
+ writer.Headers.OptionalHeader.DataDirectory[2].VirtualAddress = rsrc.VirtualAddress;
+ writer.Headers.OptionalHeader.DataDirectory[2].Size = rsrc.VirtualSize;
+ }
+
+ SectionHeader reloc = new SectionHeader();
+ reloc.Name = ".reloc";
+ reloc.VirtualAddress = rsrc.VirtualAddress + writer.ToSectionAlignment(rsrc.VirtualSize);
+ reloc.VirtualSize = 12;
+ reloc.PointerToRawData = rsrc.PointerToRawData + rsrc.SizeOfRawData;
+ reloc.SizeOfRawData = writer.ToFileAlignment(reloc.VirtualSize);
+ reloc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_DISCARDABLE;
+
+ // Base Relocation Directory
+ writer.Headers.OptionalHeader.DataDirectory[5].VirtualAddress = reloc.VirtualAddress;
+ writer.Headers.OptionalHeader.DataDirectory[5].Size = reloc.VirtualSize;
+
+ writer.Headers.OptionalHeader.SizeOfCode = text.SizeOfRawData;
+ writer.Headers.OptionalHeader.SizeOfInitializedData = sdata.SizeOfRawData + rsrc.SizeOfRawData + reloc.SizeOfRawData;
+ writer.Headers.OptionalHeader.SizeOfUninitializedData = 0;
+ writer.Headers.OptionalHeader.SizeOfImage = reloc.VirtualAddress + writer.ToSectionAlignment(reloc.VirtualSize);
+ writer.Headers.OptionalHeader.SizeOfHeaders = text.PointerToRawData;
+ writer.Headers.OptionalHeader.BaseOfCode = code.BaseRVA;
+ writer.Headers.OptionalHeader.BaseOfData = sdata.VirtualAddress;
+ writer.Headers.OptionalHeader.ImageBase = (ulong)moduleBuilder.__ImageBase;
+
+ if (imageFileMachine == ImageFileMachine.IA64)
+ {
+ // apparently for IA64 AddressOfEntryPoint points to the address of the entry point
+ // (i.e. there is an additional layer of indirection), so we add the offset to the pointer
+ writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + 0x20;
+ }
+ else
+ {
+ writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA;
+ }
+
+ writer.WritePEHeaders();
+ writer.WriteSectionHeader(text);
+ if (sdata.SizeOfRawData != 0)
+ {
+ writer.WriteSectionHeader(sdata);
+ }
+ if (rsrc.SizeOfRawData != 0)
+ {
+ writer.WriteSectionHeader(rsrc);
+ }
+ writer.WriteSectionHeader(reloc);
+
+ fs.Seek(text.PointerToRawData, SeekOrigin.Begin);
+ code.Write(mw, (int)sdata.VirtualAddress);
+
+ fs.Seek(sdata.PointerToRawData, SeekOrigin.Begin);
+ mw.Write(moduleBuilder.initializedData);
+
+ if (rsrc.SizeOfRawData != 0)
+ {
+ fs.Seek(rsrc.PointerToRawData, SeekOrigin.Begin);
+ resources.Write(mw, rsrc.VirtualAddress);
+ }
+
+ fs.Seek(reloc.PointerToRawData, SeekOrigin.Begin);
+ // .reloc section
+ uint relocAddress = code.StartupStubRVA;
+ switch (imageFileMachine)
+ {
+ case ImageFileMachine.I386:
+ case ImageFileMachine.AMD64:
+ relocAddress += 2;
+ break;
+ case ImageFileMachine.IA64:
+ relocAddress += 0x20;
+ break;
+ }
+ uint pageRVA = relocAddress & ~0xFFFU;
+ mw.Write(pageRVA); // PageRVA
+ mw.Write(0x000C); // Block Size
+ if (imageFileMachine == ImageFileMachine.I386)
+ {
+ mw.Write(0x3000 + relocAddress - pageRVA); // Type / Offset
+ }
+ else if (imageFileMachine == ImageFileMachine.AMD64)
+ {
+ mw.Write(0xA000 + relocAddress - pageRVA); // Type / Offset
+ }
+ else if (imageFileMachine == ImageFileMachine.IA64)
+ {
+ // on IA64 the StartupStubRVA is 16 byte aligned, so these two addresses won't cross a page boundary
+ mw.Write((short)(0xA000 + relocAddress - pageRVA)); // Type / Offset
+ mw.Write((short)(0xA000 + relocAddress - pageRVA + 8)); // Type / Offset
+ }
+
+ // file alignment
+ mw.Write(new byte[writer.Headers.OptionalHeader.FileAlignment - reloc.VirtualSize]);
+
+ // do the strong naming
+ if (keyPair != null)
+ {
+ StrongName(fs, keyPair, writer.HeaderSize, text.PointerToRawData, code.StrongNameSignatureRVA - text.VirtualAddress + text.PointerToRawData, code.StrongNameSignatureLength);
+ }
+ }
+
+ if (moduleBuilder.symbolWriter != null)
+ {
+ moduleBuilder.WriteSymbolTokenMap();
+ moduleBuilder.symbolWriter.Close();
+ }
+ }
+
+ private static int ComputeStrongNameSignatureLength(byte[] publicKey)
+ {
+ if (publicKey == null)
+ {
+ return 0;
+ }
+ else if (publicKey.Length == 16)
+ {
+ // it must be the ECMA pseudo public key, we don't know the key size of the real key, but currently both Mono and Microsoft use a 1024 bit key size
+ return 128;
+ }
+ else
+ {
+ // for the supported strong naming algorithms, the signature size is the same as the key size
+ // (we have to subtract 32 for the header)
+ return publicKey.Length - 32;
+ }
+ }
+
+ private static void StrongName(FileStream fs, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength)
+ {
+ SHA1Managed hash = new SHA1Managed();
+ using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
+ {
+ fs.Seek(0, SeekOrigin.Begin);
+ byte[] buf = new byte[8192];
+ HashChunk(fs, cs, buf, (int)headerLength);
+ fs.Seek(textSectionFileOffset, SeekOrigin.Begin);
+ HashChunk(fs, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset));
+ fs.Seek(strongNameSignatureLength, SeekOrigin.Current);
+ HashChunk(fs, cs, buf, (int)(fs.Length - (strongNameSignatureFileOffset + strongNameSignatureLength)));
+ }
+ using (RSA rsa = CryptoHack.CreateRSA(keyPair))
+ {
+ RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa);
+ byte[] signature = sign.CreateSignature(hash);
+ Array.Reverse(signature);
+ if (signature.Length != strongNameSignatureLength)
+ {
+ throw new InvalidOperationException("Signature length mismatch");
+ }
+ fs.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin);
+ fs.Write(signature, 0, signature.Length);
+ }
+
+ // compute the PE checksum
+ fs.Seek(0, SeekOrigin.Begin);
+ int count = (int)fs.Length / 4;
+ BinaryReader br = new BinaryReader(fs);
+ long sum = 0;
+ for (int i = 0; i < count; i++)
+ {
+ sum += br.ReadUInt32();
+ int carry = (int)(sum >> 32);
+ sum &= 0xFFFFFFFFU;
+ sum += carry;
+ }
+ while ((sum >> 16) != 0)
+ {
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ }
+ sum += fs.Length;
+
+ // write the PE checksum, note that it is always at offset 0xD8 in the file
+ ByteBuffer bb = new ByteBuffer(4);
+ bb.Write((int)sum);
+ fs.Seek(0xD8, SeekOrigin.Begin);
+ bb.WriteTo(fs);
+ }
+
+ internal static void HashChunk(FileStream fs, CryptoStream cs, byte[] buf, int length)
+ {
+ while (length > 0)
+ {
+ int read = fs.Read(buf, 0, Math.Min(buf.Length, length));
+ cs.Write(buf, 0, read);
+ length -= read;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.IO;
+using BYTE = System.Byte;
+using WORD = System.UInt16;
+using DWORD = System.UInt32;
+using ULONGLONG = System.UInt64;
+
+namespace IKVM.Reflection.Writer
+{
+ sealed class PEWriter
+ {
+ private readonly BinaryWriter bw;
+ private readonly IMAGE_NT_HEADERS hdr = new IMAGE_NT_HEADERS();
+
+ internal PEWriter(Stream stream)
+ {
+ bw = new BinaryWriter(stream);
+ WriteMSDOSHeader();
+ }
+
+ public IMAGE_NT_HEADERS Headers
+ {
+ get { return hdr; }
+ }
+
+ public uint HeaderSize
+ {
+ get
+ {
+ return (uint)
+ ((8 * 16) + // MSDOS header
+ 4 + // signature
+ 20 + // IMAGE_FILE_HEADER
+ hdr.FileHeader.SizeOfOptionalHeader +
+ hdr.FileHeader.NumberOfSections * 40);
+ }
+ }
+
+ private void WriteMSDOSHeader()
+ {
+ bw.Write(new byte[] {
+ 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
+ 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72,
+ 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F,
+ 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E,
+ 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20,
+ 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ });
+ }
+
+ internal void WritePEHeaders()
+ {
+ bw.Write(hdr.Signature);
+
+ // IMAGE_FILE_HEADER
+ bw.Write(hdr.FileHeader.Machine);
+ bw.Write(hdr.FileHeader.NumberOfSections);
+ bw.Write(hdr.FileHeader.TimeDateStamp);
+ bw.Write(hdr.FileHeader.PointerToSymbolTable);
+ bw.Write(hdr.FileHeader.NumberOfSymbols);
+ bw.Write(hdr.FileHeader.SizeOfOptionalHeader);
+ bw.Write(hdr.FileHeader.Characteristics);
+
+ // IMAGE_OPTIONAL_HEADER
+ hdr.OptionalHeader.Write(bw);
+ }
+
+ internal void WriteSectionHeader(SectionHeader sectionHeader)
+ {
+ byte[] name = new byte[8];
+ System.Text.Encoding.UTF8.GetBytes(sectionHeader.Name, 0, sectionHeader.Name.Length, name, 0);
+ bw.Write(name);
+ bw.Write(sectionHeader.VirtualSize);
+ bw.Write(sectionHeader.VirtualAddress);
+ bw.Write(sectionHeader.SizeOfRawData);
+ bw.Write(sectionHeader.PointerToRawData);
+ bw.Write(sectionHeader.PointerToRelocations);
+ bw.Write(sectionHeader.PointerToLinenumbers);
+ bw.Write(sectionHeader.NumberOfRelocations);
+ bw.Write(sectionHeader.NumberOfLinenumbers);
+ bw.Write(sectionHeader.Characteristics);
+ }
+
+ internal uint ToFileAlignment(uint p)
+ {
+ return (p + (Headers.OptionalHeader.FileAlignment - 1)) & ~(Headers.OptionalHeader.FileAlignment - 1);
+ }
+
+ internal uint ToSectionAlignment(uint p)
+ {
+ return (p + (Headers.OptionalHeader.SectionAlignment - 1)) & ~(Headers.OptionalHeader.SectionAlignment - 1);
+ }
+ }
+
+ sealed class IMAGE_NT_HEADERS
+ {
+ public DWORD Signature = 0x00004550; // "PE\0\0"
+ public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
+ public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
+ }
+
+ sealed class IMAGE_FILE_HEADER
+ {
+ public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
+ public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
+ public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
+
+ public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
+ public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
+ public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
+ public const WORD IMAGE_FILE_DLL = 0x2000;
+
+ public WORD Machine;
+ public WORD NumberOfSections;
+ public DWORD TimeDateStamp = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
+ public DWORD PointerToSymbolTable = 0;
+ public DWORD NumberOfSymbols = 0;
+ public WORD SizeOfOptionalHeader = 0xE0;
+ public WORD Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
+ }
+
+ sealed class IMAGE_OPTIONAL_HEADER
+ {
+ public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
+ public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
+
+ public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
+ public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
+
+ public const WORD IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040;
+ public const WORD IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100;
+ public const WORD IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400;
+ public const WORD IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000;
+
+ public WORD Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ public BYTE MajorLinkerVersion = 8;
+ public BYTE MinorLinkerVersion = 0;
+ public DWORD SizeOfCode;
+ public DWORD SizeOfInitializedData;
+ public DWORD SizeOfUninitializedData;
+ public DWORD AddressOfEntryPoint;
+ public DWORD BaseOfCode;
+ public DWORD BaseOfData;
+ public ULONGLONG ImageBase;
+ public DWORD SectionAlignment = 0x2000;
+ public DWORD FileAlignment = 0x200;
+ public WORD MajorOperatingSystemVersion = 4;
+ public WORD MinorOperatingSystemVersion = 0;
+ public WORD MajorImageVersion = 0;
+ public WORD MinorImageVersion = 0;
+ public WORD MajorSubsystemVersion = 4;
+ public WORD MinorSubsystemVersion = 0;
+ public DWORD Win32VersionValue = 0;
+ public DWORD SizeOfImage;
+ public DWORD SizeOfHeaders;
+ public DWORD CheckSum = 0;
+ public WORD Subsystem;
+ public WORD DllCharacteristics;
+ public ULONGLONG SizeOfStackReserve = 0x100000;
+ public ULONGLONG SizeOfStackCommit = 0x1000;
+ public ULONGLONG SizeOfHeapReserve = 0x100000;
+ public ULONGLONG SizeOfHeapCommit = 0x1000;
+ public DWORD LoaderFlags = 0;
+ public DWORD NumberOfRvaAndSizes = 16;
+ public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16];
+
+ internal void Write(BinaryWriter bw)
+ {
+ bw.Write(Magic);
+ bw.Write(MajorLinkerVersion);
+ bw.Write(MinorLinkerVersion);
+ bw.Write(SizeOfCode);
+ bw.Write(SizeOfInitializedData);
+ bw.Write(SizeOfUninitializedData);
+ bw.Write(AddressOfEntryPoint);
+ bw.Write(BaseOfCode);
+ if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ bw.Write(BaseOfData);
+ bw.Write((DWORD)ImageBase);
+ }
+ else
+ {
+ bw.Write(ImageBase);
+ }
+ bw.Write(SectionAlignment);
+ bw.Write(FileAlignment);
+ bw.Write(MajorOperatingSystemVersion);
+ bw.Write(MinorOperatingSystemVersion);
+ bw.Write(MajorImageVersion);
+ bw.Write(MinorImageVersion);
+ bw.Write(MajorSubsystemVersion);
+ bw.Write(MinorSubsystemVersion);
+ bw.Write(Win32VersionValue);
+ bw.Write(SizeOfImage);
+ bw.Write(SizeOfHeaders);
+ bw.Write(CheckSum);
+ bw.Write(Subsystem);
+ bw.Write(DllCharacteristics);
+ if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ bw.Write((DWORD)SizeOfStackReserve);
+ }
+ else
+ {
+ bw.Write(SizeOfStackReserve);
+ }
+ if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ bw.Write((DWORD)SizeOfStackCommit);
+ }
+ else
+ {
+ bw.Write(SizeOfStackCommit);
+ }
+ if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ bw.Write((DWORD)SizeOfHeapReserve);
+ }
+ else
+ {
+ bw.Write(SizeOfHeapReserve);
+ }
+ if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ bw.Write((DWORD)SizeOfHeapCommit);
+ }
+ else
+ {
+ bw.Write(SizeOfHeapCommit);
+ }
+ bw.Write(LoaderFlags);
+ bw.Write(NumberOfRvaAndSizes);
+ for (int i = 0; i < DataDirectory.Length; i++)
+ {
+ bw.Write(DataDirectory[i].VirtualAddress);
+ bw.Write(DataDirectory[i].Size);
+ }
+ }
+ }
+
+ struct IMAGE_DATA_DIRECTORY
+ {
+ public DWORD VirtualAddress;
+ public DWORD Size;
+ }
+
+ class SectionHeader
+ {
+ public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
+ public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
+ public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
+ public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
+ public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
+ public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
+
+ public string Name; // 8 byte UTF8 encoded 0-padded
+ public DWORD VirtualSize;
+ public DWORD VirtualAddress;
+ public DWORD SizeOfRawData;
+ public DWORD PointerToRawData;
+#pragma warning disable 649 // the follow fields are never assigned to
+ public DWORD PointerToRelocations;
+ public DWORD PointerToLinenumbers;
+ public WORD NumberOfRelocations;
+ public WORD NumberOfLinenumbers;
+#pragma warning restore 649
+ public DWORD Characteristics;
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2010 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using IKVM.Reflection.Reader;
+
+namespace IKVM.Reflection.Writer
+{
+ sealed class ResourceSection
+ {
+ private const int RT_ICON = 3;
+ private const int RT_GROUP_ICON = 14;
+ private const int RT_VERSION = 16;
+ private ResourceDirectoryEntry root = new ResourceDirectoryEntry(new OrdinalOrName("root"));
+ private ByteBuffer bb;
+ private List<int> linkOffsets;
+
+ internal void AddVersionInfo(ByteBuffer versionInfo)
+ {
+ root[new OrdinalOrName(RT_VERSION)][new OrdinalOrName(1)][new OrdinalOrName(0)].Data = versionInfo;
+ }
+
+ internal void AddIcon(byte[] iconFile)
+ {
+ BinaryReader br = new BinaryReader(new MemoryStream(iconFile));
+ ushort idReserved = br.ReadUInt16();
+ ushort idType = br.ReadUInt16();
+ ushort idCount = br.ReadUInt16();
+ if (idReserved != 0 || idType != 1)
+ {
+ throw new ArgumentException("The supplied byte array is not a valid .ico file.");
+ }
+ ByteBuffer group = new ByteBuffer(6 + 14 * idCount);
+ group.Write(idReserved);
+ group.Write(idType);
+ group.Write(idCount);
+ for (int i = 0; i < idCount; i++)
+ {
+ byte bWidth = br.ReadByte();
+ byte bHeight = br.ReadByte();
+ byte bColorCount = br.ReadByte();
+ byte bReserved = br.ReadByte();
+ ushort wPlanes = br.ReadUInt16();
+ ushort wBitCount = br.ReadUInt16();
+ uint dwBytesInRes = br.ReadUInt32();
+ uint dwImageOffset = br.ReadUInt32();
+
+ // we start the icon IDs at 2
+ ushort id = (ushort)(2 + i);
+
+ group.Write(bWidth);
+ group.Write(bHeight);
+ group.Write(bColorCount);
+ group.Write(bReserved);
+ group.Write(wPlanes);
+ group.Write(wBitCount);
+ group.Write(dwBytesInRes);
+ group.Write(id);
+
+ byte[] icon = new byte[dwBytesInRes];
+ Buffer.BlockCopy(iconFile, (int)dwImageOffset, icon, 0, icon.Length);
+ root[new OrdinalOrName(RT_ICON)][new OrdinalOrName(id)][new OrdinalOrName(0)].Data = ByteBuffer.Wrap(icon);
+ }
+ root[new OrdinalOrName(RT_GROUP_ICON)][new OrdinalOrName(32512)][new OrdinalOrName(0)].Data = group;
+ }
+
+ internal void ExtractResources(byte[] buf)
+ {
+ ByteReader br = new ByteReader(buf, 0, buf.Length);
+ while (br.Length >= 32)
+ {
+ br.Align(4);
+ RESOURCEHEADER hdr = new RESOURCEHEADER(br);
+ if (hdr.DataSize != 0)
+ {
+ root[hdr.TYPE][hdr.NAME][new OrdinalOrName(hdr.LanguageId)].Data = ByteBuffer.Wrap(br.ReadBytes(hdr.DataSize));
+ }
+ }
+ }
+
+ internal void Finish()
+ {
+ if (bb != null)
+ {
+ throw new InvalidOperationException();
+ }
+ bb = new ByteBuffer(1024);
+ linkOffsets = new List<int>();
+ root.Write(bb, linkOffsets);
+ root = null;
+ }
+
+ internal int Length
+ {
+ get { return bb.Length; }
+ }
+
+ internal void Write(MetadataWriter mw, uint rva)
+ {
+ foreach (int offset in linkOffsets)
+ {
+ bb.Position = offset;
+ bb.Write(bb.GetInt32AtCurrentPosition() + (int)rva);
+ }
+ mw.Write(bb);
+ }
+ }
+
+ sealed class ResourceDirectoryEntry
+ {
+ internal readonly OrdinalOrName OrdinalOrName;
+ internal ByteBuffer Data;
+ private int namedEntries;
+ private readonly List<ResourceDirectoryEntry> entries = new List<ResourceDirectoryEntry>();
+
+ internal ResourceDirectoryEntry(OrdinalOrName id)
+ {
+ this.OrdinalOrName = id;
+ }
+
+ internal ResourceDirectoryEntry this[OrdinalOrName id]
+ {
+ get
+ {
+ foreach (ResourceDirectoryEntry entry in entries)
+ {
+ if (entry.OrdinalOrName.Ordinal == id.Ordinal && entry.OrdinalOrName.Name == id.Name)
+ {
+ return entry;
+ }
+ }
+ ResourceDirectoryEntry newEntry = new ResourceDirectoryEntry(id);
+ if (id.Name == null)
+ {
+ entries.Add(newEntry);
+ }
+ else
+ {
+ entries.Insert(namedEntries++, newEntry);
+ }
+ return newEntry;
+ }
+ }
+
+ private int DirectoryLength
+ {
+ get
+ {
+ if (Data != null)
+ {
+ return 16;
+ }
+ else
+ {
+ int length = 16 + entries.Count * 8;
+ foreach (ResourceDirectoryEntry entry in entries)
+ {
+ length += entry.DirectoryLength;
+ }
+ return length;
+ }
+ }
+ }
+
+ internal void Write(ByteBuffer bb, List<int> linkOffsets)
+ {
+ if (entries.Count != 0)
+ {
+ int stringTableOffset = this.DirectoryLength;
+ Dictionary<string, int> strings = new Dictionary<string, int>();
+ ByteBuffer stringTable = new ByteBuffer(16);
+ int offset = 16 + entries.Count * 8;
+ for (int pass = 0; pass < 3; pass++)
+ {
+ Write(bb, pass, 0, ref offset, strings, ref stringTableOffset, stringTable);
+ }
+ // the pecoff spec says that the string table is between the directory entries and the data entries,
+ // but the windows linker puts them after the data entries, so we do too.
+ stringTable.Align(4);
+ offset += stringTable.Length;
+ WriteResourceDataEntries(bb, linkOffsets, ref offset);
+ bb.Write(stringTable);
+ WriteData(bb);
+ }
+ }
+
+ private void WriteResourceDataEntries(ByteBuffer bb, List<int> linkOffsets, ref int offset)
+ {
+ foreach (ResourceDirectoryEntry entry in entries)
+ {
+ if (entry.Data != null)
+ {
+ linkOffsets.Add(bb.Position);
+ bb.Write(offset);
+ bb.Write(entry.Data.Length);
+ bb.Write(0); // code page
+ bb.Write(0); // reserved
+ offset += (entry.Data.Length + 3) & ~3;
+ }
+ else
+ {
+ entry.WriteResourceDataEntries(bb, linkOffsets, ref offset);
+ }
+ }
+ }
+
+ private void WriteData(ByteBuffer bb)
+ {
+ foreach (ResourceDirectoryEntry entry in entries)
+ {
+ if (entry.Data != null)
+ {
+ bb.Write(entry.Data);
+ bb.Align(4);
+ }
+ else
+ {
+ entry.WriteData(bb);
+ }
+ }
+ }
+
+ private void Write(ByteBuffer bb, int writeDepth, int currentDepth, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
+ {
+ if (currentDepth == writeDepth)
+ {
+ // directory header
+ bb.Write(0); // Characteristics
+ bb.Write(0); // Time/Date Stamp
+ bb.Write(0); // Version (Major / Minor)
+ bb.Write((ushort)namedEntries);
+ bb.Write((ushort)(entries.Count - namedEntries));
+ }
+ foreach (ResourceDirectoryEntry entry in entries)
+ {
+ if (currentDepth == writeDepth)
+ {
+ entry.WriteEntry(bb, ref offset, strings, ref stringTableOffset, stringTable);
+ }
+ else
+ {
+ entry.Write(bb, writeDepth, currentDepth + 1, ref offset, strings, ref stringTableOffset, stringTable);
+ }
+ }
+ }
+
+ private void WriteEntry(ByteBuffer bb, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
+ {
+ WriteNameOrOrdinal(bb, OrdinalOrName, strings, ref stringTableOffset, stringTable);
+ if (Data == null)
+ {
+ bb.Write(0x80000000U | (uint)offset);
+ }
+ else
+ {
+ bb.Write(offset);
+ }
+ offset += 16 + entries.Count * 8;
+ }
+
+ private static void WriteNameOrOrdinal(ByteBuffer bb, OrdinalOrName id, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
+ {
+ if (id.Name == null)
+ {
+ bb.Write((int)id.Ordinal);
+ }
+ else
+ {
+ int stringOffset;
+ if (!strings.TryGetValue(id.Name, out stringOffset))
+ {
+ stringOffset = stringTableOffset;
+ strings.Add(id.Name, stringOffset);
+ stringTableOffset += id.Name.Length * 2 + 2;
+ stringTable.Write((ushort)id.Name.Length);
+ foreach (char c in id.Name)
+ {
+ stringTable.Write((short)c);
+ }
+ }
+ bb.Write(0x80000000U | (uint)stringOffset);
+ }
+ }
+ }
+
+ struct OrdinalOrName
+ {
+ internal readonly ushort Ordinal;
+ internal readonly string Name;
+
+ internal OrdinalOrName(ushort value)
+ {
+ Ordinal = value;
+ Name = null;
+ }
+
+ internal OrdinalOrName(string value)
+ {
+ Ordinal = 0xFFFF;
+ Name = value;
+ }
+ }
+
+ struct RESOURCEHEADER
+ {
+ internal int DataSize;
+ internal int HeaderSize;
+ internal OrdinalOrName TYPE;
+ internal OrdinalOrName NAME;
+ internal int DataVersion;
+ internal ushort MemoryFlags;
+ internal ushort LanguageId;
+ internal int Version;
+ internal int Characteristics;
+
+ internal RESOURCEHEADER(ByteReader br)
+ {
+ DataSize = br.ReadInt32();
+ HeaderSize = br.ReadInt32();
+ TYPE = ReadOrdinalOrName(br);
+ NAME = ReadOrdinalOrName(br);
+ br.Align(4);
+ DataVersion = br.ReadInt32();
+ MemoryFlags = br.ReadUInt16();
+ LanguageId = br.ReadUInt16();
+ Version = br.ReadInt32();
+ Characteristics = br.ReadInt32();
+ }
+
+ private static OrdinalOrName ReadOrdinalOrName(ByteReader br)
+ {
+ char c = br.ReadChar();
+ if (c == 0xFFFF)
+ {
+ return new OrdinalOrName(br.ReadUInt16());
+ }
+ else
+ {
+ StringBuilder sb = new StringBuilder();
+ while (c != 0)
+ {
+ sb.Append(c);
+ c = br.ReadChar();
+ }
+ return new OrdinalOrName(sb.ToString());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using IKVM.Reflection.Emit;
+using IKVM.Reflection.Impl;
+using IKVM.Reflection.Metadata;
+
+namespace IKVM.Reflection.Writer
+{
+ sealed class TextSection
+ {
+ private readonly PEWriter peWriter;
+ private readonly CliHeader cliHeader;
+ private readonly ModuleBuilder moduleBuilder;
+ private readonly uint strongNameSignatureLength;
+
+ internal TextSection(PEWriter peWriter, CliHeader cliHeader, ModuleBuilder moduleBuilder, int strongNameSignatureLength)
+ {
+ this.peWriter = peWriter;
+ this.cliHeader = cliHeader;
+ this.moduleBuilder = moduleBuilder;
+ this.strongNameSignatureLength = (uint)strongNameSignatureLength;
+ }
+
+ internal uint PointerToRawData
+ {
+ get { return peWriter.ToFileAlignment(peWriter.HeaderSize); }
+ }
+
+ internal uint BaseRVA
+ {
+ get { return 0x2000; }
+ }
+
+ internal uint ImportAddressTableRVA
+ {
+ get { return BaseRVA; }
+ }
+
+ internal uint ImportAddressTableLength
+ {
+ get
+ {
+ if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+ {
+ return 8;
+ }
+ else
+ {
+ return 16;
+ }
+ }
+ }
+
+ internal uint ComDescriptorRVA
+ {
+ get { return ImportAddressTableRVA + ImportAddressTableLength; }
+ }
+
+ internal uint ComDescriptorLength
+ {
+ get { return cliHeader.Cb; }
+ }
+
+ internal uint MethodBodiesRVA
+ {
+ get { return (ComDescriptorRVA + ComDescriptorLength + 7) & ~7U; }
+ }
+
+ private uint MethodBodiesLength
+ {
+ get { return (uint)moduleBuilder.methodBodies.Length; }
+ }
+
+ private uint ResourcesRVA
+ {
+ get
+ {
+ if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+ {
+ return (MethodBodiesRVA + MethodBodiesLength + 3) & ~3U;
+ }
+ else
+ {
+ return (MethodBodiesRVA + MethodBodiesLength + 15) & ~15U;
+ }
+ }
+ }
+
+ private uint ResourcesLength
+ {
+ get { return (uint)moduleBuilder.manifestResources.Length; }
+ }
+
+ internal uint StrongNameSignatureRVA
+ {
+ get
+ {
+ return (ResourcesRVA + ResourcesLength + 3) & ~3U;
+ }
+ }
+
+ internal uint StrongNameSignatureLength
+ {
+ get
+ {
+ return strongNameSignatureLength;
+ }
+ }
+
+ private uint MetadataRVA
+ {
+ get
+ {
+ return (StrongNameSignatureRVA + StrongNameSignatureLength + 3) & ~3U;
+ }
+ }
+
+ private uint MetadataLength
+ {
+ get { return (uint)moduleBuilder.MetadataLength; }
+ }
+
+ internal uint DebugDirectoryRVA
+ {
+ get { return MetadataRVA + MetadataLength; }
+ }
+
+ internal uint DebugDirectoryLength
+ {
+ get
+ {
+ if (DebugDirectoryContentsLength != 0)
+ {
+ return 28;
+ }
+ return 0;
+ }
+ }
+
+ private uint DebugDirectoryContentsLength
+ {
+ get
+ {
+ if (moduleBuilder.symbolWriter != null)
+ {
+ IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY();
+ return (uint)SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd).Length;
+ }
+ return 0;
+ }
+ }
+
+ internal uint ImportDirectoryRVA
+ {
+ // on AMD64 (and probably IA64) the import directory needs to be 16 byte aligned (on I386 4 byte alignment is sufficient)
+ get { return (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength + 15) & ~15U; }
+ }
+
+ internal uint ImportDirectoryLength
+ {
+ get { return (ImportHintNameTableRVA - ImportDirectoryRVA) + 27; }
+ }
+
+ private uint ImportHintNameTableRVA
+ {
+ get
+ {
+ if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+ {
+ return (ImportDirectoryRVA + 48 + 15) & ~15U;
+ }
+ else
+ {
+ return (ImportDirectoryRVA + 48 + 4 + 15) & ~15U;
+ }
+ }
+ }
+
+ internal uint StartupStubRVA
+ {
+ get
+ {
+ if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
+ {
+ // note that the alignment is driven by the requirement that the two relocation fixups are in a single page
+ return (ImportDirectoryRVA + ImportDirectoryLength + 15U) & ~15U;
+ }
+ else
+ {
+ // the additional 2 bytes padding are to align the address in the jump (which is a relocation fixup)
+ return 2 + ((ImportDirectoryRVA + ImportDirectoryLength + 3U) & ~3U);
+ }
+ }
+ }
+
+ internal uint StartupStubLength
+ {
+ get
+ {
+ if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64)
+ {
+ return 12;
+ }
+ else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
+ {
+ return 48;
+ }
+ else
+ {
+ return 6;
+ }
+ }
+ }
+
+ private void WriteRVA(MetadataWriter mw, uint rva)
+ {
+ if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+ {
+ mw.Write(rva);
+ }
+ else
+ {
+ mw.Write((ulong)rva);
+ }
+ }
+
+ internal void Write(MetadataWriter mw, int sdataRVA)
+ {
+ // Now that we're ready to start writing, we need to do some fix ups
+ moduleBuilder.MethodDef.Fixup(this);
+ moduleBuilder.MethodImpl.Fixup(moduleBuilder);
+ moduleBuilder.MethodSemantics.Fixup(moduleBuilder);
+ moduleBuilder.InterfaceImpl.Fixup();
+ moduleBuilder.MemberRef.Fixup(moduleBuilder);
+ moduleBuilder.Constant.Fixup(moduleBuilder);
+ moduleBuilder.FieldMarshal.Fixup(moduleBuilder);
+ moduleBuilder.DeclSecurity.Fixup(moduleBuilder);
+ moduleBuilder.GenericParam.Fixup(moduleBuilder);
+ moduleBuilder.CustomAttribute.Fixup(moduleBuilder);
+ moduleBuilder.FieldLayout.Fixup(moduleBuilder);
+ moduleBuilder.FieldRVA.Fixup(moduleBuilder, sdataRVA);
+ moduleBuilder.ImplMap.Fixup(moduleBuilder);
+ moduleBuilder.MethodSpec.Fixup(moduleBuilder);
+ moduleBuilder.GenericParamConstraint.Fixup(moduleBuilder);
+
+ // Import Address Table
+ AssertRVA(mw, ImportAddressTableRVA);
+ WriteRVA(mw, ImportHintNameTableRVA);
+ WriteRVA(mw, 0);
+
+ // CLI Header
+ AssertRVA(mw, ComDescriptorRVA);
+ cliHeader.MetaDataRVA = MetadataRVA;
+ cliHeader.MetaDataSize = MetadataLength;
+ if (ResourcesLength != 0)
+ {
+ cliHeader.ResourcesRVA = ResourcesRVA;
+ cliHeader.ResourcesSize = ResourcesLength;
+ }
+ if (StrongNameSignatureLength != 0)
+ {
+ cliHeader.StrongNameSignatureRVA = StrongNameSignatureRVA;
+ cliHeader.StrongNameSignatureSize = StrongNameSignatureLength;
+ }
+ cliHeader.Write(mw);
+
+ // alignment padding
+ for (int i = (int)(MethodBodiesRVA - (ComDescriptorRVA + ComDescriptorLength)); i > 0; i--)
+ {
+ mw.Write((byte)0);
+ }
+
+ // Method Bodies
+ mw.Write(moduleBuilder.methodBodies);
+
+ // alignment padding
+ for (int i = (int)(ResourcesRVA - (MethodBodiesRVA + MethodBodiesLength)); i > 0; i--)
+ {
+ mw.Write((byte)0);
+ }
+
+ // Resources
+ mw.Write(moduleBuilder.manifestResources);
+
+ // The strong name signature live here (if it exists), but it will written later
+ // and the following alignment padding will take care of reserving the space.
+
+ // alignment padding
+ for (int i = (int)(MetadataRVA - (ResourcesRVA + ResourcesLength)); i > 0; i--)
+ {
+ mw.Write((byte)0);
+ }
+
+ // Metadata
+ AssertRVA(mw, MetadataRVA);
+ moduleBuilder.WriteMetadata(mw);
+
+ // Debug Directory
+ AssertRVA(mw, DebugDirectoryRVA);
+ WriteDebugDirectory(mw);
+
+ // alignment padding
+ for (int i = (int)(ImportDirectoryRVA - (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength)); i > 0; i--)
+ {
+ mw.Write((byte)0);
+ }
+
+ // Import Directory
+ AssertRVA(mw, ImportDirectoryRVA);
+ WriteImportDirectory(mw);
+
+ // alignment padding
+ for (int i = (int)(StartupStubRVA - (ImportDirectoryRVA + ImportDirectoryLength)); i > 0; i--)
+ {
+ mw.Write((byte)0);
+ }
+
+ // Startup Stub
+ AssertRVA(mw, StartupStubRVA);
+ if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64)
+ {
+ /*
+ * 48 A1 00 20 40 00 00 00 00 00 mov rax,qword ptr [0000000000402000h]
+ * FF E0 jmp rax
+ */
+ mw.Write((ushort)0xA148);
+ mw.Write(peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
+ mw.Write((ushort)0xE0FF);
+ }
+ else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
+ {
+ mw.Write(new byte[] {
+ 0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00
+ });
+ mw.Write(peWriter.Headers.OptionalHeader.ImageBase + StartupStubRVA);
+ mw.Write(peWriter.Headers.OptionalHeader.ImageBase + BaseRVA);
+ }
+ else
+ {
+ mw.Write((ushort)0x25FF);
+ mw.Write((uint)peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
+ }
+ }
+
+ [Conditional("DEBUG")]
+ private void AssertRVA(MetadataWriter mw, uint rva)
+ {
+ Debug.Assert(mw.Position - PointerToRawData + BaseRVA == rva);
+ }
+
+ private void WriteDebugDirectory(MetadataWriter mw)
+ {
+ if (DebugDirectoryLength != 0)
+ {
+ IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY();
+ idd.Characteristics = 0;
+ idd.TimeDateStamp = peWriter.Headers.FileHeader.TimeDateStamp;
+ byte[] buf = SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd);
+ idd.PointerToRawData = (DebugDirectoryRVA - BaseRVA) + DebugDirectoryLength + PointerToRawData;
+ mw.Write(idd.Characteristics);
+ mw.Write(idd.TimeDateStamp);
+ mw.Write(idd.MajorVersion);
+ mw.Write(idd.MinorVersion);
+ mw.Write(idd.Type);
+ mw.Write(idd.SizeOfData);
+ mw.Write(idd.AddressOfRawData);
+ mw.Write(idd.PointerToRawData);
+ mw.Write(buf);
+ }
+ }
+
+ private void WriteImportDirectory(MetadataWriter mw)
+ {
+ mw.Write(ImportDirectoryRVA + 40); // ImportLookupTable
+ mw.Write(0); // DateTimeStamp
+ mw.Write(0); // ForwarderChain
+ mw.Write(ImportHintNameTableRVA + 14); // Name
+ mw.Write(ImportAddressTableRVA);
+ mw.Write(new byte[20]);
+ // Import Lookup Table
+ mw.Write(ImportHintNameTableRVA); // Hint/Name Table RVA
+ int size = 48;
+ if (peWriter.Headers.FileHeader.Machine != IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
+ {
+ size += 4;
+ mw.Write(0);
+ }
+ mw.Write(0);
+
+ // alignment padding
+ for (int i = (int)(ImportHintNameTableRVA - (ImportDirectoryRVA + size)); i > 0; i--)
+ {
+ mw.Write((byte)0);
+ }
+
+ // Hint/Name Table
+ AssertRVA(mw, ImportHintNameTableRVA);
+ mw.Write((ushort)0); // Hint
+ if ((peWriter.Headers.FileHeader.Characteristics & IMAGE_FILE_HEADER.IMAGE_FILE_DLL) != 0)
+ {
+ mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorDllMain"));
+ }
+ else
+ {
+ mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorExeMain"));
+ }
+ mw.Write((byte)0);
+ // Name
+ mw.Write(System.Text.Encoding.ASCII.GetBytes("mscoree.dll"));
+ mw.Write((ushort)0);
+ }
+
+ internal int Length
+ {
+ get { return (int)(StartupStubRVA - BaseRVA + StartupStubLength); }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Globalization;
+using IKVM.Reflection.Emit;
+
+namespace IKVM.Reflection.Writer
+{
+ sealed class VersionInfo
+ {
+ private AssemblyName name;
+ private string fileName;
+ internal string copyright;
+ internal string trademark;
+ internal string product;
+ internal string company;
+ private string description;
+ private string title;
+ internal string informationalVersion;
+ private string culture;
+ private string fileVersion;
+
+ internal void SetName(AssemblyName name)
+ {
+ this.name = name;
+ }
+
+ internal void SetFileName(string assemblyFileName)
+ {
+ this.fileName = assemblyFileName;
+ }
+
+ internal void SetAttribute(CustomAttributeBuilder cab)
+ {
+ Universe u = cab.Constructor.Module.universe;
+ Type type = cab.Constructor.DeclaringType;
+ if (copyright == null && type == u.System_Reflection_AssemblyCopyrightAttribute)
+ {
+ copyright = (string)cab.GetConstructorArgument(0);
+ }
+ else if (trademark == null && type == u.System_Reflection_AssemblyTrademarkAttribute)
+ {
+ trademark = (string)cab.GetConstructorArgument(0);
+ }
+ else if (product == null && type == u.System_Reflection_AssemblyProductAttribute)
+ {
+ product = (string)cab.GetConstructorArgument(0);
+ }
+ else if (company == null && type == u.System_Reflection_AssemblyCompanyAttribute)
+ {
+ company = (string)cab.GetConstructorArgument(0);
+ }
+ else if (description == null && type == u.System_Reflection_AssemblyDescriptionAttribute)
+ {
+ description = (string)cab.GetConstructorArgument(0);
+ }
+ else if (title == null && type == u.System_Reflection_AssemblyTitleAttribute)
+ {
+ title = (string)cab.GetConstructorArgument(0);
+ }
+ else if (informationalVersion == null && type == u.System_Reflection_AssemblyInformationalVersionAttribute)
+ {
+ informationalVersion = (string)cab.GetConstructorArgument(0);
+ }
+ else if (culture == null && type == u.System_Reflection_AssemblyCultureAttribute)
+ {
+ culture = (string)cab.GetConstructorArgument(0);
+ }
+ else if (fileVersion == null && type == u.System_Reflection_AssemblyFileVersionAttribute)
+ {
+ fileVersion = (string)cab.GetConstructorArgument(0);
+ }
+ }
+
+ internal void Write(ByteBuffer bb)
+ {
+ if (fileVersion == null)
+ {
+ if (name.Version != null)
+ {
+ fileVersion = name.Version.ToString();
+ }
+ else
+ {
+ fileVersion = "0.0.0.0";
+ }
+ }
+
+ int codepage = 1200; // Unicode codepage
+ int lcid = 0x7f;
+ if (name.CultureInfo != null)
+ {
+ lcid = name.CultureInfo.LCID;
+ }
+ if (culture != null)
+ {
+ lcid = new CultureInfo(culture).LCID;
+ }
+
+ Version filever = ParseVersionRobust(fileVersion);
+ int fileVersionMajor = filever.Major;
+ int fileVersionMinor = filever.Minor;
+ int fileVersionBuild = filever.Build;
+ int fileVersionRevision = filever.Revision;
+
+ int productVersionMajor = fileVersionMajor;
+ int productVersionMinor = fileVersionMinor;
+ int productVersionBuild = fileVersionBuild;
+ int productVersionRevision = fileVersionRevision;
+ if (informationalVersion != null)
+ {
+ Version productver = ParseVersionRobust(informationalVersion);
+ productVersionMajor = productver.Major;
+ productVersionMinor = productver.Minor;
+ productVersionBuild = productver.Build;
+ productVersionRevision = productver.Revision;
+ }
+
+ ByteBuffer stringTable = new ByteBuffer(512);
+ stringTable.Write((short)0); // wLength (placeholder)
+ stringTable.Write((short)0); // wValueLength
+ stringTable.Write((short)1); // wType
+ WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage));
+ stringTable.Align(4);
+
+ WriteString(stringTable, "Comments", description);
+ WriteString(stringTable, "CompanyName", company);
+ WriteString(stringTable, "FileDescription", title);
+ WriteString(stringTable, "FileVersion", fileVersion);
+ WriteString(stringTable, "InternalName", name.Name);
+ WriteString(stringTable, "LegalCopyright", copyright);
+ WriteString(stringTable, "LegalTrademarks", trademark);
+ WriteString(stringTable, "OriginalFilename", fileName);
+ WriteString(stringTable, "ProductName", product);
+ WriteString(stringTable, "ProductVersion", informationalVersion);
+
+ stringTable.Position = 0;
+ stringTable.Write((short)stringTable.Length);
+
+ ByteBuffer stringFileInfo = new ByteBuffer(512);
+ stringFileInfo.Write((short)0); // wLength (placeholder)
+ stringFileInfo.Write((short)0); // wValueLength
+ stringFileInfo.Write((short)1); // wType
+ WriteUTF16Z(stringFileInfo, "StringFileInfo");
+ stringFileInfo.Align(4);
+ stringFileInfo.Write(stringTable);
+ stringFileInfo.Position = 0;
+ stringFileInfo.Write((short)stringFileInfo.Length);
+
+ byte[] preamble1 = new byte[] {
+ // VS_VERSIONINFO (platform SDK)
+ 0x34, 0x00, // wValueLength
+ 0x00, 0x00, // wType
+ 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, // "VS_VERSION_INFO\0"
+ 0x00, 0x00, // Padding1 (32 bit alignment)
+ // VS_FIXEDFILEINFO starts
+ 0xBD, 0x04, 0xEF, 0xFE, // dwSignature (0xFEEF04BD)
+ 0x00, 0x00, 0x01, 0x00, // dwStrucVersion
+ };
+ byte[] preamble2 = new byte[] {
+ 0x3F, 0x00, 0x00, 0x00, // dwFileFlagsMask (??)
+ 0x00, 0x00, 0x00, 0x00, // dwFileFlags (??)
+ 0x04, 0x00, 0x00, 0x00, // dwFileOS
+ 0x02, 0x00, 0x00, 0x00, // dwFileType
+ 0x00, 0x00, 0x00, 0x00, // dwFileSubtype
+ 0x00, 0x00, 0x00, 0x00, // dwFileDateMS
+ 0x00, 0x00, 0x00, 0x00, // dwFileDateLS
+ // Padding2 (32 bit alignment)
+ // VarFileInfo
+ 0x44, 0x00, // wLength
+ 0x00, 0x00, // wValueLength
+ 0x01, 0x00, // wType
+ 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, // "VarFileInfo\0"
+ 0x00, 0x00, // Padding
+ // Var
+ 0x24, 0x00, // wLength
+ 0x04, 0x00, // wValueLength
+ 0x00, 0x00, // wType
+ 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, // "Translation\0"
+ 0x00, 0x00, // Padding (32 bit alignment)
+ };
+ bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length));
+ bb.Write(preamble1);
+ bb.Write((short)fileVersionMinor);
+ bb.Write((short)fileVersionMajor);
+ bb.Write((short)fileVersionRevision);
+ bb.Write((short)fileVersionBuild);
+ bb.Write((short)productVersionMinor);
+ bb.Write((short)productVersionMajor);
+ bb.Write((short)productVersionRevision);
+ bb.Write((short)productVersionBuild);
+ bb.Write(preamble2);
+ bb.Write((short)lcid);
+ bb.Write((short)codepage);
+ bb.Write(stringFileInfo);
+ }
+
+ private static void WriteUTF16Z(ByteBuffer bb, string str)
+ {
+ foreach (char c in str)
+ {
+ bb.Write((short)c);
+ }
+ bb.Write((short)0);
+ }
+
+ private static void WriteString(ByteBuffer bb, string name, string value)
+ {
+ value = value ?? " ";
+ int pos = bb.Position;
+ bb.Write((short)0); // wLength (placeholder)
+ bb.Write((short)(value.Length + 1));// wValueLength
+ bb.Write((short)1); // wType
+ WriteUTF16Z(bb, name);
+ bb.Align(4);
+ WriteUTF16Z(bb, value);
+ bb.Align(4);
+ int savedPos = bb.Position;
+ bb.Position = pos;
+ bb.Write((short)(savedPos - pos));
+ bb.Position = savedPos;
+ }
+
+ private static Version ParseVersionRobust(string ver)
+ {
+ int index = 0;
+ ushort major = ParseVersionPart(ver, ref index);
+ ushort minor = ParseVersionPart(ver, ref index);
+ ushort build = ParseVersionPart(ver, ref index);
+ ushort revision = ParseVersionPart(ver, ref index);
+ return new Version(major, minor, build, revision);
+ }
+
+ private static ushort ParseVersionPart(string str, ref int pos)
+ {
+ ushort value = 0;
+ while (pos < str.Length)
+ {
+ char c = str[pos];
+ if (c == '.')
+ {
+ pos++;
+ break;
+ }
+ else if (c >= '0' && c <= '9')
+ {
+ value *= 10;
+ value += (ushort)(c - '0');
+ pos++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return value;
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0"?>
+<project name="reflect" default="IKVM.Reflection">
+ <target name="IKVM.Reflection">
+ <property name="defs" value="TRACE" />
+ <if test="${framework::exists('mono-2.0')}">
+ <property name="defs" value="${defs};MONO" />
+ </if>
+ <if test="${property::exists('signed')}">
+ <property name="defs" value="${defs};${signed}" />
+ </if>
+ <if test="${version::get-major(framework::get-version(framework::get-target-framework() )) == 4}">
+ <property name="defs" value="${defs};NET_4_0" />
+ </if>
+ <!-- workaround for the fact that <include if="${framework::exists('mono-2.0')} ...> still insists on evaluating the name attribute -->
+ <property name="MonoSymbolWriter" value="dummy.dll" />
+ <if test="${framework::exists('mono-2.0')}">
+ <property name="MonoSymbolWriter" value="${path::combine(framework::get-assembly-directory('mono-2.0'), 'Mono.CompilerServices.SymbolWriter.dll')}" />
+ </if>
+ <csc target="library" output="../bin/IKVM.Reflection.dll" optimize="true" define="${defs}">
+ <sources>
+ <include name="../CommonAssemblyInfo.cs" />
+ <include name="AmbiguousMatchException.cs" />
+ <include name="Assembly.cs" />
+ <include name="AssemblyName.cs" />
+ <include name="BadImageFormatException.cs" />
+ <include name="Binder.cs" />
+ <include name="ConstructorInfo.cs" />
+ <include name="CustomAttributeData.cs" />
+ <include name="CustomAttributeNamedArgument.cs" />
+ <include name="CustomAttributeTypedArgument.cs" />
+ <include name="Enums.cs" />
+ <include name="EventInfo.cs" />
+ <include name="ExceptionHandlingClause.cs" />
+ <include name="FieldInfo.cs" />
+ <include name="FieldSignature.cs" />
+ <include name="Fusion.cs" />
+ <include name="GenericWrappers.cs" />
+ <include name="InterfaceMapping.cs" />
+ <include name="LocalVariableInfo.cs" />
+ <include name="ManifestResourceInfo.cs" />
+ <include name="MarshalSpec.cs" />
+ <include name="MemberInfo.cs" />
+ <include name="MethodBase.cs" />
+ <include name="MethodBody.cs" />
+ <include name="MethodImplMap.cs" />
+ <include name="MethodInfo.cs" />
+ <include name="MethodSignature.cs" />
+ <include name="Module.cs" />
+ <include name="ParameterInfo.cs" />
+ <include name="ParameterModifier.cs" />
+ <include name="PropertyInfo.cs" />
+ <include name="PropertySignature.cs" />
+ <include name="Signature.cs" />
+ <include name="StandAloneMethodSig.cs" />
+ <include name="StrongNameKeyPair.cs" />
+ <include name="Type.cs" />
+ <include name="TypeNameParser.cs" />
+ <include name="Universe.cs" />
+ <include name="Util.cs" />
+ <include name="Emit\AssemblyBuilder.cs" />
+ <include name="Emit\ConstructorBuilder.cs" />
+ <include name="Emit\CustomAttributeBuilder.cs" />
+ <include name="Emit\EnumBuilder.cs" />
+ <include name="Emit\Enums.cs" />
+ <include name="Emit\EventBuilder.cs" />
+ <include name="Emit\FieldBuilder.cs" />
+ <include name="Emit\ILGenerator.cs" />
+ <include name="Emit\MethodBuilder.cs" />
+ <include name="Emit\ModuleBuilder.cs" />
+ <include name="Emit\OpCode.cs" />
+ <include name="Emit\OpCodes.cs" />
+ <include name="Emit\ParameterBuilder.cs" />
+ <include name="Emit\PropertyBuilder.cs" />
+ <include name="Emit\SignatureHelper.cs" />
+ <include name="Emit\Tokens.cs" />
+ <include name="Emit\TypeBuilder.cs" />
+ <include name="Impl\CryptoConvert.cs" />
+ <include name="Impl\CryptoHack.cs" />
+ <include name="Impl\ITypeOwner.cs" />
+ <include name="Impl\MdbWriter.cs" />
+ <include name="Impl\PdbWriter.cs" />
+ <include name="Impl\SymbolSupport.cs" />
+ <include name="Metadata\CliHeader.cs" />
+ <include name="Metadata\MetadataRW.cs" />
+ <include name="Metadata\Tables.cs" />
+ <include name="Properties\AssemblyInfo.cs" />
+ <include name="Reader\AssemblyReader.cs" />
+ <include name="Reader\ByteReader.cs" />
+ <include name="Reader\EventInfoImpl.cs" />
+ <include name="Reader\Field.cs" />
+ <include name="Reader\GenericTypeParameter.cs" />
+ <include name="Reader\MetadataReader.cs" />
+ <include name="Reader\Method.cs" />
+ <include name="Reader\ModuleReader.cs" />
+ <include name="Reader\PEReader.cs" />
+ <include name="Reader\PropertyInfoImpl.cs" />
+ <include name="Reader\ResourceModule.cs" />
+ <include name="Reader\TypeDefImpl.cs" />
+ <include name="Writer\ByteBuffer.cs" />
+ <include name="Writer\Heaps.cs" />
+ <include name="Writer\MetadataWriter.cs" />
+ <include name="Writer\ModuleWriter.cs" />
+ <include name="Writer\PEWriter.cs" />
+ <include name="Writer\ResourceSection.cs" />
+ <include name="Writer\TextSection.cs" />
+ <include name="Writer\VersionInfo.cs" />
+ </sources>
+ <references>
+ <include if="${framework::exists('mono-2.0')}" name="${MonoSymbolWriter}" />
+ </references>
+ </csc>
+ </target>
+</project>