This commit is contained in:
jfrijters 2008-11-14 07:40:49 +00:00
Родитель 19f5c9cd08
Коммит 4f74774934
30 изменённых файлов: 11356 добавлений и 0 удалений

268
refemit/AssemblyBuilder.cs Normal file
Просмотреть файл

@ -0,0 +1,268 @@
/*
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.Reflection;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;
using IKVM.Reflection.Emit.Writer;
using IKVM.Reflection.Emit.Impl;
namespace IKVM.Reflection.Emit
{
public sealed class AssemblyBuilder : IkvmAssembly
{
private readonly AssemblyName name;
private readonly string dir;
private PEFileKinds fileKind = PEFileKinds.Dll;
private MethodBuilder entryPoint;
private bool setVersionInfo;
private List<ResourceFile> resourceFiles = new List<ResourceFile>();
private List<ModuleBuilder> modules = new List<ModuleBuilder>();
private List<CustomAttributeBuilder> customAttributes = new List<CustomAttributeBuilder>();
private struct ResourceFile
{
internal string Name;
internal string FileName;
internal ResourceAttributes Attributes;
}
private AssemblyBuilder(AssemblyName name, string dir)
{
this.name = name;
this.dir = dir;
}
public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)
{
return DefineDynamicAssembly(name, access, null);
}
public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, string dir)
{
return new AssemblyBuilder(name, dir);
}
public AssemblyName GetName()
{
return name;
}
public string FullName
{
get { return name.FullName; }
}
public ModuleBuilder DefineDynamicModule(string name, string fileName, bool emitSymbolInfo)
{
ModuleBuilder module = new ModuleBuilder(this, name, fileName, emitSymbolInfo);
modules.Add(module);
return module;
}
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
if (customBuilder.Constructor.DeclaringType == typeof(AssemblyVersionAttribute))
{
throw new NotImplementedException();
}
else
{
customAttributes.Add(customBuilder);
}
}
public void SetEntryPoint(MethodBuilder mb)
{
SetEntryPoint(mb, PEFileKinds.ConsoleApplication);
}
public void SetEntryPoint(MethodBuilder mb, PEFileKinds kind)
{
this.entryPoint = mb;
this.fileKind = kind;
}
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)
{
if (string.Compare(moduleBuilder.fileName, assemblyFileName, StringComparison.OrdinalIgnoreCase) == 0)
{
manifestModule = moduleBuilder;
break;
}
}
if (manifestModule == null)
{
manifestModule = DefineDynamicModule("RefEmit_OnDiskManifestModule", assemblyFileName, false);
}
TableHeap.AssemblyTable.Record assemblyRecord = new TableHeap.AssemblyTable.Record();
assemblyRecord.HashAlgId = 0x8004; // SHA1
assemblyRecord.Name = manifestModule.Strings.Add(name.Name);
if (name.Version != null)
{
assemblyRecord.MajorVersion = (short)name.Version.Major;
assemblyRecord.MinorVersion = (short)name.Version.Major;
assemblyRecord.BuildNumber = (short)name.Version.Build;
assemblyRecord.RevisionNumber = (short)name.Version.Revision;
}
if (name.KeyPair != null)
{
assemblyRecord.PublicKey = manifestModule.Blobs.Add(ByteBuffer.Wrap(name.KeyPair.PublicKey));
assemblyRecord.Flags |= 0x0001; // PublicKey
}
if (name.CultureInfo != null)
{
assemblyRecord.Culture = manifestModule.Strings.Add(name.CultureInfo.Name);
}
manifestModule.Tables.Assembly.AddRecord(assemblyRecord);
ByteBuffer versionInfoData = null;
if (setVersionInfo)
{
VersionInfo versionInfo = new VersionInfo();
versionInfo.SetName(name);
versionInfo.SetFileName(assemblyFileName);
foreach (CustomAttributeBuilder cab in customAttributes)
{
versionInfo.SetAttribute(cab);
}
versionInfoData = new ByteBuffer(512);
versionInfo.Write(versionInfoData);
}
foreach (CustomAttributeBuilder cab in customAttributes)
{
manifestModule.SetCustomAttribute(0x20000001, cab);
}
foreach (ResourceFile resfile in resourceFiles)
{
int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/);
TableHeap.ManifestResourceTable.Record rec = new TableHeap.ManifestResourceTable.Record();
rec.Offset = 0;
rec.Flags = (int)resfile.Attributes;
rec.Name = manifestModule.Strings.Add(resfile.Name);
rec.Implementation = fileToken;
manifestModule.Tables.ManifestResource.AddRecord(rec);
}
int entryPointToken = 0;
foreach (ModuleBuilder moduleBuilder in modules)
{
if (moduleBuilder != manifestModule)
{
int fileToken;
if (entryPoint != null && entryPoint.ModuleBuilder == moduleBuilder)
{
ModuleWriter.WriteModule(dir, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, null, entryPoint.MetadataToken);
entryPointToken = fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
}
else
{
ModuleWriter.WriteModule(dir, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, null, 0);
fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
}
moduleBuilder.ExportTypes(fileToken, manifestModule);
}
}
if (entryPointToken == 0 && entryPoint != null)
{
entryPointToken = entryPoint.MetadataToken;
}
// finally, write the manifest module
ModuleWriter.WriteModule(dir, name.KeyPair, manifestModule, fileKind, portableExecutableKind, imageFileMachine, versionInfoData, 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);
}
}
TableHeap.FileTable.Record file = new TableHeap.FileTable.Record();
file.Flags = flags;
file.Name = manifestModule.Strings.Add(fileName);
file.HashValue = manifestModule.Blobs.Add(ByteBuffer.Wrap(hash.Hash));
return 0x26000000 + manifestModule.Tables.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()
{
setVersionInfo = true;
}
public override Type GetType(string typeName)
{
foreach (ModuleBuilder mb in modules)
{
Type type = mb.GetType(typeName);
if (type != null)
{
return type;
}
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,133 @@
/*
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.Reflection;
namespace IKVM.Reflection.Emit
{
public sealed class ConstructorBuilder : ConstructorInfo
{
private readonly MethodBuilder methodBuilder;
internal ConstructorBuilder(MethodBuilder mb)
{
this.methodBuilder = mb;
}
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 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 override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
public override MethodAttributes Attributes
{
get { return methodBuilder.Attributes; }
}
public override MethodImplAttributes GetMethodImplementationFlags()
{
return methodBuilder.GetMethodImplementationFlags();
}
public override ParameterInfo[] GetParameters()
{
return methodBuilder.GetParameters();
}
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
{
return methodBuilder.Invoke(obj, invokeAttr, binder, parameters, culture);
}
public override RuntimeMethodHandle MethodHandle
{
get { return methodBuilder.MethodHandle; }
}
public override Type DeclaringType
{
get { return methodBuilder.DeclaringType; }
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
return methodBuilder.GetCustomAttributes(attributeType, inherit);
}
public override object[] GetCustomAttributes(bool inherit)
{
return methodBuilder.GetCustomAttributes(inherit);
}
public override bool IsDefined(Type attributeType, bool inherit)
{
return methodBuilder.IsDefined(attributeType, inherit);
}
public override string Name
{
get { return methodBuilder.Name; }
}
public override Type ReflectedType
{
get { return methodBuilder.ReflectedType; }
}
public override int MetadataToken
{
get { return methodBuilder.MetadataToken; }
}
internal ModuleBuilder ModuleBuilder
{
get { return methodBuilder.ModuleBuilder; }
}
}
}

Просмотреть файл

@ -0,0 +1,465 @@
/*
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.Reflection;
using System.IO;
using IKVM.Reflection.Emit.Writer;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
namespace IKVM.Reflection.Emit
{
public 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;
this.constructorArgs = null;
this.namedProperties = null;
this.propertyValues = null;
this.namedFields = null;
this.fieldValues = null;
}
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, FieldInfo[] namedFields, object[] fieldValues)
{
this.con = con;
this.blob = null;
this.constructorArgs = constructorArgs;
this.namedProperties = namedProperties;
this.propertyValues = propertyValues;
this.namedFields = namedFields;
this.fieldValues = fieldValues;
}
private class BlobWriter
{
private readonly ModuleBuilder moduleBuilder;
private readonly CustomAttributeBuilder cab;
private readonly MemoryStream str = new MemoryStream();
internal BlobWriter(ModuleBuilder moduleBuilder, CustomAttributeBuilder cab)
{
this.moduleBuilder = moduleBuilder;
this.cab = cab;
}
internal byte[] GetBlob()
{
// prolog
WriteUInt16(1);
ParameterInfo[] pi = cab.con.GetParameters();
for (int i = 0; i < pi.Length; i++)
{
WriteFixedArg(pi[i].ParameterType, cab.constructorArgs[i]);
}
// NumNamed
int named = 0;
if (cab.namedFields != null)
{
named += cab.namedFields.Length;
}
if (cab.namedProperties != null)
{
named += cab.namedProperties.Length;
}
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]);
}
}
return str.ToArray();
}
private void WriteNamedArg(byte fieldOrProperty, Type type, string name, object value)
{
str.WriteByte(fieldOrProperty);
WriteFieldOrPropType(type);
WriteString(name);
WriteFixedArg(type, value);
}
private void WriteUInt16(ushort value)
{
str.WriteByte((byte)value);
str.WriteByte((byte)(value >> 8));
}
private void WriteInt32(int value)
{
str.WriteByte((byte)(value >> 0));
str.WriteByte((byte)(value >> 8));
str.WriteByte((byte)(value >> 16));
str.WriteByte((byte)(value >> 24));
}
private void WriteFixedArg(Type type, object value)
{
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)
{
WriteElem(elemType, val);
}
}
}
else
{
WriteElem(type, value);
}
}
private void WriteElem(Type type, object value)
{
if (type == typeof(string))
{
WriteString((string)value);
}
else if (type == typeof(Type))
{
WriteTypeName((Type)value);
}
else if (type == typeof(object))
{
if (value == null)
{
type = typeof(string);
}
else if (value is Type)
{
// value.GetType() would return a RuntimeType, but we don't want to deal with that
type = typeof(Type);
}
else
{
type = value.GetType();
}
WriteFieldOrPropType(type);
WriteElem(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)
{
WriteElem(elemType, val);
}
}
}
else if (type.IsEnum)
{
WriteElem(Enum.GetUnderlyingType(type), value);
}
else
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
str.WriteByte((bool)value ? (byte)1 : (byte)0);
break;
case TypeCode.Char:
WriteUInt16((char)value);
break;
case TypeCode.SByte:
str.WriteByte((byte)(sbyte)value);
break;
case TypeCode.Byte:
str.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 NotImplementedException();
}
}
}
private void WriteInt64(long value)
{
WriteInt32((int)value);
WriteInt32((int)(value >> 32));
}
private void WriteSingle(float value)
{
str.Write(BitConverter.GetBytes(value), 0, 4);
}
private void WriteDouble(double value)
{
WriteInt64(BitConverter.DoubleToInt64Bits(value));
}
private void WriteTypeName(Type type)
{
string name = null;
if (type != null)
{
// we could also use just the FullName for mscorlib types (IkvmAssembly.GetAssembly(type) == IkvmAssembly.GetAssembly(typeof(object)))
if (IkvmAssembly.GetAssembly(type) == moduleBuilder.Assembly)
{
name = type.FullName;
}
else
{
name = type.AssemblyQualifiedName;
}
}
WriteString(name);
}
private void WriteString(string val)
{
if (val == null)
{
str.WriteByte(0xFF);
}
else
{
byte[] buf = System.Text.Encoding.UTF8.GetBytes(val);
WritePackedLen(buf.Length);
str.Write(buf, 0, buf.Length);
}
}
private void WritePackedLen(int len)
{
if (len < 0 || len > 0x1FFFFFFF)
throw new ArgumentOutOfRangeException();
if (len <= 0x7F)
str.WriteByte((byte)len);
else if (len <= 0x3FFF)
{
str.WriteByte((byte)(0x80 | (len >> 8)));
str.WriteByte((byte)len);
}
else
{
str.WriteByte((byte)(0xC0 | (len >> 24)));
str.WriteByte((byte)(len >> 16));
str.WriteByte((byte)(len >> 8));
str.WriteByte((byte)len);
}
}
private void WriteFieldOrPropType(Type type)
{
if (type == typeof(Type))
{
str.WriteByte(0x50);
}
else if (type == typeof(object))
{
str.WriteByte(0x51);
}
else if (type.IsArray)
{
str.WriteByte(0x1D);
WriteFieldOrPropType(type.GetElementType());
}
else if (type.IsEnum)
{
str.WriteByte(0x55);
WriteTypeName(type);
}
else
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
str.WriteByte(0x02);
break;
case TypeCode.Char:
str.WriteByte(0x03);
break;
case TypeCode.SByte:
str.WriteByte(0x04);
break;
case TypeCode.Byte:
str.WriteByte(0x05);
break;
case TypeCode.Int16:
str.WriteByte(0x06);
break;
case TypeCode.UInt16:
str.WriteByte(0x07);
break;
case TypeCode.Int32:
str.WriteByte(0x08);
break;
case TypeCode.UInt32:
str.WriteByte(0x09);
break;
case TypeCode.Int64:
str.WriteByte(0x0A);
break;
case TypeCode.UInt64:
str.WriteByte(0x0B);
break;
case TypeCode.Single:
str.WriteByte(0x0C);
break;
case TypeCode.Double:
str.WriteByte(0x0D);
break;
case TypeCode.String:
str.WriteByte(0x0E);
break;
default:
throw new NotImplementedException();
}
}
}
}
internal bool IsPseudoCustomAttribute
{
get
{
Type type = con.DeclaringType;
return type == typeof(AssemblyFlagsAttribute)
|| type == typeof(AssemblyAlgorithmIdAttribute)
|| type == typeof(DllImportAttribute)
|| type == typeof(FieldOffsetAttribute)
|| type == typeof(InAttribute)
|| type == typeof(MarshalAsAttribute)
|| type == typeof(MethodImplAttribute)
|| type == typeof(OutAttribute)
|| type == typeof(StructLayoutAttribute)
|| type == typeof(NonSerializedAttribute)
|| type == typeof(SerializableAttribute)
|| type == typeof(OptionalAttribute)
|| type == typeof(PreserveSigAttribute)
|| type == typeof(AssemblyVersionAttribute)
|| type == typeof(ComImportAttribute)
|| type == typeof(DefaultParameterValueAttribute);
}
}
internal ConstructorInfo Constructor
{
get { return con; }
}
internal int WriteBlob(ModuleBuilder moduleBuilder)
{
BlobWriter bw = new BlobWriter(moduleBuilder, this);
return moduleBuilder.Blobs.Add(ByteBuffer.Wrap(bw.GetBlob()));
}
internal bool IsBlob
{
get { return blob != null; }
}
internal object GetConstructorArgument(int pos)
{
return constructorArgs[pos];
}
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;
}
}
}

79
refemit/Enums.cs Normal file
Просмотреть файл

@ -0,0 +1,79 @@
/*
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 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,
}
public enum PEFileKinds
{
Dll = 1,
ConsoleApplication = 2,
WindowApplication = 3,
}
}

223
refemit/FieldBuilder.cs Normal file
Просмотреть файл

@ -0,0 +1,223 @@
/*
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.Reflection;
using IKVM.Reflection.Emit.Writer;
using System.Runtime.InteropServices;
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 Type fieldType;
private readonly Type[] requiredCustomModifiers;
private readonly Type[] optionalCustomModifiers;
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.fieldType = fieldType;
ByteBuffer sig = new ByteBuffer(5);
SignatureHelper.WriteFieldSig(this.typeBuilder.ModuleBuilder, sig, fieldType, requiredCustomModifiers, optionalCustomModifiers);
this.signature = this.typeBuilder.ModuleBuilder.Blobs.Add(sig);
this.attribs = attribs;
this.typeBuilder.ModuleBuilder.Tables.Field.AddRow();
this.requiredCustomModifiers = MethodBuilder.Copy(requiredCustomModifiers);
this.optionalCustomModifiers = MethodBuilder.Copy(optionalCustomModifiers);
}
public void SetConstant(object defaultValue)
{
attribs |= FieldAttributes.HasDefault;
this.ModuleBuilder.AddConstant(pseudoToken, defaultValue);
}
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
if (customBuilder.Constructor.DeclaringType == typeof(FieldOffsetAttribute))
{
TableHeap.FieldLayoutTable.Record rec = new TableHeap.FieldLayoutTable.Record();
rec.Offset = (int)customBuilder.GetConstructorArgument(0);
rec.Field = pseudoToken;
this.ModuleBuilder.Tables.FieldLayout.AddRecord(rec);
}
else if (customBuilder.Constructor.DeclaringType == typeof(MarshalAsAttribute))
{
TableHeap.FieldMarshalTable.Record rec = new TableHeap.FieldMarshalTable.Record();
rec.Parent = pseudoToken;
rec.NativeType = WriteMarshallingDescriptor(this.ModuleBuilder, customBuilder);
this.ModuleBuilder.Tables.FieldMarshal.AddRecord(rec);
attribs |= FieldAttributes.HasFieldMarshal;
}
else if (customBuilder.Constructor.DeclaringType == typeof(NonSerializedAttribute))
{
attribs |= FieldAttributes.NotSerialized;
}
else
{
this.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
}
}
internal static int WriteMarshallingDescriptor(ModuleBuilder moduleBuiler, CustomAttributeBuilder customBuilder)
{
UnmanagedType nativeType;
object val = customBuilder.GetConstructorArgument(0);
if (val is short)
{
nativeType = (UnmanagedType)(short)val;
}
else
{
nativeType = (UnmanagedType)val;
}
ByteBuffer bb = new ByteBuffer(5);
bb.Write((byte)nativeType);
object arraySubType = customBuilder.GetFieldValue("ArraySubType");
if (arraySubType != null)
{
bb.Write((byte)(UnmanagedType)arraySubType);
}
object sizeParamIndex = customBuilder.GetFieldValue("SizeParamIndex");
if (sizeParamIndex != null)
{
bb.WriteCompressedInt((short)sizeParamIndex + 1);
}
object sizeConst = customBuilder.GetFieldValue("SizeConst");
if (sizeConst != null)
{
if (sizeParamIndex == null)
{
bb.WriteCompressedInt(0);
}
bb.WriteCompressedInt((int)sizeConst);
}
if (customBuilder.GetFieldValue("IidParameterIndex") != null
|| customBuilder.GetFieldValue("MarshalCookie") != null
|| customBuilder.GetFieldValue("MarshalType") != null
|| customBuilder.GetFieldValue("MarshalTypeRef") != null
|| customBuilder.GetFieldValue("SafeArraySubType") != null
|| customBuilder.GetFieldValue("SafeArrayUserDefinedSubType") != null)
{
throw new NotImplementedException();
}
return moduleBuiler.Blobs.Add(bb);
}
public override FieldAttributes Attributes
{
get { return attribs; }
}
public override RuntimeFieldHandle FieldHandle
{
get { throw new NotImplementedException(); }
}
public override Type FieldType
{
get { return fieldType; }
}
public override object GetValue(object obj)
{
throw new NotImplementedException();
}
public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
public override Type DeclaringType
{
get { return this.ModuleBuilder.IsModuleType(typeBuilder) ? null : typeBuilder; }
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
throw new NotImplementedException();
}
public override object[] GetCustomAttributes(bool inherit)
{
throw new NotImplementedException();
}
public override bool IsDefined(Type attributeType, bool inherit)
{
throw new NotImplementedException();
}
public override string Name
{
get { return name; }
}
public override Type ReflectedType
{
get { return this.DeclaringType; }
}
public override int MetadataToken
{
get { return 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 ModuleBuilder ModuleBuilder
{
get { return typeBuilder.ModuleBuilder; }
}
internal int ImportTo(ModuleBuilder other)
{
return other.ImportField(typeBuilder, name, fieldType, optionalCustomModifiers, requiredCustomModifiers);
}
}
}

Просмотреть файл

@ -0,0 +1,77 @@
<?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>{3949055D-38DF-4A8F-A632-0F0E62337428}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>IKVM.Reflection.Emit</RootNamespace>
<AssemblyName>IKVM.Reflection.Emit</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>false</SignAssembly>
</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>
<Reference Include="ISymWrapper" />
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\CommonAssemblyInfo.cs" />
<Compile Include="AssemblyBuilder.cs" />
<Compile Include="Enums.cs" />
<Compile Include="ConstructorBuilder.cs" />
<Compile Include="CustomAttributeBuilder.cs" />
<Compile Include="FieldBuilder.cs" />
<Compile Include="IkvmAssembly.cs" />
<Compile Include="ILGenerator.cs" />
<Compile Include="Impl\CryptoConvert.cs" />
<Compile Include="Impl\CryptoHack.cs" />
<Compile Include="Impl\ITypeOwner.cs" />
<Compile Include="Impl\PdbSupport.cs" />
<Compile Include="Impl\TypeBase.cs" />
<Compile Include="MethodBuilder.cs" />
<Compile Include="ModuleBuilder.cs" />
<Compile Include="OpCodes.cs" />
<Compile Include="ParameterBuilder.cs" />
<Compile Include="Tokens.cs" />
<Compile Include="Writer\ModuleWriter.cs" />
<Compile Include="Writer\PEWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PropertyBuilder.cs" />
<Compile Include="SignatureHelper.cs" />
<Compile Include="TypeBuilder.cs" />
<Compile Include="Writer\ByteBuffer.cs" />
<Compile Include="Writer\TextSection.cs" />
<Compile Include="Writer\Heaps.cs" />
<Compile Include="Writer\MetadataWriter.cs" />
<Compile Include="Writer\VersionInfo.cs" />
</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>

1000
refemit/ILGenerator.cs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

70
refemit/IkvmAssembly.cs Normal file
Просмотреть файл

@ -0,0 +1,70 @@
/*
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.Reflection;
using IKVM.Reflection.Emit.Impl;
namespace IKVM.Reflection.Emit
{
public abstract class IkvmAssembly
{
private static readonly Dictionary<Assembly, IkvmAssembly> assemblies = new Dictionary<Assembly, IkvmAssembly>();
internal IkvmAssembly() { }
private class AssemblyWrapper : IkvmAssembly
{
private readonly Assembly asm;
internal AssemblyWrapper(Assembly asm)
{
this.asm = asm;
}
public override Type GetType(string typeName)
{
return asm.GetType(typeName);
}
}
public static IkvmAssembly GetAssembly(Type type)
{
TypeBase tb = type as TypeBase;
if (tb != null)
{
return tb.ModuleBuilder.Assembly;
}
IkvmAssembly ikvmAssembly;
if (!assemblies.TryGetValue(type.Assembly, out ikvmAssembly))
{
ikvmAssembly = new AssemblyWrapper(type.Assembly);
assemblies.Add(type.Assembly, ikvmAssembly);
}
return ikvmAssembly;
}
public abstract Type GetType(string typeName);
}
}

Просмотреть файл

@ -0,0 +1,743 @@
//
// 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;
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
/*
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.Reflection;
using System.Runtime.Serialization;
namespace IKVM.Reflection.Emit.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).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);
}
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
/*
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.Impl
{
interface ITypeOwner
{
ModuleBuilder ModuleBuilder { get; }
}
}

179
refemit/Impl/PdbSupport.cs Normal file
Просмотреть файл

@ -0,0 +1,179 @@
/*
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.InteropServices;
using System.Diagnostics.SymbolStore;
namespace IKVM.Reflection.Emit.Impl
{
static class PdbSupport
{
[Guid("809c652e-7396-11d2-9771-00a0c9b4d50c")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[CoClass(typeof(MetaDataDispenserClass))]
[ComImport]
private interface IMetaDataDispenser
{
void DefineScope(
[In] ref Guid rclsid,
[In] int dwCreateFlags,
[In] ref Guid riid,
[Out, MarshalAs(UnmanagedType.IUnknown)] out object punk);
}
[Guid("e5cb7a31-7512-11d2-89ce-0080c792e5d8")]
[ComImport]
private class MetaDataDispenserClass { }
[Guid("7dac8207-d3ae-4c75-9b67-92801a497d44")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
private interface IMetadataImport { }
[Guid("ba3fee4c-ecb9-4e41-83b7-183fa41cd859")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
private interface IMetaDataEmit { }
[Guid("ed14aa72-78e2-4884-84e2-334293ae5214")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
[CoClass(typeof(CorSymWriterClass))]
private interface ISymUnmanagedWriter
{
void PlaceHolder_DefineDocument();
void PlaceHolder_SetUserEntryPoint();
void PlaceHolder_OpenMethod();
void PlaceHolder_CloseMethod();
void PlaceHolder_OpenScope();
void PlaceHolder_CloseScope();
void PlaceHolder_SetScopeRange();
void PlaceHolder_DefineLocalVariable();
void PlaceHolder_DefineParameter();
void PlaceHolder_DefineField();
void PlaceHolder_DefineGlobalVariable();
void PlaceHolder_Close();
void PlaceHolder_SetSymAttribute();
void PlaceHolder_OpenNamespace();
void PlaceHolder_CloseNamespace();
void PlaceHolder_UsingNamespace();
void PlaceHolder_SetMethodSourceRange();
void PlaceHolder_Initialize();
void GetDebugInfo(
[In, Out] ref IMAGE_DEBUG_DIRECTORY pIDD,
[In] uint cData,
[Out] out uint pcData,
[Out, MarshalAs(UnmanagedType.LPArray)] byte[] data);
void PlaceHolder_DefineSequencePoints();
void RemapToken(
[In] int oldToken,
[In] int newToken);
}
[Guid("108296c1-281e-11d3-bd22-0000f80849bd")]
[ComImport]
private class CorSymWriterClass { }
[StructLayout(LayoutKind.Sequential)]
internal struct IMAGE_DEBUG_DIRECTORY
{
internal uint Characteristics;
internal uint TimeDateStamp;
internal ushort MajorVersion;
internal ushort MinorVersion;
internal uint Type;
internal uint SizeOfData;
internal uint AddressOfRawData;
internal uint PointerToRawData;
}
private sealed class MySymWriter : SymWriter
{
private readonly IntPtr ppISymUnmanagedWriter = Marshal.AllocHGlobal(IntPtr.Size);
private readonly ISymUnmanagedWriter symUnmanagedWriter = new ISymUnmanagedWriter();
private readonly IntPtr pISymUnmanagedWriter;
internal MySymWriter(string fileName)
{
pISymUnmanagedWriter = Marshal.GetComInterfaceForObject(symUnmanagedWriter, typeof(ISymUnmanagedWriter));
Marshal.WriteIntPtr(ppISymUnmanagedWriter, pISymUnmanagedWriter);
SetUnderlyingWriter(ppISymUnmanagedWriter);
IMetaDataDispenser disp = new IMetaDataDispenser();
object emitter;
Guid CLSID_CorMetaDataRuntime = new Guid("005023ca-72b1-11d3-9fc4-00c04f79a0a3");
Guid IID_IMetaDataEmit = typeof(IMetaDataEmit).GUID;
disp.DefineScope(ref CLSID_CorMetaDataRuntime, 0, ref IID_IMetaDataEmit, out emitter);
IntPtr emitterPtr = Marshal.GetComInterfaceForObject(emitter, typeof(IMetaDataEmit));
try
{
Initialize(emitterPtr, fileName, true);
}
finally
{
Marshal.Release(emitterPtr);
}
Marshal.ReleaseComObject(disp);
Marshal.ReleaseComObject(emitter);
}
~MySymWriter()
{
Marshal.Release(pISymUnmanagedWriter);
Marshal.FreeHGlobal(ppISymUnmanagedWriter);
}
internal byte[] GetDebugInfo(ref IMAGE_DEBUG_DIRECTORY idd)
{
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;
}
internal void RemapToken(int oldToken, int newToken)
{
symUnmanagedWriter.RemapToken(oldToken, newToken);
}
}
internal static ISymbolWriter CreateSymbolWriter(string fileName)
{
return new MySymWriter(fileName);
}
internal static byte[] GetDebugInfo(ISymbolWriter writer, ref IMAGE_DEBUG_DIRECTORY idd)
{
return ((MySymWriter)writer).GetDebugInfo(ref idd);
}
internal static void RemapToken(ISymbolWriter writer, int oldToken, int newToken)
{
((MySymWriter)writer).RemapToken(oldToken, newToken);
}
}
}

223
refemit/Impl/TypeBase.cs Normal file
Просмотреть файл

@ -0,0 +1,223 @@
/*
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.Reflection;
namespace IKVM.Reflection.Emit.Impl
{
public abstract class TypeBase : Type
{
public sealed override Assembly Assembly
{
get { throw new NotSupportedException(); }
}
public abstract override string AssemblyQualifiedName
{
get;
}
public abstract override Type BaseType
{
get;
}
public abstract override string FullName
{
get;
}
public sealed override Guid GUID
{
get { throw new NotSupportedException(); }
}
protected abstract override TypeAttributes GetAttributeFlagsImpl();
protected sealed override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
throw new NotSupportedException();
}
public sealed override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public override Type GetElementType()
{
return null;
}
public sealed override EventInfo GetEvent(string name, BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public sealed override EventInfo[] GetEvents(BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public sealed override FieldInfo GetField(string name, BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public sealed override FieldInfo[] GetFields(BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public sealed override Type GetInterface(string name, bool ignoreCase)
{
throw new NotSupportedException();
}
public sealed override Type[] GetInterfaces()
{
throw new NotSupportedException();
}
public sealed override MemberInfo[] GetMembers(BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
protected abstract override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers);
public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public sealed override Type GetNestedType(string name, BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public sealed override Type[] GetNestedTypes(BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
public sealed override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
throw new NotSupportedException();
}
protected sealed override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
throw new NotSupportedException();
}
protected abstract override bool HasElementTypeImpl();
public sealed override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
{
throw new NotSupportedException();
}
protected abstract override bool IsArrayImpl();
protected abstract override bool IsByRefImpl();
protected sealed override bool IsCOMObjectImpl()
{
throw new NotSupportedException();
}
protected sealed override bool IsPointerImpl()
{
return false;
}
protected sealed override bool IsPrimitiveImpl()
{
return false;
}
public sealed override Module Module
{
get { throw new NotSupportedException(); }
}
public override Type UnderlyingSystemType
{
get { return this; }
}
public override Type DeclaringType
{
get { return null; }
}
public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
throw new NotSupportedException();
}
public sealed override object[] GetCustomAttributes(bool inherit)
{
throw new NotSupportedException();
}
public sealed override bool IsDefined(Type attributeType, bool inherit)
{
throw new NotSupportedException();
}
public override string Name
{
get
{
string fullname = FullName;
return fullname.Substring(fullname.LastIndexOf('.') + 1);
}
}
public sealed override string Namespace
{
get
{
if (IsNested)
{
return null;
}
string fullname = FullName;
int index = fullname.LastIndexOf('.');
return index < 0 ? null : fullname.Substring(0, index);
}
}
public override Type MakeArrayType()
{
return ArrayType.Make(this);
}
internal abstract ModuleBuilder ModuleBuilder { get; }
internal abstract TypeToken GetToken();
}
}

524
refemit/MethodBuilder.cs Normal file
Просмотреть файл

@ -0,0 +1,524 @@
/*
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.Reflection;
using System.IO;
using System.Diagnostics;
using IKVM.Reflection.Emit.Writer;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Diagnostics.SymbolStore;
namespace IKVM.Reflection.Emit
{
public sealed class MethodBuilder : MethodInfo
{
private readonly TypeBuilder typeBuilder;
private readonly string name;
private readonly int nameIndex;
private readonly int signature;
private readonly int pseudoToken;
private readonly Type returnType;
private readonly Type[] parameterTypes;
private readonly Type[][] requiredCustomModifiers; // last element is for the return type
private readonly Type[][] optionalCustomModifiers;
private MethodAttributes attributes;
private MethodImplAttributes implFlags;
private ILGenerator ilgen;
private int rva;
private List<ParameterBuilder> parameters;
internal MethodBuilder(TypeBuilder typeBuilder, string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
{
this.typeBuilder = typeBuilder;
this.name = name;
this.pseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
this.nameIndex = typeBuilder.ModuleBuilder.Strings.Add(name);
this.attributes = attributes;
this.returnType = returnType ?? typeof(void);
this.parameterTypes = Copy(parameterTypes);
if ((attributes & MethodAttributes.Static) == 0)
{
callingConvention |= CallingConventions.HasThis;
}
ByteBuffer signature = new ByteBuffer(16);
SignatureHelper.WriteMethodSig(this.ModuleBuilder, signature, callingConvention, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
this.signature = this.ModuleBuilder.Blobs.Add(signature);
requiredCustomModifiers = PackCustomModifiers(returnTypeRequiredCustomModifiers, parameterTypeRequiredCustomModifiers, this.parameterTypes.Length);
optionalCustomModifiers = PackCustomModifiers(returnTypeOptionalCustomModifiers, parameterTypeOptionalCustomModifiers, this.parameterTypes.Length);
}
internal static Type[] Copy(Type[] array)
{
if (array == null || array.Length == 0)
{
return Type.EmptyTypes;
}
Type[] newArray = new Type[array.Length];
Array.Copy(array, newArray, array.Length);
return newArray;
}
private static Type[][] PackCustomModifiers(Type[] returnTypeCustomModifiers, Type[][] parameterTypeCustomModifiers, int parameterCount)
{
if (returnTypeCustomModifiers == null && parameterTypeCustomModifiers == null)
{
return null;
}
Type[][] newArray = new Type[parameterCount + 1][];
newArray[parameterCount] = Copy(returnTypeCustomModifiers);
if (parameterTypeCustomModifiers != null)
{
for (int i = 0; i < parameterCount; i++)
{
newArray[i] = Copy(parameterTypeCustomModifiers[i]);
}
}
else
{
for (int i = 0; i < parameterCount; i++)
{
newArray[i] = Type.EmptyTypes;
}
}
return newArray;
}
public ILGenerator GetILGenerator()
{
if (ilgen == null)
{
ilgen = new ILGenerator(typeBuilder.ModuleBuilder);
}
return ilgen;
}
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
}
private void SetDllImportPseudoCustomAttribute(CustomAttributeBuilder customBuilder)
{
if (customBuilder.IsBlob)
{
throw new NotImplementedException();
}
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;
bool? bestFitMapping = (bool?)customBuilder.GetFieldValue("BestFitMapping");
if (bestFitMapping.HasValue)
{
flags |= bestFitMapping.Value ? BestFitOn : BestFitOff;
}
bool? throwOnUnmappableChar = (bool?)customBuilder.GetFieldValue("ThrowOnUnmappableChar");
if (throwOnUnmappableChar.HasValue)
{
flags |= throwOnUnmappableChar.Value ? CharMapErrorOn : CharMapErrorOff;
}
CallingConvention? callingConvention = (CallingConvention?)customBuilder.GetFieldValue("CallingConvention");
if (callingConvention.HasValue)
{
flags &= ~CallConvMask;
switch (callingConvention.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;
}
}
CharSet? charSet = (CharSet?)customBuilder.GetFieldValue("CharSet");
if (charSet.HasValue)
{
flags &= ~CharSetMask;
switch (charSet.Value)
{
case CharSet.Ansi:
case CharSet.None:
flags |= CharSetAnsi;
break;
case CharSet.Auto:
flags |= CharSetAuto;
break;
case CharSet.Unicode:
flags |= CharSetUnicode;
break;
}
}
string entryPoint = (string)customBuilder.GetFieldValue("EntryPoint");
if (entryPoint != null)
{
name = this.ModuleBuilder.Strings.Add(entryPoint);
}
bool? exactSpelling = (bool?)customBuilder.GetFieldValue("ExactSpelling");
if (exactSpelling.HasValue && exactSpelling.Value)
{
flags |= NoMangle;
}
bool? preserveSig = (bool?)customBuilder.GetFieldValue("PreserveSig");
if (!preserveSig.HasValue || preserveSig.Value)
{
implFlags |= MethodImplAttributes.PreserveSig;
}
bool? setLastError = (bool?)customBuilder.GetFieldValue("SetLastError");
if (setLastError.HasValue && setLastError.Value)
{
flags |= SupportsLastError;
}
TableHeap.ImplMapTable.Record rec = new TableHeap.ImplMapTable.Record();
rec.MappingFlags = flags;
rec.MemberForwarded = pseudoToken;
rec.ImportName = name;
rec.ImportScope = this.ModuleBuilder.Tables.ModuleRef.Add(this.ModuleBuilder.Strings.Add((string)customBuilder.GetConstructorArgument(0)));
this.ModuleBuilder.Tables.ImplMap.AddRecord(rec);
}
private void SetMethodImplAttribute(CustomAttributeBuilder customBuilder)
{
MethodImplOptions opt;
switch (customBuilder.Constructor.GetParameters().Length)
{
case 0:
opt = 0;
break;
case 1:
{
object val = customBuilder.GetConstructorArgument(0);
if (val is short)
{
opt = (MethodImplOptions)(short)val;
}
else
{
opt = (MethodImplOptions)val;
}
break;
}
default:
throw new NotSupportedException();
}
MethodCodeType? type = (MethodCodeType?)customBuilder.GetFieldValue("MethodCodeType");
implFlags = (MethodImplAttributes)opt;
if (type.HasValue)
{
implFlags |= (MethodImplAttributes)type;
}
}
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
if (customBuilder.Constructor.DeclaringType == typeof(DllImportAttribute))
{
SetDllImportPseudoCustomAttribute(customBuilder);
}
else if (customBuilder.Constructor.DeclaringType == typeof(MethodImplAttribute))
{
SetMethodImplAttribute(customBuilder);
}
else if (customBuilder.Constructor.DeclaringType == typeof(PreserveSigAttribute))
{
implFlags |= MethodImplAttributes.PreserveSig;
}
else
{
this.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
}
}
public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
{
TableHeap.DeclSecurityTable.Record rec = new TableHeap.DeclSecurityTable.Record();
rec.Action = (short)securityAction;
rec.Parent = pseudoToken;
// like Ref.Emit, we're using the .NET 1.x xml format
rec.PermissionSet = this.ModuleBuilder.Blobs.Add(ByteBuffer.Wrap(System.Text.Encoding.Unicode.GetBytes(permissionSet.ToXml().ToString())));
this.ModuleBuilder.Tables.DeclSecurity.AddRecord(rec);
this.attributes |= MethodAttributes.HasSecurity;
}
public void SetImplementationFlags(MethodImplAttributes attributes)
{
implFlags = attributes;
}
public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
{
if (parameters == null)
{
parameters = new List<ParameterBuilder>();
}
this.ModuleBuilder.Tables.Param.AddRow();
ParameterBuilder pb = new ParameterBuilder(this.ModuleBuilder, position, attributes, strParamName);
parameters.Add(pb);
return pb;
}
public override MethodInfo GetBaseDefinition()
{
throw new NotSupportedException();
}
public override Type ReturnType
{
get { return returnType; }
}
public override ParameterInfo ReturnParameter
{
get { return new ParameterInfoImpl(this, -1); }
}
public override ICustomAttributeProvider ReturnTypeCustomAttributes
{
get { throw new NotImplementedException(); }
}
public override MethodAttributes Attributes
{
get { return attributes; }
}
public override MethodImplAttributes GetMethodImplementationFlags()
{
return implFlags;
}
private class ParameterInfoImpl : ParameterInfo
{
private readonly MethodBuilder method;
private readonly int parameter;
internal ParameterInfoImpl(MethodBuilder method, int parameter)
{
this.method = method;
this.parameter = parameter;
}
public override Type ParameterType
{
get
{
return parameter == -1 ? method.returnType : method.parameterTypes[parameter];
}
}
public override Type[] GetOptionalCustomModifiers()
{
if (method.optionalCustomModifiers == null)
{
return Type.EmptyTypes;
}
int index = parameter == -1 ? method.optionalCustomModifiers.Length - 1 : parameter;
return Copy(method.optionalCustomModifiers[index]);
}
public override Type[] GetRequiredCustomModifiers()
{
if (method.requiredCustomModifiers == null)
{
return Type.EmptyTypes;
}
int index = parameter == -1 ? method.requiredCustomModifiers.Length - 1 : parameter;
return Copy(method.requiredCustomModifiers[index]);
}
}
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;
}
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
public override RuntimeMethodHandle MethodHandle
{
get { throw new NotImplementedException(); }
}
public override Type DeclaringType
{
get { return this.ModuleBuilder.IsModuleType(typeBuilder) ? null : typeBuilder; }
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
throw new NotImplementedException();
}
public override object[] GetCustomAttributes(bool inherit)
{
throw new NotImplementedException();
}
public override bool IsDefined(Type attributeType, bool inherit)
{
throw new NotImplementedException();
}
public override string Name
{
get { return name; }
}
public override Type ReflectedType
{
get { return this.DeclaringType; }
}
public override CallingConventions CallingConvention
{
get { throw new NotImplementedException(); }
}
public override int MetadataToken
{
get { return pseudoToken; }
}
internal void Bake()
{
if (ilgen != null)
{
if (this.ModuleBuilder.symbolWriter != null)
{
this.ModuleBuilder.symbolWriter.OpenMethod(new SymbolToken(-pseudoToken | 0x06000000));
}
rva = ilgen.WriteBody();
if (this.ModuleBuilder.symbolWriter != null)
{
this.ModuleBuilder.symbolWriter.CloseMethod();
}
ilgen = null;
}
else
{
rva = -1;
}
}
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 bool MatchParameters(Type[] types)
{
if (types.Length == parameterTypes.Length)
{
for (int i = 0; i < types.Length; i++)
{
if (!types[i].Equals(parameterTypes[i]))
{
return false;
}
}
return true;
}
return false;
}
}
}

911
refemit/ModuleBuilder.cs Normal file
Просмотреть файл

@ -0,0 +1,911 @@
/*
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.Reflection;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Diagnostics.SymbolStore;
using IKVM.Reflection.Emit.Impl;
using IKVM.Reflection.Emit.Writer;
using System.Security.Cryptography;
namespace IKVM.Reflection.Emit
{
public sealed class ModuleBuilder : ITypeOwner
{
private readonly AssemblyBuilder asm;
internal readonly string moduleName;
internal readonly string fileName;
internal readonly ISymbolWriter symbolWriter;
private readonly TypeBuilder moduleType;
private readonly List<TypeBuilder> types = new List<TypeBuilder>();
private readonly Dictionary<Type, TypeToken> typeTokens = new Dictionary<Type, TypeToken>();
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);
private readonly Dictionary<MemberInfo, int> importedMembers = new Dictionary<MemberInfo, int>();
private readonly Dictionary<AssemblyName, int> referencedAssemblies = new Dictionary<AssemblyName, int>(new AssemblyNameEqualityComparer());
private readonly Dictionary<Type, Type> canonicalizedTypes = new Dictionary<Type, Type>();
private readonly Dictionary<MethodInfo, MethodInfo> canonicalizedGenericMethods = new Dictionary<MethodInfo, MethodInfo>(new GenericMethodComparer());
private int nextPseudoToken = -1;
private readonly List<int> resolvedTokens = new List<int>();
internal readonly TableHeap Tables;
internal readonly StringHeap Strings = new StringHeap();
internal readonly UserStringHeap UserStrings = new UserStringHeap();
internal readonly GuidHeap Guids = new GuidHeap();
internal readonly BlobHeap Blobs = new BlobHeap();
internal bool bigStrings;
internal bool bigGuids;
internal bool bigBlobs;
internal bool bigField;
internal bool bigMethodDef;
internal bool bigParam;
internal bool bigTypeDef;
internal bool bigProperty;
internal bool bigGenericParam;
internal bool bigModuleRef;
internal bool bigResolutionScope;
internal bool bigMemberRefParent;
internal bool bigMethodDefOrRef;
internal bool bigTypeDefOrRef;
internal bool bigHasCustomAttribute;
internal bool bigCustomAttributeType;
internal bool bigHasConstant;
internal bool bigHasSemantics;
internal bool bigImplementation;
internal bool bigTypeOrMethodDef;
internal bool bigHasDeclSecurity;
internal bool bigMemberForwarded;
internal bool bigHasFieldMarshal;
// FXBUG AssemblyName doesn't have a working Equals (sigh)
private sealed class AssemblyNameEqualityComparer : IEqualityComparer<AssemblyName>
{
public bool Equals(AssemblyName x, AssemblyName y)
{
return x.FullName == y.FullName;
}
public int GetHashCode(AssemblyName obj)
{
return obj.FullName.GetHashCode();
}
}
// this class makes multiple instances of a generic method compare as equal,
// however, it does not ensure that the underlying method definition is canonicalized
private sealed class GenericMethodComparer : IEqualityComparer<MethodInfo>
{
public bool Equals(MethodInfo x, MethodInfo y)
{
if (x.GetGenericMethodDefinition() == y.GetGenericMethodDefinition())
{
Type[] xArgs = x.GetGenericArguments();
Type[] yArgs = y.GetGenericArguments();
for (int i = 0; i < xArgs.Length; i++)
{
if (xArgs[i] != yArgs[i])
{
return false;
}
}
return true;
}
return false;
}
public int GetHashCode(MethodInfo obj)
{
int hash = obj.GetGenericMethodDefinition().GetHashCode();
foreach (Type arg in obj.GetGenericArguments())
{
hash *= 37;
hash ^= arg.GetHashCode();
}
return hash;
}
}
internal ModuleBuilder(AssemblyBuilder asm, string moduleName, string fileName, bool emitSymbolInfo)
{
this.Tables = new TableHeap(this);
this.asm = asm;
this.moduleName = moduleName;
this.fileName = fileName;
if (emitSymbolInfo)
{
symbolWriter = PdbSupport.CreateSymbolWriter(Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".pdb"));
}
// <Module> must be the first record in the TypeDef table
moduleType = new TypeBuilder(this, "<Module>", null, 0);
types.Add(moduleType);
}
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 GetTypeCount()
{
return types.Count;
}
internal int AllocPseudoToken()
{
return nextPseudoToken--;
}
public TypeBuilder DefineType(string name)
{
return DefineType(name, TypeAttributes.Class);
}
public TypeBuilder DefineType(string name, TypeAttributes attribs)
{
return DefineType(name, attribs, null);
}
public TypeBuilder DefineType(string name, TypeAttributes attribs, Type baseType)
{
return DefineType(name, attribs, baseType, PackingSize.Unspecified, 0);
}
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
{
if (parent == null && (attr & TypeAttributes.Interface) == 0)
{
parent = typeof(object);
}
TypeBuilder typeBuilder = new TypeBuilder(this, name, parent, attr);
PostDefineType(typeBuilder, packingSize, typesize);
return typeBuilder;
}
internal TypeBuilder DefineNestedTypeHelper(TypeBuilder enclosingType, string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
{
if (parent == null && (attr & TypeAttributes.Interface) == 0)
{
parent = typeof(object);
}
TypeBuilder typeBuilder = new TypeBuilder(enclosingType, name, parent, attr);
PostDefineType(typeBuilder, packingSize, typesize);
if (enclosingType != null)
{
TableHeap.NestedClassTable.Record rec = new TableHeap.NestedClassTable.Record();
rec.NestedClass = typeBuilder.GetToken().Token;
rec.EnclosingClass = enclosingType.GetToken().Token;
this.Tables.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)
{
TableHeap.ClassLayoutTable.Record rec = new TableHeap.ClassLayoutTable.Record();
rec.PackingSize = (short)packingSize;
rec.ClassSize = typesize;
rec.Parent = typeBuilder.GetToken().Token;
this.Tables.ClassLayout.AddRecord(rec);
}
}
public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
{
Type fieldType = GetType("$ArrayType$" + data.Length);
if (fieldType == null)
{
fieldType = DefineType("$ArrayType$" + data.Length, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.ExplicitLayout, typeof(ValueType), PackingSize.Size1, data.Length);
}
FieldBuilder fb = moduleType.DefineField(name, fieldType, attributes | FieldAttributes.Static | FieldAttributes.HasFieldRVA);
TableHeap.FieldRVATable.Record rec = new TableHeap.FieldRVATable.Record();
rec.RVA = initializedData.Position;
rec.Field = fb.MetadataToken;
this.Tables.FieldRVA.AddRecord(rec);
initializedData.Write(data);
return fb;
}
public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
{
return moduleType.DefineMethod(name, attributes, returnType, parameterTypes);
}
public void CreateGlobalFunctions()
{
moduleType.CreateType();
}
public TypeToken GetTypeToken(Type type)
{
TypeToken token;
if (!typeTokens.TryGetValue(type, out token))
{
token = ImportType(type);
typeTokens.Add(type, token);
}
return token;
}
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
SetCustomAttribute(0x00000001, customBuilder);
}
internal void SetCustomAttribute(int token, CustomAttributeBuilder customBuilder)
{
if (customBuilder.IsPseudoCustomAttribute)
{
throw new NotImplementedException("Pseudo custom attribute " + customBuilder.Constructor.DeclaringType.FullName + " is not implemented");
}
TableHeap.CustomAttributeTable.Record rec = new TableHeap.CustomAttributeTable.Record();
rec.Parent = token;
rec.Type = this.GetConstructorToken(customBuilder.Constructor).Token;
rec.Value = customBuilder.WriteBlob(this);
this.Tables.CustomAttribute.AddRecord(rec);
}
public void DefineManifestResource(string name, Stream stream, ResourceAttributes attribute)
{
TableHeap.ManifestResourceTable.Record rec = new TableHeap.ManifestResourceTable.Record();
rec.Offset = manifestResources.Position;
rec.Flags = (int)attribute;
rec.Name = this.Strings.Add(name);
rec.Implementation = 0;
this.Tables.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 AssemblyBuilder Assembly
{
get { return asm; }
}
public Type GetType(string className)
{
return GetType(className, false, false);
}
public Type GetType(string className, bool throwOnError, bool ignoreCase)
{
if (ignoreCase)
{
throw new NotImplementedException();
}
TypeBuilder type;
if (!fullNameToType.TryGetValue(className, out type) && throwOnError)
{
throw new TypeLoadException();
}
return type;
}
public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)
{
return symbolWriter.DefineDocument(url, language, languageVendor, documentType);
}
public FieldToken GetFieldToken(FieldInfo field)
{
FieldBuilder fb = field as FieldBuilder;
if (fb != null)
{
if (fb.ModuleBuilder == this)
{
return new FieldToken(fb.MetadataToken);
}
else
{
int token;
if (!importedMembers.TryGetValue(field, out token))
{
token = fb.ImportTo(this);
importedMembers.Add(field, token);
}
return new FieldToken(token);
}
}
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));
}
}
public ConstructorToken GetConstructorToken(ConstructorInfo constructor)
{
ConstructorBuilder cb = constructor as ConstructorBuilder;
if (cb != null)
{
if (cb.ModuleBuilder == this)
{
return new ConstructorToken(cb.MetadataToken);
}
else
{
throw new NotImplementedException();
}
}
else
{
return new ConstructorToken(ImportMember(constructor));
}
}
private int ImportMember(MemberInfo member)
{
int token;
if (!importedMembers.TryGetValue(member, out token))
{
if (member.DeclaringType == null)
{
throw new NotImplementedException();
}
if (member.ReflectedType != member.DeclaringType)
{
// look up the canonicalized member
token = ImportMember(member.Module.ResolveMember(member.MetadataToken));
importedMembers.Add(member, token);
return token;
}
MethodInfo method = member as MethodInfo;
if (method != null)
{
if (method.IsGenericMethod && !method.IsGenericMethodDefinition)
{
// FXBUG generic MethodInfos don't have a working Equals/GetHashCode,
// so we have to canonicalize them manually
// (we don't have to recursively call ImportMember here (like above), because the first method we encounter will always become the canonical one)
if (importedMembers.TryGetValue(CanonicalizeGenericMethod(method), out token))
{
importedMembers.Add(member, token);
return token;
}
const byte GENERICINST = 0x0A;
ByteBuffer spec = new ByteBuffer(10);
spec.Write(GENERICINST);
Type[] args = method.GetGenericArguments();
spec.WriteCompressedInt(args.Length);
foreach (Type arg in args)
{
SignatureHelper.WriteType(this, spec, arg);
}
TableHeap.MethodSpecTable.Record rec = new TableHeap.MethodSpecTable.Record();
rec.Method = GetMethodToken(method.GetGenericMethodDefinition()).Token;
rec.Instantiation = this.Blobs.Add(spec);
token = 0x2B000000 | this.Tables.MethodSpec.AddRecord(rec);
}
else
{
token = ImportMethodOrConstructorRef(method);
}
}
else
{
ConstructorInfo constructor = member as ConstructorInfo;
if (constructor != null)
{
token = ImportMethodOrConstructorRef(constructor);
}
else
{
FieldInfo field = member as FieldInfo;
if (field != null)
{
token = ImportField(field.DeclaringType, field.Name, field.FieldType, field.GetOptionalCustomModifiers(), field.GetRequiredCustomModifiers());
}
else
{
throw new NotImplementedException();
}
}
}
importedMembers.Add(member, token);
}
return token;
}
private int ImportMethodOrConstructorRef(MethodBase method)
{
if (method.DeclaringType == null)
{
throw new NotImplementedException();
}
TableHeap.MemberRefTable.Record rec = new TableHeap.MemberRefTable.Record();
rec.Class = GetTypeToken(method.DeclaringType).Token;
rec.Name = this.Strings.Add(method.Name);
ByteBuffer bb = new ByteBuffer(16);
SignatureHelper.WriteMethodSig(this, bb, method);
rec.Signature = this.Blobs.Add(bb);
return 0x0A000000 | this.Tables.MemberRef.AddRecord(rec);
}
internal int ImportField(Type declaringType, string name, Type fieldType, Type[] optionalCustomModifiers, Type[] requiredCustomModifiers)
{
if (declaringType == null)
{
throw new NotImplementedException();
}
TableHeap.MemberRefTable.Record rec = new TableHeap.MemberRefTable.Record();
rec.Class = GetTypeToken(declaringType).Token;
rec.Name = this.Strings.Add(name);
ByteBuffer bb = new ByteBuffer(16);
bb.Write(SignatureHelper.FIELD);
SignatureHelper.WriteCustomModifiers(this, bb, SignatureHelper.ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers);
SignatureHelper.WriteCustomModifiers(this, bb, SignatureHelper.ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers);
SignatureHelper.WriteType(this, bb, fieldType);
rec.Signature = this.Blobs.Add(bb);
return 0x0A000000 | this.Tables.MemberRef.AddRecord(rec);
}
private TypeToken ImportType(Type type)
{
if (type.IsPointer || type.IsByRef)
{
throw new NotImplementedException();
}
TypeBase tb = type as TypeBase;
if (tb != null)
{
if (tb.ModuleBuilder == this)
{
return tb.GetToken();
}
else if (tb.ModuleBuilder.Assembly != this.Assembly)
{
return ImportTypeRef(tb.ModuleBuilder.Assembly.GetName(), type);
}
else
{
throw new NotImplementedException();
}
}
else if (type.IsArray || (type.IsGenericType && !type.IsGenericTypeDefinition))
{
ByteBuffer spec = new ByteBuffer(5);
SignatureHelper.WriteType(this, spec, type);
return new TypeToken(0x1B000000 | this.Tables.TypeSpec.AddRecord(this.Blobs.Add(spec)));
}
else
{
return ImportTypeRef(type.Assembly.GetName(), type);
}
}
private TypeToken ImportTypeRef(AssemblyName asm, Type type)
{
TableHeap.TypeRefTable.Record rec = new TableHeap.TypeRefTable.Record();
if (type.IsNested)
{
rec.ResolutionScope = GetTypeToken(type.DeclaringType).Token;
rec.TypeName = this.Strings.Add(type.Name);
rec.TypeNameSpace = 0;
}
else
{
rec.ResolutionScope = ImportAssemblyRef(asm);
rec.TypeName = this.Strings.Add(type.Name);
string ns = type.Namespace;
rec.TypeNameSpace = ns == null ? 0 : this.Strings.Add(ns);
}
return new TypeToken(0x01000000 | this.Tables.TypeRef.AddRecord(rec));
}
private int ImportAssemblyRef(AssemblyName asm)
{
int token;
if (!referencedAssemblies.TryGetValue(asm, out token))
{
TableHeap.AssemblyRefTable.Record rec = new TableHeap.AssemblyRefTable.Record();
Version ver = asm.Version ?? new Version(0, 0, 0, 0);
rec.MajorVersion = (short)ver.Major;
rec.MinorVersion = (short)ver.Minor;
rec.BuildNumber = (short)ver.Build;
rec.RevisionNumber = (short)ver.Revision;
rec.Flags = 0;
byte[] pubkey = asm.GetPublicKeyToken();
if (pubkey == null && asm.KeyPair != null)
{
pubkey = GetPublicKeyToken(asm.KeyPair);
}
if (pubkey != null)
{
rec.PublicKeyOrToken = this.Blobs.Add(ByteBuffer.Wrap(pubkey));
}
rec.Name = this.Strings.Add(asm.Name);
rec.Culture = 0;
rec.HashValue = 0;
token = 0x23000000 | this.Tables.AssemblyRef.AddRecord(rec);
referencedAssemblies.Add(asm, token);
}
return token;
}
private byte[] GetPublicKeyToken(StrongNameKeyPair strongNameKeyPair)
{
SHA1Managed sha1 = new SHA1Managed();
byte[] hash = sha1.ComputeHash(strongNameKeyPair.PublicKey);
byte[] token = new byte[8];
Buffer.BlockCopy(hash, hash.Length - 8, token, 0, 8);
Array.Reverse(token);
return token;
}
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);
PdbSupport.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));
}
}
internal int MetadataLength
{
get
{
return (Blobs.IsEmpty ? 92 : 108 + 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("v2.0.50727");
mw.Write(version.Length); // Length
mw.Write(version);
mw.Write((ushort)0); // Flags
int offset;
// #Blob is the only optional heap
if (Blobs.IsEmpty)
{
mw.Write((ushort)4); // Streams
offset = 92;
}
else
{
mw.Write((ushort)5); // Streams
offset = 108;
}
// 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 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 void Freeze()
{
Strings.Freeze(this);
UserStrings.Freeze(this);
Guids.Freeze(this);
Blobs.Freeze(this);
this.bigStrings = Strings.IsBig;
this.bigGuids = Guids.IsBig;
this.bigBlobs = Blobs.IsBig;
this.bigField = Tables.Field.IsBig;
this.bigMethodDef = Tables.MethodDef.IsBig;
this.bigParam = Tables.Param.IsBig;
this.bigTypeDef = Tables.TypeDef.IsBig;
this.bigProperty = Tables.Property.IsBig;
this.bigGenericParam = Tables.GenericParam.IsBig;
this.bigModuleRef = Tables.ModuleRef.IsBig;
this.bigResolutionScope = IsBig(2, Tables.Module, Tables.ModuleRef, Tables.AssemblyRef, Tables.TypeRef);
this.bigMemberRefParent = IsBig(3, Tables.TypeDef, Tables.TypeRef, Tables.ModuleRef, Tables.MethodDef, Tables.TypeSpec);
this.bigMethodDefOrRef = IsBig(1, Tables.MethodDef, Tables.MemberRef);
this.bigTypeDefOrRef = IsBig(2, Tables.TypeDef, Tables.TypeRef);
this.bigHasCustomAttribute = IsBig(5, Tables.MethodDef, Tables.Field, Tables.TypeDef, Tables.Param, Tables.Module, Tables.Property, Tables.Assembly);
this.bigCustomAttributeType = IsBig(3, Tables.MethodDef, Tables.MemberRef);
this.bigHasConstant = IsBig(2, Tables.Field, Tables.Param, Tables.Property);
this.bigHasSemantics = IsBig(1, /*Tables.Event,*/ Tables.Property);
this.bigImplementation = IsBig(2, Tables.File, Tables.AssemblyRef, Tables.ExportedType);
this.bigTypeOrMethodDef = IsBig(1, Tables.TypeDef, Tables.MethodDef);
this.bigHasDeclSecurity = IsBig(2, Tables.TypeDef, Tables.MethodDef, Tables.Assembly);
this.bigMemberForwarded = IsBig(1, Tables.Field, Tables.MethodDef);
this.bigHasFieldMarshal = IsBig(1, Tables.Field, Tables.Param);
Tables.Freeze(this);
}
private bool IsBig(int bitsUsed, params TableHeap.Table[] tables)
{
int limit = 1 << (16 - bitsUsed);
foreach (TableHeap.Table table in tables)
{
if (table.RowCount >= limit)
{
return true;
}
}
return false;
}
internal Type CanonicalizeType(Type type)
{
Type canon;
if (!canonicalizedTypes.TryGetValue(type, out canon))
{
canon = type;
canonicalizedTypes.Add(canon, canon);
}
return canon;
}
private MethodInfo CanonicalizeGenericMethod(MethodInfo method)
{
MethodInfo canon;
if (!canonicalizedGenericMethods.TryGetValue(method, out canon))
{
canonicalizedGenericMethods.Add(method, method);
canon = method;
}
return canon;
}
internal void ExportTypes(int fileToken, ModuleBuilder manifestModule)
{
Dictionary<Type, int> declaringTypes = new Dictionary<Type, int>();
foreach (TypeBuilder type in types)
{
if (type != moduleType && IsVisible(type))
{
TableHeap.ExportedTypeTable.Record rec = new TableHeap.ExportedTypeTable.Record();
rec.Flags = (int)type.Attributes;
rec.TypeDefId = type.GetToken().Token & 0xFFFFFF;
rec.TypeName = manifestModule.Strings.Add(type.Name);
rec.TypeNamespace = manifestModule.Strings.Add(type.Namespace);
if (type.IsNested)
{
rec.Implementation = declaringTypes[type.DeclaringType];
}
else
{
rec.Implementation = fileToken;
}
int exportTypeToken = 0x27000000 | manifestModule.Tables.ExportedType.AddRecord(rec);
declaringTypes.Add(type, exportTypeToken);
}
}
}
internal static bool IsVisible(Type type)
{
return type.IsPublic || ((type.IsNestedFamily || type.IsNestedFamORAssem || type.IsNestedPublic) && IsVisible(type.DeclaringType));
}
internal void AddConstant(int parentToken, object defaultValue)
{
TableHeap.ConstantTable.Record rec = new TableHeap.ConstantTable.Record();
rec.Parent = parentToken;
ByteBuffer val = new ByteBuffer(16);
if (defaultValue == null)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_CLASS;
}
else if (defaultValue is bool)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_BOOLEAN;
val.Write((bool)defaultValue ? (byte)1 : (byte)0);
}
else if (defaultValue is char)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_CHAR;
val.Write((char)defaultValue);
}
else if (defaultValue is byte)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_U1;
val.Write((byte)defaultValue);
}
else if (defaultValue is short)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_I2;
val.Write((short)defaultValue);
}
else if (defaultValue is int)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_I4;
val.Write((int)defaultValue);
}
else if (defaultValue is long)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_I8;
val.Write((long)defaultValue);
}
else if (defaultValue is float)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_R4;
val.Write((float)defaultValue);
}
else if (defaultValue is double)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_R8;
val.Write((double)defaultValue);
}
else if (defaultValue is string)
{
rec.Type = SignatureHelper.ELEMENT_TYPE_STRING;
foreach (char c in (string)defaultValue)
{
val.Write(c);
}
}
else
{
throw new NotImplementedException(defaultValue.GetType().FullName);
}
rec.Value = this.Blobs.Add(val);
this.Tables.Constant.AddRecord(rec);
}
internal bool IsModuleType(TypeBuilder type)
{
return type == moduleType;
}
ModuleBuilder ITypeOwner.ModuleBuilder
{
get { return this; }
}
}
}

308
refemit/OpCodes.cs Normal file
Просмотреть файл

@ -0,0 +1,308 @@
/*
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;
namespace IKVM.Reflection.Emit
{
public struct OpCode
{
private const int OperandTypeCount = 19;
private const int FlowControlCount = 9;
private const int StackDiffCount = 5;
private readonly short value;
private readonly short info;
internal OpCode(short value, OperandType operandType, FlowControl flowControl, short stackDiff)
{
Debug.Assert(operandType >= 0 && (int)operandType < OperandTypeCount);
Debug.Assert(flowControl >= 0 && (int)flowControl < FlowControlCount);
Debug.Assert(stackDiff >= -3 && stackDiff <= 1);
this.value = value;
this.info = (short)(operandType
+ OperandTypeCount * (short)flowControl
+ OperandTypeCount * FlowControlCount * (stackDiff + 3));
Debug.Assert(this.OperandType == operandType);
Debug.Assert(this.FlowControl == flowControl);
Debug.Assert(this.StackDiff == stackDiff);
}
public short Value
{
get { return value; }
}
public int Size
{
get { return value < 0 ? 2 : 1; }
}
public OperandType OperandType
{
get { return (OperandType)(info % OperandTypeCount); }
}
public FlowControl FlowControl
{
get { return (FlowControl)((info / OperandTypeCount) % FlowControlCount); }
}
internal short StackDiff
{
get { return (short)(((info / (OperandTypeCount * FlowControlCount)) % StackDiffCount) - 3); }
}
}
public class OpCodes
{
public static readonly OpCode Nop = new OpCode(0, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Break = new OpCode(1, OperandType.InlineNone, FlowControl.Break, 0);
public static readonly OpCode Ldarg_0 = new OpCode(2, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldarg_1 = new OpCode(3, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldarg_2 = new OpCode(4, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldarg_3 = new OpCode(5, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldloc_0 = new OpCode(6, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldloc_1 = new OpCode(7, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldloc_2 = new OpCode(8, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldloc_3 = new OpCode(9, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Stloc_0 = new OpCode(10, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Stloc_1 = new OpCode(11, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Stloc_2 = new OpCode(12, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Stloc_3 = new OpCode(13, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldarg_S = new OpCode(14, OperandType.ShortInlineVar, FlowControl.Next, 1);
public static readonly OpCode Ldarga_S = new OpCode(15, OperandType.ShortInlineVar, FlowControl.Next, 1);
public static readonly OpCode Starg_S = new OpCode(16, OperandType.ShortInlineVar, FlowControl.Next, -1);
public static readonly OpCode Ldloc_S = new OpCode(17, OperandType.ShortInlineVar, FlowControl.Next, 1);
public static readonly OpCode Ldloca_S = new OpCode(18, OperandType.ShortInlineVar, FlowControl.Next, 1);
public static readonly OpCode Stloc_S = new OpCode(19, OperandType.ShortInlineVar, FlowControl.Next, -1);
public static readonly OpCode Ldnull = new OpCode(20, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_M1 = new OpCode(21, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_0 = new OpCode(22, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_1 = new OpCode(23, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_2 = new OpCode(24, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_3 = new OpCode(25, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_4 = new OpCode(26, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_5 = new OpCode(27, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_6 = new OpCode(28, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_7 = new OpCode(29, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_8 = new OpCode(30, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4_S = new OpCode(31, OperandType.ShortInlineI, FlowControl.Next, 1);
public static readonly OpCode Ldc_I4 = new OpCode(32, OperandType.InlineI, FlowControl.Next, 1);
public static readonly OpCode Ldc_I8 = new OpCode(33, OperandType.InlineI8, FlowControl.Next, 1);
public static readonly OpCode Ldc_R4 = new OpCode(34, OperandType.ShortInlineR, FlowControl.Next, 1);
public static readonly OpCode Ldc_R8 = new OpCode(35, OperandType.InlineR, FlowControl.Next, 1);
public static readonly OpCode Dup = new OpCode(37, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Pop = new OpCode(38, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Jmp = new OpCode(39, OperandType.InlineMethod, FlowControl.Call, 0);
public static readonly OpCode Call = new OpCode(40, OperandType.InlineMethod, FlowControl.Call, 0);
public static readonly OpCode Calli = new OpCode(41, OperandType.InlineSig, FlowControl.Call, 0);
public static readonly OpCode Ret = new OpCode(42, OperandType.InlineNone, FlowControl.Return, 0);
public static readonly OpCode Br_S = new OpCode(43, OperandType.ShortInlineBrTarget, FlowControl.Branch, 0);
public static readonly OpCode Brfalse_S = new OpCode(44, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -1);
public static readonly OpCode Brtrue_S = new OpCode(45, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -1);
public static readonly OpCode Beq_S = new OpCode(46, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bge_S = new OpCode(47, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bgt_S = new OpCode(48, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Ble_S = new OpCode(49, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Blt_S = new OpCode(50, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bne_Un_S = new OpCode(51, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bge_Un_S = new OpCode(52, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bgt_Un_S = new OpCode(53, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Ble_Un_S = new OpCode(54, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Blt_Un_S = new OpCode(55, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Br = new OpCode(56, OperandType.InlineBrTarget, FlowControl.Branch, 0);
public static readonly OpCode Brfalse = new OpCode(57, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -1);
public static readonly OpCode Brtrue = new OpCode(58, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -1);
public static readonly OpCode Beq = new OpCode(59, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bge = new OpCode(60, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bgt = new OpCode(61, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Ble = new OpCode(62, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Blt = new OpCode(63, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bne_Un = new OpCode(64, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bge_Un = new OpCode(65, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Bgt_Un = new OpCode(66, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Ble_Un = new OpCode(67, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Blt_Un = new OpCode(68, OperandType.InlineBrTarget, FlowControl.Cond_Branch, -2);
public static readonly OpCode Switch = new OpCode(69, OperandType.InlineSwitch, FlowControl.Cond_Branch, -1);
public static readonly OpCode Ldind_I1 = new OpCode(70, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_U1 = new OpCode(71, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_I2 = new OpCode(72, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_U2 = new OpCode(73, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_I4 = new OpCode(74, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_U4 = new OpCode(75, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_I8 = new OpCode(76, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_I = new OpCode(77, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_R4 = new OpCode(78, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_R8 = new OpCode(79, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldind_Ref = new OpCode(80, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Stind_Ref = new OpCode(81, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Stind_I1 = new OpCode(82, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Stind_I2 = new OpCode(83, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Stind_I4 = new OpCode(84, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Stind_I8 = new OpCode(85, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Stind_R4 = new OpCode(86, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Stind_R8 = new OpCode(87, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Add = new OpCode(88, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Sub = new OpCode(89, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Mul = new OpCode(90, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Div = new OpCode(91, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Div_Un = new OpCode(92, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Rem = new OpCode(93, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Rem_Un = new OpCode(94, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode And = new OpCode(95, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Or = new OpCode(96, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Xor = new OpCode(97, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Shl = new OpCode(98, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Shr = new OpCode(99, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Shr_Un = new OpCode(100, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Neg = new OpCode(101, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Not = new OpCode(102, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_I1 = new OpCode(103, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_I2 = new OpCode(104, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_I4 = new OpCode(105, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_I8 = new OpCode(106, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_R4 = new OpCode(107, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_R8 = new OpCode(108, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_U4 = new OpCode(109, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_U8 = new OpCode(110, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Callvirt = new OpCode(111, OperandType.InlineMethod, FlowControl.Call, 0);
public static readonly OpCode Cpobj = new OpCode(112, OperandType.InlineType, FlowControl.Next, -2);
public static readonly OpCode Ldobj = new OpCode(113, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Ldstr = new OpCode(114, OperandType.InlineString, FlowControl.Next, 1);
public static readonly OpCode Newobj = new OpCode(115, OperandType.InlineMethod, FlowControl.Call, 1);
public static readonly OpCode Castclass = new OpCode(116, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Isinst = new OpCode(117, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Conv_R_Un = new OpCode(118, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Unbox = new OpCode(121, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Throw = new OpCode(122, OperandType.InlineNone, FlowControl.Throw, -1);
public static readonly OpCode Ldfld = new OpCode(123, OperandType.InlineField, FlowControl.Next, 0);
public static readonly OpCode Ldflda = new OpCode(124, OperandType.InlineField, FlowControl.Next, 0);
public static readonly OpCode Stfld = new OpCode(125, OperandType.InlineField, FlowControl.Next, -2);
public static readonly OpCode Ldsfld = new OpCode(126, OperandType.InlineField, FlowControl.Next, 1);
public static readonly OpCode Ldsflda = new OpCode(127, OperandType.InlineField, FlowControl.Next, 1);
public static readonly OpCode Stsfld = new OpCode(128, OperandType.InlineField, FlowControl.Next, -1);
public static readonly OpCode Stobj = new OpCode(129, OperandType.InlineType, FlowControl.Next, -2);
public static readonly OpCode Conv_Ovf_I1_Un = new OpCode(130, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I2_Un = new OpCode(131, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I4_Un = new OpCode(132, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I8_Un = new OpCode(133, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U1_Un = new OpCode(134, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U2_Un = new OpCode(135, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U4_Un = new OpCode(136, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U8_Un = new OpCode(137, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I_Un = new OpCode(138, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U_Un = new OpCode(139, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Box = new OpCode(140, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Newarr = new OpCode(141, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Ldlen = new OpCode(142, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Ldelema = new OpCode(143, OperandType.InlineType, FlowControl.Next, -1);
public static readonly OpCode Ldelem_I1 = new OpCode(144, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_U1 = new OpCode(145, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_I2 = new OpCode(146, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_U2 = new OpCode(147, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_I4 = new OpCode(148, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_U4 = new OpCode(149, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_I8 = new OpCode(150, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_I = new OpCode(151, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_R4 = new OpCode(152, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_R8 = new OpCode(153, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldelem_Ref = new OpCode(154, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Stelem_I = new OpCode(155, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Stelem_I1 = new OpCode(156, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Stelem_I2 = new OpCode(157, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Stelem_I4 = new OpCode(158, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Stelem_I8 = new OpCode(159, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Stelem_R4 = new OpCode(160, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Stelem_R8 = new OpCode(161, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Stelem_Ref = new OpCode(162, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Ldelem = new OpCode(163, OperandType.InlineType, FlowControl.Next, -1);
public static readonly OpCode Stelem = new OpCode(164, OperandType.InlineType, FlowControl.Next, -3);
public static readonly OpCode Unbox_Any = new OpCode(165, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I1 = new OpCode(179, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U1 = new OpCode(180, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I2 = new OpCode(181, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U2 = new OpCode(182, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I4 = new OpCode(183, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U4 = new OpCode(184, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I8 = new OpCode(185, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U8 = new OpCode(186, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Refanyval = new OpCode(194, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Ckfinite = new OpCode(195, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Mkrefany = new OpCode(198, OperandType.InlineType, FlowControl.Next, 0);
public static readonly OpCode Ldtoken = new OpCode(208, OperandType.InlineTok, FlowControl.Next, 1);
public static readonly OpCode Conv_U2 = new OpCode(209, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_U1 = new OpCode(210, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_I = new OpCode(211, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_I = new OpCode(212, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Conv_Ovf_U = new OpCode(213, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Add_Ovf = new OpCode(214, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Add_Ovf_Un = new OpCode(215, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Mul_Ovf = new OpCode(216, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Mul_Ovf_Un = new OpCode(217, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Sub_Ovf = new OpCode(218, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Sub_Ovf_Un = new OpCode(219, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Endfinally = new OpCode(220, OperandType.InlineNone, FlowControl.Return, 0);
public static readonly OpCode Leave = new OpCode(221, OperandType.InlineBrTarget, FlowControl.Branch, 0);
public static readonly OpCode Leave_S = new OpCode(222, OperandType.ShortInlineBrTarget, FlowControl.Branch, 0);
public static readonly OpCode Stind_I = new OpCode(223, OperandType.InlineNone, FlowControl.Next, -2);
public static readonly OpCode Conv_U = new OpCode(224, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Prefix7 = new OpCode(248, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Prefix6 = new OpCode(249, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Prefix5 = new OpCode(250, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Prefix4 = new OpCode(251, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Prefix3 = new OpCode(252, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Prefix2 = new OpCode(253, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Prefix1 = new OpCode(254, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Prefixref = new OpCode(255, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Arglist = new OpCode(-512, OperandType.InlineNone, FlowControl.Next, 1);
public static readonly OpCode Ceq = new OpCode(-511, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Cgt = new OpCode(-510, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Cgt_Un = new OpCode(-509, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Clt = new OpCode(-508, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Clt_Un = new OpCode(-507, OperandType.InlineNone, FlowControl.Next, -1);
public static readonly OpCode Ldftn = new OpCode(-506, OperandType.InlineMethod, FlowControl.Next, 1);
public static readonly OpCode Ldvirtftn = new OpCode(-505, OperandType.InlineMethod, FlowControl.Next, 0);
public static readonly OpCode Ldarg = new OpCode(-503, OperandType.InlineVar, FlowControl.Next, 1);
public static readonly OpCode Ldarga = new OpCode(-502, OperandType.InlineVar, FlowControl.Next, 1);
public static readonly OpCode Starg = new OpCode(-501, OperandType.InlineVar, FlowControl.Next, -1);
public static readonly OpCode Ldloc = new OpCode(-500, OperandType.InlineVar, FlowControl.Next, 1);
public static readonly OpCode Ldloca = new OpCode(-499, OperandType.InlineVar, FlowControl.Next, 1);
public static readonly OpCode Stloc = new OpCode(-498, OperandType.InlineVar, FlowControl.Next, -1);
public static readonly OpCode Localloc = new OpCode(-497, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Endfilter = new OpCode(-495, OperandType.InlineNone, FlowControl.Return, -1);
public static readonly OpCode Unaligned = new OpCode(-494, OperandType.ShortInlineI, FlowControl.Meta, 0);
public static readonly OpCode Volatile = new OpCode(-493, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Tailcall = new OpCode(-492, OperandType.InlineNone, FlowControl.Meta, 0);
public static readonly OpCode Initobj = new OpCode(-491, OperandType.InlineType, FlowControl.Next, -1);
public static readonly OpCode Constrained = new OpCode(-490, OperandType.InlineType, FlowControl.Meta, 0);
public static readonly OpCode Cpblk = new OpCode(-489, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Initblk = new OpCode(-488, OperandType.InlineNone, FlowControl.Next, -3);
public static readonly OpCode Rethrow = new OpCode(-486, OperandType.InlineNone, FlowControl.Throw, 0);
public static readonly OpCode Sizeof = new OpCode(-484, OperandType.InlineType, FlowControl.Next, 1);
public static readonly OpCode Refanytype = new OpCode(-483, OperandType.InlineNone, FlowControl.Next, 0);
public static readonly OpCode Readonly = new OpCode(-482, OperandType.InlineNone, FlowControl.Meta, 0);
}
}

107
refemit/ParameterBuilder.cs Normal file
Просмотреть файл

@ -0,0 +1,107 @@
/*
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.Reflection;
using IKVM.Reflection.Emit.Writer;
using System.Runtime.InteropServices;
namespace IKVM.Reflection.Emit
{
public sealed class ParameterBuilder
{
private readonly ModuleBuilder moduleBuilder;
private short flags;
private readonly short sequence;
private readonly int 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.name = name == null ? 0 : moduleBuilder.Strings.Add(name);
}
public void SetCustomAttribute(CustomAttributeBuilder customAttributeBuilder)
{
if (customAttributeBuilder.Constructor.DeclaringType == typeof(InAttribute))
{
flags |= (short)ParameterAttributes.In;
}
else if (customAttributeBuilder.Constructor.DeclaringType == typeof(OutAttribute))
{
flags |= (short)ParameterAttributes.Out;
}
else if (customAttributeBuilder.Constructor.DeclaringType == typeof(OptionalAttribute))
{
flags |= (short)ParameterAttributes.Optional;
}
else if (customAttributeBuilder.Constructor.DeclaringType == typeof(MarshalAsAttribute))
{
flags |= (short)ParameterAttributes.HasFieldMarshal;
if (lazyPseudoToken == 0)
{
lazyPseudoToken = moduleBuilder.AllocPseudoToken();
}
TableHeap.FieldMarshalTable.Record rec = new TableHeap.FieldMarshalTable.Record();
rec.Parent = lazyPseudoToken;
rec.NativeType = FieldBuilder.WriteMarshallingDescriptor(moduleBuilder, customAttributeBuilder);
moduleBuilder.Tables.FieldMarshal.AddRecord(rec);
}
else if (customAttributeBuilder.Constructor.DeclaringType == typeof(DefaultParameterValueAttribute))
{
flags |= (short)ParameterAttributes.HasDefault;
if (lazyPseudoToken == 0)
{
lazyPseudoToken = moduleBuilder.AllocPseudoToken();
}
moduleBuilder.AddConstant(lazyPseudoToken, customAttributeBuilder.GetConstructorArgument(0));
}
else
{
if (lazyPseudoToken == 0)
{
lazyPseudoToken = moduleBuilder.AllocPseudoToken();
}
moduleBuilder.SetCustomAttribute(lazyPseudoToken, customAttributeBuilder);
}
}
internal void WriteParamRecord(MetadataWriter mw)
{
mw.Write(flags);
mw.Write(sequence);
mw.WriteStringIndex(name);
}
internal void FixupToken(int parameterToken)
{
if (lazyPseudoToken != 0)
{
moduleBuilder.RegisterTokenFixup(lazyPseudoToken, parameterToken);
}
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
/*
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 Emit")]
[assembly: AssemblyDescription("Managed (partial) Reflection Emit implementation for use by ikvmc")]

202
refemit/PropertyBuilder.cs Normal file
Просмотреть файл

@ -0,0 +1,202 @@
/*
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.Reflection;
using IKVM.Reflection.Emit.Writer;
namespace IKVM.Reflection.Emit
{
public class PropertyBuilder : PropertyInfo
{
private readonly ModuleBuilder moduleBuilder;
private readonly int name;
private readonly PropertyAttributes attributes;
private readonly ByteBuffer signature;
private int getMethodToken;
private int setMethodToken;
private int pseudoToken;
internal PropertyBuilder(ModuleBuilder moduleBuilder, string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes)
{
this.moduleBuilder = moduleBuilder;
this.name = moduleBuilder.Strings.Add(name);
this.attributes = attributes;
signature = new ByteBuffer(16);
// later on we'll patch this byte, if it turns out that it is an instance property
signature.Write(SignatureHelper.PROPERTY);
signature.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
SignatureHelper.WriteType(moduleBuilder, signature, returnType);
if (parameterTypes != null)
{
foreach (Type type in parameterTypes)
{
SignatureHelper.WriteType(moduleBuilder, signature, type);
}
}
}
public void SetGetMethod(MethodBuilder mdBuilder)
{
if (!mdBuilder.IsStatic)
{
signature.Position = 0;
signature.Write((byte)(SignatureHelper.PROPERTY | SignatureHelper.HASTHIS));
}
getMethodToken = mdBuilder.MetadataToken;
}
public void SetSetMethod(MethodBuilder mdBuilder)
{
if (!mdBuilder.IsStatic)
{
signature.Position = 0;
signature.Write((byte)(SignatureHelper.PROPERTY | SignatureHelper.HASTHIS));
}
setMethodToken = mdBuilder.MetadataToken;
}
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
if (pseudoToken == 0)
{
pseudoToken = moduleBuilder.AllocPseudoToken();
}
moduleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
}
public override PropertyAttributes Attributes
{
get { throw new NotImplementedException(); }
}
public override bool CanRead
{
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get { throw new NotImplementedException(); }
}
public override MethodInfo[] GetAccessors(bool nonPublic)
{
throw new NotImplementedException();
}
public override MethodInfo GetGetMethod(bool nonPublic)
{
throw new NotImplementedException();
}
public override ParameterInfo[] GetIndexParameters()
{
throw new NotImplementedException();
}
public override MethodInfo GetSetMethod(bool nonPublic)
{
throw new NotImplementedException();
}
public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
public override Type PropertyType
{
get { throw new NotImplementedException(); }
}
public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
public override Type DeclaringType
{
get { throw new NotImplementedException(); }
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
throw new NotImplementedException();
}
public override object[] GetCustomAttributes(bool inherit)
{
throw new NotImplementedException();
}
public override bool IsDefined(Type attributeType, bool inherit)
{
throw new NotImplementedException();
}
public override string Name
{
get { throw new NotImplementedException(); }
}
public override Type ReflectedType
{
get { throw new NotImplementedException(); }
}
internal void Bake()
{
TableHeap.PropertyTable.Record rec = new TableHeap.PropertyTable.Record();
rec.Flags = (short)attributes;
rec.Name = name;
rec.Type = moduleBuilder.Blobs.Add(signature);
int token = 0x17000000 | moduleBuilder.Tables.Property.AddRecord(rec);
if (pseudoToken != 0)
{
moduleBuilder.RegisterTokenFixup(pseudoToken, token);
}
if (getMethodToken != 0)
{
const short Getter = 0x0002;
AddMethodSemantics(Getter, getMethodToken, token);
}
if (setMethodToken != 0)
{
const short Setter = 0x0001;
AddMethodSemantics(Setter, setMethodToken, token);
}
}
private void AddMethodSemantics(short semantics, int methodToken, int propertyToken)
{
TableHeap.MethodSemanticsTable.Record rec = new TableHeap.MethodSemanticsTable.Record();
rec.Semantics = semantics;
rec.Method = methodToken;
rec.Association = propertyToken;
moduleBuilder.Tables.MethodSemantics.AddRecord(rec);
}
}
}

353
refemit/SignatureHelper.cs Normal file
Просмотреть файл

@ -0,0 +1,353 @@
/*
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.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using IKVM.Reflection.Emit.Writer;
namespace IKVM.Reflection.Emit
{
public class SignatureHelper
{
internal const byte DEFAULT = 0x00;
internal const byte GENERIC = 0x10;
internal const byte HASTHIS = 0x20;
internal const byte FIELD = 0x06;
internal const byte PROPERTY = 0x08;
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_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_GENERICINST = 0x15;
internal const byte ELEMENT_TYPE_I = 0x18;
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 = 0x020;
private enum GenericParameterType
{
None,
Method,
Type
}
internal static void WriteType(ModuleBuilder moduleBuilder, ByteBuffer bb, Type type)
{
WriteType(moduleBuilder, bb, type, GenericParameterType.None);
}
private static void WriteType(ModuleBuilder moduleBuilder, ByteBuffer bb, Type type, GenericParameterType genericParameter)
{
while (type.IsArray)
{
// check for non-szarrays
if (!type.FullName.EndsWith("[]", StringComparison.Ordinal))
{
throw new NotImplementedException();
}
bb.Write(ELEMENT_TYPE_SZARRAY);
type = type.GetElementType();
}
while (type.IsByRef)
{
bb.Write(ELEMENT_TYPE_BYREF);
type = type.GetElementType();
}
if (type == typeof(void))
{
bb.Write(ELEMENT_TYPE_VOID);
}
else if (type == typeof(bool))
{
bb.Write(ELEMENT_TYPE_BOOLEAN);
}
else if (type == typeof(char))
{
bb.Write(ELEMENT_TYPE_CHAR);
}
else if (type == typeof(sbyte))
{
bb.Write(ELEMENT_TYPE_I1);
}
else if (type == typeof(byte))
{
bb.Write(ELEMENT_TYPE_U1);
}
else if (type == typeof(short))
{
bb.Write(ELEMENT_TYPE_I2);
}
else if (type == typeof(ushort))
{
bb.Write(ELEMENT_TYPE_U2);
}
else if (type == typeof(int))
{
bb.Write(ELEMENT_TYPE_I4);
}
else if (type == typeof(uint))
{
bb.Write(ELEMENT_TYPE_U4);
}
else if (type == typeof(long))
{
bb.Write(ELEMENT_TYPE_I8);
}
else if (type == typeof(ulong))
{
bb.Write(ELEMENT_TYPE_U8);
}
else if (type == typeof(float))
{
bb.Write(ELEMENT_TYPE_R4);
}
else if (type == typeof(double))
{
bb.Write(ELEMENT_TYPE_R8);
}
else if (type == typeof(string))
{
bb.Write(ELEMENT_TYPE_STRING);
}
else if (type == typeof(IntPtr))
{
bb.Write(ELEMENT_TYPE_I);
}
else if (type == typeof(object))
{
bb.Write(ELEMENT_TYPE_OBJECT);
}
else if (type.IsGenericParameter)
{
switch (genericParameter)
{
case GenericParameterType.Type:
bb.Write(ELEMENT_TYPE_VAR);
bb.WriteCompressedInt(type.GenericParameterPosition);
break;
case GenericParameterType.Method:
bb.Write(ELEMENT_TYPE_MVAR);
bb.WriteCompressedInt(type.GenericParameterPosition);
break;
default:
throw new InvalidOperationException();
}
}
else if (type.IsGenericType && !type.IsGenericTypeDefinition)
{
WriteGenericSignature(moduleBuilder, bb, type.GetGenericTypeDefinition(), type.GetGenericArguments());
}
else if (!type.IsPrimitive)
{
if (type.IsValueType)
{
bb.Write(ELEMENT_TYPE_VALUETYPE);
}
else
{
bb.Write(ELEMENT_TYPE_CLASS);
}
bb.WriteTypeDefOrRefEncoded(moduleBuilder.GetTypeToken(type).Token);
}
else
{
throw new NotImplementedException(type.FullName);
}
}
internal static void WriteCustomModifiers(ModuleBuilder moduleBuilder, ByteBuffer bb, byte mod, Type[] modifiers)
{
if (modifiers != null)
{
foreach (Type type in modifiers)
{
bb.Write(mod);
bb.WriteTypeDefOrRefEncoded(moduleBuilder.GetTypeToken(type).Token);
}
}
}
internal static void WriteFieldSig(ModuleBuilder moduleBuilder, ByteBuffer bb, Type fieldType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
{
bb.Write(FIELD);
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_REQD, requiredCustomModifiers);
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_OPT, optionalCustomModifiers);
WriteType(moduleBuilder, bb, fieldType);
}
internal static void WriteMethodSig(ModuleBuilder moduleBuilder, ByteBuffer bb, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
{
if ((callingConvention & ~CallingConventions.HasThis) != CallingConventions.Standard)
{
throw new NotImplementedException();
}
byte first = DEFAULT;
if ((callingConvention & CallingConventions.HasThis) != 0)
{
first |= HASTHIS;
}
parameterTypes = parameterTypes ?? Type.EmptyTypes;
bb.Write(first);
bb.WriteCompressedInt(parameterTypes.Length);
// RetType
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_REQD, returnTypeRequiredCustomModifiers);
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_OPT, returnTypeOptionalCustomModifiers);
WriteType(moduleBuilder, bb, returnType ?? typeof(void));
// Param
for (int i = 0; i < parameterTypes.Length; i++)
{
if (parameterTypeRequiredCustomModifiers != null && parameterTypeRequiredCustomModifiers.Length > i)
{
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_REQD, parameterTypeRequiredCustomModifiers[i]);
}
if (parameterTypeOptionalCustomModifiers != null && parameterTypeOptionalCustomModifiers.Length > i)
{
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_OPT, parameterTypeOptionalCustomModifiers[i]);
}
WriteType(moduleBuilder, bb, parameterTypes[i]);
}
}
private static MethodBase GetMethodOnTypeDefinition(MethodBase method)
{
Type type = method.DeclaringType;
if (type != null && type.IsGenericType && !type.IsGenericTypeDefinition)
{
// this trick allows us to go from the method on the generic type instance, to the equivalent method on the generic type definition
method = method.Module.ResolveMethod(method.MetadataToken);
}
return method;
}
internal static void WriteMethodSig(ModuleBuilder moduleBuilder, ByteBuffer bb, MethodBase methodOnTypeInstance)
{
Debug.Assert(!methodOnTypeInstance.IsGenericMethod || methodOnTypeInstance.IsGenericMethodDefinition);
MethodBase method = GetMethodOnTypeDefinition(methodOnTypeInstance);
ParameterInfo returnParameter = null;
ParameterInfo[] parameters = method.GetParameters();
if (method is MethodInfo)
{
returnParameter = ((MethodInfo)method).ReturnParameter;
}
bool methodIsGeneric = false;
ParameterInfo methodOnTypeInstanceReturnParameter = returnParameter;
ParameterInfo[] methodOnTypeInstanceParameters = parameters;
if (methodOnTypeInstance.IsGenericMethodDefinition)
{
methodIsGeneric = true;
methodOnTypeInstanceReturnParameter = ((MethodInfo)methodOnTypeInstance).ReturnParameter;
methodOnTypeInstanceParameters = methodOnTypeInstance.GetParameters();
}
byte first = DEFAULT;
if (!method.IsStatic)
{
first |= HASTHIS;
}
if (method.IsGenericMethod)
{
first |= GENERIC;
}
bb.Write(first);
if (method.IsGenericMethod)
{
bb.WriteCompressedInt(method.GetGenericArguments().Length);
}
bb.WriteCompressedInt(parameters.Length);
// RetType
if (returnParameter == null)
{
WriteType(moduleBuilder, bb, typeof(void));
}
else
{
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_REQD, returnParameter.GetRequiredCustomModifiers());
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_OPT, returnParameter.GetOptionalCustomModifiers());
WriteMethodParameterType(moduleBuilder, bb, returnParameter.ParameterType, methodOnTypeInstanceReturnParameter.ParameterType, methodIsGeneric);
}
// Param
for (int i = 0; i < parameters.Length; i++)
{
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_REQD, parameters[i].GetRequiredCustomModifiers());
WriteCustomModifiers(moduleBuilder, bb, ELEMENT_TYPE_CMOD_OPT, parameters[i].GetOptionalCustomModifiers());
WriteMethodParameterType(moduleBuilder, bb, parameters[i].ParameterType, methodOnTypeInstanceParameters[i].ParameterType, methodIsGeneric);
}
}
private static bool IsGenericParameter(Type type)
{
while (type.HasElementType)
{
type = type.GetElementType();
}
return type.IsGenericParameter;
}
private static void WriteMethodParameterType(ModuleBuilder moduleBuilder, ByteBuffer bb, Type type1, Type type2, bool methodIsGeneric)
{
if (methodIsGeneric && IsGenericParameter(type2))
{
WriteType(moduleBuilder, bb, type1, GenericParameterType.Method);
}
else if (IsGenericParameter(type1))
{
WriteType(moduleBuilder, bb, type1, GenericParameterType.Type);
}
else
{
WriteType(moduleBuilder, bb, type1);
}
}
internal static void WriteGenericSignature(ModuleBuilder moduleBuilder, ByteBuffer bb, Type type, Type[] typeArguments)
{
Debug.Assert(type.IsGenericTypeDefinition);
bb.Write(ELEMENT_TYPE_GENERICINST);
WriteType(moduleBuilder, bb, type);
bb.WriteCompressedInt(typeArguments.Length);
foreach (Type t in typeArguments)
{
WriteType(moduleBuilder, bb, t);
}
}
}
}

81
refemit/Tokens.cs Normal file
Просмотреть файл

@ -0,0 +1,81 @@
/*
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 ConstructorToken
{
internal readonly int Token;
internal ConstructorToken(int token)
{
this.Token = token;
}
internal bool IsPseudoToken
{
get { return Token < 0; }
}
}
public struct FieldToken
{
internal readonly int Token;
internal FieldToken(int token)
{
this.Token = token;
}
internal bool IsPseudoToken
{
get { return Token < 0; }
}
}
public struct MethodToken
{
internal readonly int Token;
internal MethodToken(int token)
{
this.Token = token;
}
internal bool IsPseudoToken
{
get { return Token < 0; }
}
}
public struct TypeToken
{
internal readonly int Token;
internal TypeToken(int token)
{
this.Token = token;
}
}
}

893
refemit/TypeBuilder.cs Normal file
Просмотреть файл

@ -0,0 +1,893 @@
/*
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.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using IKVM.Reflection.Emit.Writer;
using IKVM.Reflection.Emit.Impl;
namespace IKVM.Reflection.Emit
{
public class GenericTypeParameterBuilder
{
private readonly ModuleBuilder moduleBuilder;
private readonly int owner;
internal GenericTypeParameterBuilder(ModuleBuilder moduleBuilder, int owner)
{
this.moduleBuilder = moduleBuilder;
this.owner = owner;
}
public void SetBaseTypeConstraint(Type baseTypeConstraint)
{
TableHeap.GenericParamConstraintTable.Record rec = new TableHeap.GenericParamConstraintTable.Record();
rec.Owner = owner;
rec.Constraint = moduleBuilder.GetTypeToken(baseTypeConstraint).Token;
moduleBuilder.Tables.GenericParamConstraint.AddRecord(rec);
}
}
public sealed class TypeBuilder : Impl.TypeBase, ITypeOwner
{
private readonly ITypeOwner owner;
private readonly TypeToken token;
private readonly TypeToken extends;
private readonly int typeName;
private readonly int typeNameSpace;
private readonly string nameOrFullName;
private readonly Type baseType;
private readonly List<MethodBuilder> methods = new List<MethodBuilder>();
private readonly List<FieldBuilder> fields = new List<FieldBuilder>();
private List<PropertyBuilder> properties;
private TypeAttributes attribs;
private TypeFlags typeFlags;
[Flags]
private enum TypeFlags
{
IsGenericTypeDefinition = 1,
}
internal TypeBuilder(ITypeOwner owner, string name, Type baseType, TypeAttributes attribs)
{
this.owner = owner;
this.token = this.ModuleBuilder.Tables.TypeDef.AllocToken();
this.nameOrFullName = Escape(name);
this.baseType = baseType;
if (baseType != null)
{
extends = this.ModuleBuilder.GetTypeToken(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);
}
private static string Escape(string name)
{
System.Text.StringBuilder sb = null;
int pos;
for (pos = 0; pos < name.Length; pos++)
{
if ("+\\[],*&".IndexOf(name[pos]) != -1)
{
if (sb == null)
{
sb = new System.Text.StringBuilder(name, 0, pos, name.Length + 3);
}
sb.Append('\\').Append(name[pos]);
}
}
return sb != null ? sb.ToString() : name;
}
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 = ".ctor";
if ((attribs & MethodAttributes.Static) != 0)
{
name = ".cctor";
}
MethodBuilder mb = DefineMethod(name, attribs, CallingConventions.Standard, typeof(void), null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
return new ConstructorBuilder(mb);
}
public ConstructorBuilder DefineTypeInitializer()
{
MethodBuilder mb = DefineMethod(".cctor", MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, typeof(void), Type.EmptyTypes);
return new ConstructorBuilder(mb);
}
public MethodBuilder DefineMethod(string name, MethodAttributes attribs)
{
return DefineMethod(name, attribs, null, null);
}
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)
{
this.ModuleBuilder.Tables.MethodDef.AddRow();
MethodBuilder mb = new MethodBuilder(this, name, attributes, callingConvention, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
methods.Add(mb);
return mb;
}
public void DefineMethodOverride(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
{
TableHeap.MethodImplTable.Record rec = new TableHeap.MethodImplTable.Record();
rec.Class = token.Token;
rec.MethodBody = this.ModuleBuilder.GetMethodToken(methodInfoBody).Token;
rec.MethodDeclaration = this.ModuleBuilder.GetMethodToken(methodInfoDeclaration).Token;
this.ModuleBuilder.Tables.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)
{
if (properties == null)
{
properties = new List<PropertyBuilder>();
}
PropertyBuilder pb = new PropertyBuilder(this.ModuleBuilder, name, attributes, returnType, parameterTypes);
properties.Add(pb);
return pb;
}
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)
{
return this.ModuleBuilder.DefineNestedTypeHelper(this, name, attr, parent, PackingSize.Unspecified, 0);
}
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 void AddInterfaceImplementation(Type interfaceType)
{
TableHeap.InterfaceImplTable.Record rec = new TableHeap.InterfaceImplTable.Record();
rec.Class = token.Token;
rec.Interface = this.ModuleBuilder.GetTypeToken(interfaceType).Token;
this.ModuleBuilder.Tables.InterfaceImpl.AddRecord(rec);
}
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)
{
TableHeap.ClassLayoutTable.Record rec = new TableHeap.ClassLayoutTable.Record();
rec.PackingSize = (short)(pack ?? 0);
rec.ClassSize = size ?? 0;
rec.Parent = token.Token;
this.ModuleBuilder.Tables.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 = (CharSet?)customBuilder.GetFieldValue("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(CustomAttributeBuilder customBuilder)
{
if (customBuilder.Constructor.DeclaringType == typeof(StructLayoutAttribute))
{
SetStructLayoutPseudoCustomAttribute(customBuilder);
}
else if (customBuilder.Constructor.DeclaringType == typeof(SerializableAttribute))
{
attribs |= TypeAttributes.Serializable;
}
else if (customBuilder.Constructor.DeclaringType == typeof(ComImportAttribute))
{
attribs |= TypeAttributes.Import;
}
else
{
this.ModuleBuilder.SetCustomAttribute(token.Token, customBuilder);
}
}
public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
{
throw new NotImplementedException();
}
public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
{
typeFlags |= TypeFlags.IsGenericTypeDefinition;
GenericTypeParameterBuilder[] gtpb = new GenericTypeParameterBuilder[names.Length];
for (int i = 0; i < names.Length; i++)
{
TableHeap.GenericParamTable.Record rec = new TableHeap.GenericParamTable.Record();
rec.Number = (short)i;
rec.Flags = 0;
rec.Owner = token.Token;
rec.Name = this.ModuleBuilder.Strings.Add(names[i]);
gtpb[i] = new GenericTypeParameterBuilder(this.ModuleBuilder, this.ModuleBuilder.Tables.GenericParam.AddRecord(rec));
}
return gtpb;
}
public Type CreateType()
{
foreach (MethodBuilder mb in methods)
{
mb.Bake();
}
if (properties != null)
{
TableHeap.PropertyMapTable.Record rec = new TableHeap.PropertyMapTable.Record();
rec.Parent = token.Token;
rec.PropertyList = this.ModuleBuilder.Tables.Property.RowCount + 1;
this.ModuleBuilder.Tables.PropertyMap.AddRecord(rec);
foreach (PropertyBuilder pb in properties)
{
pb.Bake();
}
properties = null;
}
return new BakedType(this);
}
public override string AssemblyQualifiedName
{
get { return FullName + ", " + this.ModuleBuilder.Assembly.FullName; }
}
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;
}
}
}
protected override TypeAttributes GetAttributeFlagsImpl()
{
return attribs;
}
internal MethodInfo __GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers);
}
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
const BindingFlags supportedFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
if (binder != null || (bindingAttr & ~supportedFlags) != 0)
{
throw new NotSupportedException();
}
foreach (MethodBuilder mb in methods)
{
if (mb.Name == name
&& ((mb.IsPublic && ((bindingAttr & BindingFlags.Public) != 0)) || (!mb.IsPublic && ((bindingAttr & BindingFlags.NonPublic) != 0)))
&& ((mb.IsStatic && ((bindingAttr & BindingFlags.Static) != 0)) || (!mb.IsStatic && ((bindingAttr & BindingFlags.Instance) != 0)))
&& (types == null || mb.MatchParameters(types)))
{
return mb;
}
}
if (baseType == null || (bindingAttr & BindingFlags.DeclaredOnly) != 0)
{
return null;
}
return baseType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
}
public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
throw new NotImplementedException();
}
protected override bool HasElementTypeImpl()
{
return false;
}
protected override bool IsArrayImpl()
{
return false;
}
protected override bool IsByRefImpl()
{
return false;
}
protected override bool IsValueTypeImpl()
{
return baseType == typeof(ValueType) || baseType == typeof(Enum);
}
public override Type MakeGenericType(params Type[] typeArguments)
{
return GenericType.Make(this, typeArguments);
}
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.Tables.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;
}
}
internal void WriteTypeDefRecord(MetadataWriter mw, ref int fieldList, ref int methodList)
{
mw.Write((int)attribs);
mw.WriteStringIndex(typeName);
mw.WriteStringIndex(typeNameSpace);
mw.WriteTypeDefOrRef(extends.Token);
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 override ModuleBuilder ModuleBuilder
{
get { return owner.ModuleBuilder; }
}
internal override TypeToken GetToken()
{
return token;
}
ModuleBuilder ITypeOwner.ModuleBuilder
{
get { return owner.ModuleBuilder; }
}
}
sealed class ArrayType : Impl.TypeBase
{
private readonly Impl.TypeBase type;
private TypeToken token;
internal static Type Make(Impl.TypeBase type)
{
return type.ModuleBuilder.CanonicalizeType(new ArrayType(type));
}
private ArrayType(Impl.TypeBase type)
{
this.type = type;
}
public override string AssemblyQualifiedName
{
get { throw new NotImplementedException(); }
}
public override Type BaseType
{
get { return typeof(System.Array); }
}
public override string FullName
{
get { return type.FullName + "[]"; }
}
protected override TypeAttributes GetAttributeFlagsImpl()
{
throw new NotImplementedException();
}
public override Type GetElementType()
{
return type;
}
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}
protected override bool HasElementTypeImpl()
{
return true;
}
protected override bool IsArrayImpl()
{
return true;
}
protected override bool IsByRefImpl()
{
return false;
}
protected override bool IsValueTypeImpl()
{
return false;
}
public override bool Equals(object o)
{
ArrayType at = o as ArrayType;
return at != null && at.type.Equals(type);
}
public override int GetHashCode()
{
return type.GetHashCode() * 5;
}
internal override ModuleBuilder ModuleBuilder
{
get { return type.ModuleBuilder; }
}
internal override TypeToken GetToken()
{
if (token.Token == 0)
{
ByteBuffer spec = new ByteBuffer(5);
SignatureHelper.WriteType(this.ModuleBuilder, spec, this);
token = new TypeToken(0x1B000000 | this.ModuleBuilder.Tables.TypeSpec.AddRecord(this.ModuleBuilder.Blobs.Add(spec)));
}
return token;
}
}
sealed class BakedType : Impl.TypeBase
{
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 FullName
{
get { return typeBuilder.FullName; }
}
protected override TypeAttributes GetAttributeFlagsImpl()
{
return typeBuilder.Attributes;
}
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
return typeBuilder.__GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers);
}
public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
return typeBuilder.GetMethods(bindingAttr);
}
protected override bool HasElementTypeImpl()
{
return false;
}
protected override bool IsArrayImpl()
{
return false;
}
protected override bool IsByRefImpl()
{
return false;
}
protected override bool IsValueTypeImpl()
{
return typeBuilder.IsValueType;
}
public override Type MakeArrayType()
{
return typeBuilder.MakeArrayType();
}
public override Type MakeGenericType(params Type[] typeArguments)
{
return typeBuilder.MakeGenericType(typeArguments);
}
public override System.Runtime.InteropServices.StructLayoutAttribute StructLayoutAttribute
{
get { return typeBuilder.StructLayoutAttribute; }
}
public override Type UnderlyingSystemType
{
// Type.Equals/GetHashCode relies on this
get { return typeBuilder; }
}
public override bool IsGenericType
{
get
{
return typeBuilder.IsGenericType;
}
}
public override bool IsGenericTypeDefinition
{
get
{
return typeBuilder.IsGenericTypeDefinition;
}
}
internal override ModuleBuilder ModuleBuilder
{
get { return typeBuilder.ModuleBuilder; }
}
internal override TypeToken GetToken()
{
return typeBuilder.GetToken();
}
}
sealed class GenericType : Impl.TypeBase
{
private readonly TypeBuilder typeBuilder;
private readonly Type[] typeArguments;
private TypeToken token;
internal static Type Make(TypeBuilder typeBuilder, Type[] typeArguments)
{
return typeBuilder.ModuleBuilder.CanonicalizeType(new GenericType(typeBuilder, typeArguments));
}
private GenericType(TypeBuilder typeBuilder, Type[] typeArguments)
{
this.typeBuilder = typeBuilder;
this.typeArguments = typeArguments;
}
public override string AssemblyQualifiedName
{
get { throw new NotImplementedException(); }
}
public override Type BaseType
{
get { throw new NotImplementedException(); }
}
public override string FullName
{
get { throw new NotImplementedException(); }
}
public override string Name
{
get { throw new NotImplementedException(); }
}
public override Type[] GetGenericArguments()
{
return (Type[])typeArguments.Clone();
}
protected override TypeAttributes GetAttributeFlagsImpl()
{
throw new NotImplementedException();
}
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}
protected override bool HasElementTypeImpl()
{
return false;
}
protected override bool IsArrayImpl()
{
return false;
}
protected override bool IsByRefImpl()
{
return false;
}
public override bool Equals(object o)
{
GenericType gt = o as GenericType;
if (gt != null && gt.typeBuilder == typeBuilder)
{
for (int i = 0; i < typeArguments.Length; i++)
{
if (typeArguments[i] != gt.typeArguments[i])
{
return false;
}
}
return true;
}
return false;
}
public override int GetHashCode()
{
int hash = typeBuilder.GetHashCode();
for (int i = 0; i < typeArguments.Length; i++)
{
hash *= 37;
hash ^= typeArguments[i].GetHashCode();
}
return hash;
}
public override bool IsGenericType
{
get { return true; }
}
public override bool IsGenericTypeDefinition
{
get { return false; }
}
internal override ModuleBuilder ModuleBuilder
{
get { return typeBuilder.ModuleBuilder; }
}
internal override TypeToken GetToken()
{
if (token.Token == 0)
{
ByteBuffer spec = new ByteBuffer(5);
SignatureHelper.WriteGenericSignature(typeBuilder.ModuleBuilder, spec, typeBuilder, typeArguments);
token = new TypeToken(0x1B000000 | this.ModuleBuilder.Tables.TypeSpec.AddRecord(this.ModuleBuilder.Blobs.Add(spec)));
}
return token;
}
}
}

Просмотреть файл

@ -0,0 +1,281 @@
/*
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;
namespace IKVM.Reflection.Emit.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)
{
this.buffer = wrap;
this.pos = wrap.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 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 TableHeap.TypeDefTable.Index:
WriteCompressedInt((token & 0xFFFFFF) << 2 | 0);
break;
case TableHeap.TypeRefTable.Index:
WriteCompressedInt((token & 0xFFFFFF) << 2 | 1);
break;
case TableHeap.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 static ByteBuffer Wrap(byte[] pubkey)
{
return new ByteBuffer(pubkey);
}
internal byte[] ToArray()
{
byte[] buf = new byte[this.Length];
Buffer.BlockCopy(this.buffer, 0, buf, 0, buf.Length);
return buf;
}
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;
}
}
}

2107
refemit/Writer/Heaps.cs Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,538 @@
/*
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;
namespace IKVM.Reflection.Emit.Writer
{
sealed class MetadataWriter
{
private readonly ModuleBuilder moduleBuilder;
private readonly Stream stream;
private readonly byte[] buffer = new byte[8];
internal MetadataWriter(ModuleBuilder moduleBuilder, Stream stream)
{
this.moduleBuilder = moduleBuilder;
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 (moduleBuilder.bigStrings)
{
Write(index);
}
else
{
Write((short)index);
}
}
internal void WriteGuidIndex(int index)
{
if (moduleBuilder.bigGuids)
{
Write(index);
}
else
{
Write((short)index);
}
}
internal void WriteBlobIndex(int index)
{
if (moduleBuilder.bigBlobs)
{
Write(index);
}
else
{
Write((short)index);
}
}
internal void WriteTypeDefOrRef(int token)
{
switch (token >> 24)
{
case 0:
break;
case TableHeap.TypeDefTable.Index:
token = (token & 0xFFFFFF) << 2 | 0;
break;
case TableHeap.TypeRefTable.Index:
token = (token & 0xFFFFFF) << 2 | 1;
break;
case TableHeap.TypeSpecTable.Index:
token = (token & 0xFFFFFF) << 2 | 2;
break;
default:
throw new NotImplementedException();
}
if (moduleBuilder.bigTypeDefOrRef)
{
Write(token);
}
else
{
Write((short)token);
}
}
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 (moduleBuilder.bigHasCustomAttribute)
{
Write(encodedToken);
}
else
{
Write((short)encodedToken);
}
}
internal void WriteCustomAttributeType(int token)
{
switch (token >> 24)
{
case TableHeap.MethodDefTable.Index:
token = (token & 0xFFFFFF) << 3 | 2;
break;
case TableHeap.MemberRefTable.Index:
token = (token & 0xFFFFFF) << 3 | 3;
break;
default:
throw new InvalidOperationException();
}
if (moduleBuilder.bigCustomAttributeType)
{
Write(token);
}
else
{
Write((short)token);
}
}
internal void WriteField(int index)
{
if (moduleBuilder.bigField)
{
Write(index & 0xFFFFFF);
}
else
{
Write((short)index);
}
}
internal void WriteMethodDef(int index)
{
if (moduleBuilder.bigMethodDef)
{
Write(index & 0xFFFFFF);
}
else
{
Write((short)index);
}
}
internal void WriteParam(int index)
{
if (moduleBuilder.bigParam)
{
Write(index & 0xFFFFFF);
}
else
{
Write((short)index);
}
}
internal void WriteTypeDef(int index)
{
if (moduleBuilder.bigTypeDef)
{
Write(index & 0xFFFFFF);
}
else
{
Write((short)index);
}
}
internal void WriteProperty(int index)
{
if (moduleBuilder.bigProperty)
{
Write(index & 0xFFFFFF);
}
else
{
Write((short)index);
}
}
internal void WriteGenericParam(int index)
{
if (moduleBuilder.bigGenericParam)
{
Write(index & 0xFFFFFF);
}
else
{
Write((short)index);
}
}
internal void WriteModuleRef(int index)
{
if (moduleBuilder.bigModuleRef)
{
Write(index & 0xFFFFFF);
}
else
{
Write((short)index);
}
}
internal void WriteResolutionScope(int token)
{
switch (token >> 24)
{
case TableHeap.ModuleTable.Index:
token = (token & 0xFFFFFF) << 2 | 0;
break;
case TableHeap.ModuleRefTable.Index:
token = (token & 0xFFFFFF) << 2 | 1;
break;
case TableHeap.AssemblyRefTable.Index:
token = (token & 0xFFFFFF) << 2 | 2;
break;
case TableHeap.TypeRefTable.Index:
token = (token & 0xFFFFFF) << 2 | 3;
break;
default:
throw new InvalidOperationException();
}
if (moduleBuilder.bigResolutionScope)
{
Write(token);
}
else
{
Write((short)token);
}
}
internal void WriteMemberRefParent(int token)
{
switch (token >> 24)
{
case TableHeap.TypeDefTable.Index:
token = (token & 0xFFFFFF) << 3 | 0;
break;
case TableHeap.TypeRefTable.Index:
token = (token & 0xFFFFFF) << 3 | 1;
break;
case TableHeap.ModuleRefTable.Index:
token = (token & 0xFFFFFF) << 3 | 2;
break;
case TableHeap.MethodDefTable.Index:
token = (token & 0xFFFFFF) << 3 | 3;
break;
case TableHeap.TypeSpecTable.Index:
token = (token & 0xFFFFFF) << 3 | 4;
break;
default:
throw new InvalidOperationException();
}
if (moduleBuilder.bigMemberRefParent)
{
Write(token);
}
else
{
Write((short)token);
}
}
internal void WriteMethodDefOrRef(int token)
{
switch (token >> 24)
{
case TableHeap.MethodDefTable.Index:
token = (token & 0xFFFFFF) << 1 | 0;
break;
case TableHeap.MemberRefTable.Index:
token = (token & 0xFFFFFF) << 1 | 1;
break;
default:
throw new InvalidOperationException();
}
if (moduleBuilder.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 (moduleBuilder.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 (moduleBuilder.bigHasSemantics)
{
Write(encodedToken);
}
else
{
Write((short)encodedToken);
}
}
internal void WriteImplementation(int token)
{
switch (token >> 24)
{
case 0:
break;
case TableHeap.FileTable.Index:
token = (token & 0xFFFFFF) << 2 | 0;
break;
case TableHeap.AssemblyRefTable.Index:
token = (token & 0xFFFFFF) << 2 | 1;
break;
case TableHeap.ExportedTypeTable.Index:
token = (token & 0xFFFFFF) << 2 | 2;
break;
default:
throw new InvalidOperationException();
}
if (moduleBuilder.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 (moduleBuilder.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 (moduleBuilder.bigHasDeclSecurity)
{
Write(encodedToken);
}
else
{
Write((short)encodedToken);
}
}
internal void WriteMemberForwarded(int token)
{
switch (token >> 24)
{
case TableHeap.FieldTable.Index:
token = (token & 0xFFFFFF) << 1 | 0;
break;
case TableHeap.MethodDefTable.Index:
token = (token & 0xFFFFFF) << 1 | 1;
break;
default:
throw new InvalidOperationException();
}
if (moduleBuilder.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 (moduleBuilder.bigHasFieldMarshal)
{
Write(encodedToken & 0xFFFFFF);
}
else
{
Write((short)encodedToken);
}
}
}
}

Просмотреть файл

@ -0,0 +1,394 @@
/*
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.Reflection;
using System.Security.Cryptography;
using IKVM.Reflection.Emit;
using IKVM.Reflection.Emit.Impl;
namespace IKVM.Reflection.Emit.Writer
{
static class ModuleWriter
{
private const int versionInfoResourceHeaderLength = 0x58;
internal static void WriteModule(string directory, StrongNameKeyPair keyPair, ModuleBuilder moduleBuilder, PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine, ByteBuffer versionInfoData, int entryPointToken)
{
moduleBuilder.FixupMethodBodyTokens();
moduleBuilder.Tables.Module.Add(0, moduleBuilder.Strings.Add(moduleBuilder.moduleName), moduleBuilder.Guids.Add(Guid.NewGuid()), 0, 0);
if (moduleBuilder.UserStrings.IsEmpty)
{
// for compat with Ref.Emit, if there aren't any user strings, we add one
moduleBuilder.UserStrings.Add(" ");
}
string fileName = moduleBuilder.fileName;
if (directory != null)
{
fileName = Path.Combine(directory, fileName);
}
using (FileStream fs = new FileStream(fileName, 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("imageFileName");
}
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 = 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;
TextSection code = new TextSection(writer, cliHeader, moduleBuilder);
// 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 (versionInfoData != null)
{
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;
if (versionInfoData != null)
{
rsrc.VirtualSize = (uint)versionInfoData.Length + versionInfoResourceHeaderLength;
rsrc.SizeOfRawData = writer.ToFileAlignment((uint)versionInfoData.Length + versionInfoResourceHeaderLength);
}
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;
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);
MetadataWriter mw = new MetadataWriter(moduleBuilder, fs);
fs.Seek(text.PointerToRawData, SeekOrigin.Begin);
code.Write(mw, (int)sdata.VirtualAddress);
fs.Seek(sdata.PointerToRawData, SeekOrigin.Begin);
mw.Write(moduleBuilder.initializedData);
if (versionInfoData != null)
{
fs.Seek(rsrc.PointerToRawData, SeekOrigin.Begin);
WriteVersionInfoResource(mw, (int)rsrc.VirtualAddress, versionInfoData);
}
fs.Seek(reloc.PointerToRawData, SeekOrigin.Begin);
// .reloc section
uint pageRVA = code.StartupStubRVA & ~0xFFFU;
mw.Write(pageRVA); // PageRVA
mw.Write(0x000C); // Block Size
if (imageFileMachine == ImageFileMachine.I386)
{
mw.Write(0x3000 + code.StartupStubRVA - pageRVA + 2); // Type / Offset + padding
}
else if (imageFileMachine == ImageFileMachine.AMD64)
{
mw.Write(0xA000 + code.StartupStubRVA - pageRVA + 2); // Type / Offset + padding
}
else if (imageFileMachine == ImageFileMachine.IA64)
{
mw.Write((short)(0xA000 + code.StartupStubRVA - pageRVA + 0x20)); // Type / Offset
mw.Write((short)(0xA000 + code.StartupStubRVA - pageRVA + 0x28)); // 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 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);
sign.SetHashAlgorithm("SHA1");
byte[] signature = sign.CreateSignature(hash.Hash);
Array.Reverse(signature);
Debug.Assert(signature.Length == strongNameSignatureLength);
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 of 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;
}
}
private static void WriteVersionInfoResource(MetadataWriter mw, int rsrcRVA, ByteBuffer versionInfoData)
{
mw.Write(new byte[] {
0x00, 0x00, 0x00, 0x00, // Characteristics
0x00, 0x00, 0x00, 0x00, // Time/Date Stamp
0x00, 0x00, // Major Version
0x00, 0x00, // Minor Version
0x00, 0x00, // Number of Name Entries
0x01, 0x00, // Number of ID Entries
// Resource Directory Entry
0x10, 0x00, 0x00, 0x00, // Integer ID
0x18, 0x00, 0x00, 0x80, // Subdirectory RVA (offset 0x18)
// Resource Directory Table (at offset 0x18)
0x00, 0x00, 0x00, 0x00, // Characterics
0x00, 0x00, 0x00, 0x00, // Time/Date Stamp
0x00, 0x00, // Major Version
0x00, 0x00, // Minor Version
0x00, 0x00, // Number of Name Entries
0x01, 0x00, // Number of ID Entries
// Resource Directory Entry
0x01, 0x00, 0x00, 0x00, // Integer ID
0x30, 0x00, 0x00, 0x80, // Subdirectory RVA (offset 0x30)
// Resource Directory Table (at offset 0x30)
0x00, 0x00, 0x00, 0x00, // Characterics
0x00, 0x00, 0x00, 0x00, // Time/Date Stamp
0x00, 0x00, // Major Version
0x00, 0x00, // Minor Version
0x00, 0x00, // Number of Name Entries
0x01, 0x00, // Number of ID Entries
// Resource Directory Entry
0x00, 0x00, 0x00, 0x00, // Integer ID
0x48, 0x00, 0x00, 0x00, // Date Entry RVA (offset 0x48)
});
// Data Entry (at offset 0x48)
mw.Write(versionInfoResourceHeaderLength + rsrcRVA); // Data RVA
mw.Write(versionInfoData.Length); // Size
mw.Write(0); // Codepage
mw.Write(0); // Reserved
mw.Write(versionInfoData);
}
}
}

301
refemit/Writer/PEWriter.cs Normal file
Просмотреть файл

@ -0,0 +1,301 @@
/*
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.Emit.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 = 0x00400000;
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;
public DWORD PointerToRelocations = 0;
public DWORD PointerToLinenumbers = 0;
public WORD NumberOfRelocations = 0;
public WORD NumberOfLinenumbers = 0;
public DWORD Characteristics;
}
}

Просмотреть файл

@ -0,0 +1,490 @@
/*
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.Impl;
namespace IKVM.Reflection.Emit.Writer
{
sealed class TextSection
{
private readonly PEWriter peWriter;
private readonly CliHeader cliHeader;
private readonly ModuleBuilder moduleBuilder;
internal TextSection(PEWriter peWriter, CliHeader cliHeader, ModuleBuilder moduleBuilder)
{
this.peWriter = peWriter;
this.cliHeader = cliHeader;
this.moduleBuilder = moduleBuilder;
moduleBuilder.Freeze();
}
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
{
if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_STRONGNAMESIGNED) != 0)
{
return 128;
}
else
{
return 0;
}
}
}
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 (moduleBuilder.symbolWriter != null)
{
return 28;
}
return 0;
}
}
private uint DebugDirectoryContentsLength
{
get
{
if (moduleBuilder.symbolWriter != null)
{
PdbSupport.IMAGE_DEBUG_DIRECTORY idd = new PdbSupport.IMAGE_DEBUG_DIRECTORY();
return (uint)PdbSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd).Length;
}
return 0;
}
}
internal uint ImportDirectoryRVA
{
get { return (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength + 3) & ~3U; }
}
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)
{
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.Tables.MethodDef.Fixup(this);
moduleBuilder.Tables.MethodImpl.Fixup(moduleBuilder);
moduleBuilder.Tables.MethodSemantics.Fixup(moduleBuilder);
moduleBuilder.Tables.InterfaceImpl.Fixup(moduleBuilder);
moduleBuilder.Tables.Constant.Fixup(moduleBuilder);
moduleBuilder.Tables.FieldMarshal.Fixup(moduleBuilder);
moduleBuilder.Tables.DeclSecurity.Fixup(moduleBuilder);
moduleBuilder.Tables.CustomAttribute.Fixup(moduleBuilder);
moduleBuilder.Tables.FieldLayout.Fixup(moduleBuilder);
moduleBuilder.Tables.FieldRVA.Fixup(moduleBuilder, sdataRVA);
moduleBuilder.Tables.ImplMap.Fixup(moduleBuilder);
moduleBuilder.Tables.GenericParam.Fixup(moduleBuilder);
moduleBuilder.Tables.MethodSpec.Fixup(moduleBuilder);
moduleBuilder.Tables.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 (moduleBuilder.symbolWriter != null)
{
PdbSupport.IMAGE_DEBUG_DIRECTORY idd = new PdbSupport.IMAGE_DEBUG_DIRECTORY();
idd.Characteristics = 0;
idd.TimeDateStamp = peWriter.Headers.FileHeader.TimeDateStamp;
byte[] buf = PdbSupport.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); }
}
}
class CliHeader
{
internal const uint COMIMAGE_FLAGS_ILONLY = 0x00000001;
internal const uint COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002;
internal const uint COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008;
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 = 0;
internal uint VTableFixupsRVA = 0;
internal uint VTableFixupsSize = 0;
internal ulong ExportAddressTableJumps = 0;
internal ulong ManagedNativeHeader = 0;
internal void Write(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);
}
}
}

Просмотреть файл

@ -0,0 +1,244 @@
/*
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.Reflection;
using System.Globalization;
namespace IKVM.Reflection.Emit.Writer
{
sealed class VersionInfo
{
private AssemblyName name;
private string fileName;
private string copyright;
private string trademark;
private string product;
private string company;
private string description;
private string title;
private 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)
{
Type type = cab.Constructor.DeclaringType;
if (type == typeof(AssemblyCopyrightAttribute))
{
copyright = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(AssemblyTrademarkAttribute))
{
trademark = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(AssemblyProductAttribute))
{
product = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(AssemblyCompanyAttribute))
{
company = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(AssemblyDescriptionAttribute))
{
description = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(AssemblyTitleAttribute))
{
title = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(AssemblyInformationalVersionAttribute))
{
informationalVersion = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(AssemblyCultureAttribute))
{
culture = (string)cab.GetConstructorArgument(0);
}
else if (type == typeof(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 = new Version(fileVersion);
int fileVersionMajor = filever.Major;
int fileVersionMinor = filever.Minor;
int fileVersionBuild = filever.Build;
int fileVersionRevision = filever.Revision;
int productVersionMajor = 0;
int productVersionMinor = 0;
int productVersionBuild = 0;
int productVersionRevision = 0;
if (informationalVersion != null)
{
Version productver = new Version(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 void WriteUTF16Z(ByteBuffer bb, string str)
{
foreach (char c in str)
{
bb.Write((short)c);
}
bb.Write((short)0);
}
private 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;
}
}
}

46
refemit/refemit.build Normal file
Просмотреть файл

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<project name="refemit" default="IKVM.Reflection.Emit">
<target name="IKVM.Reflection.Emit">
<property overwrite="false" name="signed" value="" />
<property name="defs" value="IKVM_REF_EMIT" />
<if test="${property::exists('signed')}">
<property name="defs" value="${defs};${signed}" />
</if>
<csc target="library" output="../bin/IKVM.Reflection.Emit.dll" define="${defs}">
<sources>
<include name="../CommonAssemblyInfo.cs" />
<include name="AssemblyBuilder.cs" />
<include name="ConstructorBuilder.cs" />
<include name="CustomAttributeBuilder.cs" />
<include name="Enums.cs" />
<include name="FieldBuilder.cs" />
<include name="IkvmAssembly.cs" />
<include name="ILGenerator.cs" />
<include name="MethodBuilder.cs" />
<include name="ModuleBuilder.cs" />
<include name="OpCodes.cs" />
<include name="ParameterBuilder.cs" />
<include name="PropertyBuilder.cs" />
<include name="SignatureHelper.cs" />
<include name="Tokens.cs" />
<include name="TypeBuilder.cs" />
<include name="impl/CryptoConvert.cs" />
<include name="impl/CryptoHack.cs" />
<include name="impl/ITypeOwner.cs" />
<include name="impl/PdbSupport.cs" />
<include name="impl/TypeBase.cs" />
<include name="Properties/AssemblyInfo.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/TextSection.cs" />
<include name="Writer/VersionInfo.cs" />
</sources>
<references>
<include name="${framework::get-assembly-directory(framework::get-target-framework())}/ISymWrapper.dll" />
</references>
</csc>
</target>
</project>