VMProtect/runtime/VMProtect.Runtime/VirtualMachine.cs

4285 lines
92 KiB
C#

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace VMProtect
{
[VMProtect.DeleteOnCompilation]
internal enum OpCodes
{
icUnknown, icByte, icWord, icDword, icQword, icComment, icData, icCase,
icNop, icBreak, icLdarg_0, icLdarg_1, icLdarg_2, icLdarg_3, icLdloc_0, icLdloc_1, icLdloc_2, icLdloc_3, icStloc_0, icStloc_1,
icStloc_2, icStloc_3, icLdarg_s, icLdarga_s, icStarg_s, icLdloc_s, icLdloca_s, icStloc_s, icLdnull, icLdc_i4_m1, icLdc_i4_0,
icLdc_i4_1, icLdc_i4_2, icLdc_i4_3, icLdc_i4_4, icLdc_i4_5, icLdc_i4_6, icLdc_i4_7, icLdc_i4_8, icLdc_i4_s, icLdc_i4, icLdc_i8,
icLdc_r4, icLdc_r8, icDup, icPop, icJmp, icCall, icCalli, icRet, icBr_s, icBrfalse_s, icBrtrue_s, icBeq_s, icBge_s, icBgt_s, icBle_s,
icBlt_s, icBne_un_s, icBge_un_s, icBgt_un_s, icBle_un_s, icBlt_un_s, icBr, icBrfalse, icBrtrue, icBeq, icBge, icBgt, icBle, icBlt,
icBne_un, icBge_un, icBgt_un, icBle_un, icBlt_un, icSwitch, icLdind_i1, icLdind_u1, icLdind_i2, icLdind_u2, icLdind_i4, icLdind_u4,
icLdind_i8, icLdind_i, icLdind_r4, icLdind_r8, icLdind_ref, icStind_ref, icStind_i1, icStind_i2, icStind_i4, icStind_i8, icStind_r4,
icStind_r8, icAdd, icSub, icMul, icDiv, icDiv_un, icRem, icRem_un, icAnd, icOr, icXor, icShl, icShr, icShr_un, icNeg, icNot, icConv_i1, icConv_i2,
icConv_i4, icConv_i8, icConv_r4, icConv_r8, icConv_u4, icConv_u8, icCallvirt, icCpobj, icLdobj, icLdstr, icNewobj, icCastclass,
icIsinst, icConv_r_un, icUnbox, icThrow, icLdfld, icLdflda, icStfld, icLdsfld, icLdsflda, icStsfld, icStobj, icConv_ovf_i1_un,
icConv_ovf_i2_un, icConv_ovf_i4_un, icConv_ovf_i8_un, icConv_ovf_u1_un, icConv_ovf_u2_un, icConv_ovf_u4_un, icConv_ovf_u8_un,
icConv_ovf_i_un, icConv_ovf_u_un, icBox, icNewarr, icLdlen, icLdelema, icLdelem_i1, icLdelem_u1, icLdelem_i2, icLdelem_u2,
icLdelem_i4, icLdelem_u4, icLdelem_i8, icLdelem_i, icLdelem_r4, icLdelem_r8, icLdelem_ref, icStelem_i, icStelem_i1, icStelem_i2,
icStelem_i4, icStelem_i8, icStelem_r4, icStelem_r8, icStelem_ref, icLdelem, icStelem, icUnbox_any, icConv_ovf_i1, icConv_ovf_u1,
icConv_ovf_i2, icConv_ovf_u2, icConv_ovf_i4, icConv_ovf_u4, icConv_ovf_i8, icConv_ovf_u8, icRefanyval, icCkfinite, icMkrefany,
icLdtoken, icConv_u2, icConv_u1, icConv_i, icConv_ovf_i, icConv_ovf_u, icAdd_ovf, icAdd_ovf_un, icMul_ovf, icMul_ovf_un, icSub_ovf,
icSub_ovf_un, icEndfinally, icLeave, icLeave_s, icStind_i, icConv_u, icArglist, icCeq, icCgt, icCgt_un, icClt, icClt_un, icLdftn, icLdvirtftn,
icLdarg, icLdarga, icStarg, icLdloc, icLdloca, icStloc, icLocalloc, icEndfilter, icUnaligned, icVolatile, icTail, icInitobj, icConstrained,
icCpblk, icInitblk, icNo, icRethrow, icSizeof, icRefanytype, icReadonly,
icConv, icConv_ovf, icConv_ovf_un, icLdmem_i4, icInitarg, icInitcatchblock, icEntertry, icCallvm, icCallvmvirt,
icCmp, icCmp_un
}
public class VirtualMachine
{
static class Utils
{
public static int Random()
{
return new Random().Next();
}
public static int CalcCRC(uint offset, uint size)
{
long instance = Marshal.GetHINSTANCE(typeof(CRC32).Module).ToInt64();
return (int)new CRC32().Hash(new IntPtr(instance + offset), size);
}
unsafe public static object BoxPointer(void* ptr)
{
return Pointer.Box(ptr, typeof(void*));
}
unsafe public static void* UnboxPointer(object ptr)
{
return Pointer.Unbox(ptr);
}
}
abstract class BaseVariant
{
public abstract BaseVariant Clone();
public abstract object Value();
public abstract void SetValue(object value);
public virtual void SetFieldValue(FieldInfo field, object value)
{
var obj = Value();
field.SetValue(obj, value);
}
public virtual bool IsReference()
{
return false;
}
public virtual StackableVariant ToStack()
{
throw new InvalidOperationException();
}
public virtual BaseVariant ToUnsigned()
{
return this;
}
public virtual Type Type()
{
throw new InvalidOperationException();
}
public virtual TypeCode CalcTypeCode()
{
throw new InvalidOperationException();
}
public virtual bool ToBoolean()
{
return System.Convert.ToBoolean(Value());
}
public virtual sbyte ToSByte()
{
return System.Convert.ToSByte(Value());
}
public virtual short ToInt16()
{
return System.Convert.ToInt16(Value());
}
public virtual int ToInt32()
{
return System.Convert.ToInt32(Value());
}
public virtual long ToInt64()
{
return System.Convert.ToInt64(Value());
}
public virtual char ToChar()
{
return System.Convert.ToChar(Value());
}
public virtual byte ToByte()
{
return System.Convert.ToByte(Value());
}
public virtual ushort ToUInt16()
{
return System.Convert.ToUInt16(Value());
}
public virtual uint ToUInt32()
{
return System.Convert.ToUInt32(Value());
}
public virtual ulong ToUInt64()
{
return System.Convert.ToUInt64(Value());
}
public virtual float ToSingle()
{
return System.Convert.ToSingle(Value());
}
public virtual double ToDouble()
{
return System.Convert.ToDouble(Value());
}
public override string ToString()
{
var v = Value();
return v != null ? System.Convert.ToString(v) : null;
}
public virtual IntPtr ToIntPtr()
{
var value = Value();
if (value?.GetType() == typeof(IntPtr))
return (IntPtr)value;
throw new InvalidOperationException();
}
public virtual UIntPtr ToUIntPtr()
{
var value = Value();
if (value?.GetType() == typeof(UIntPtr))
return (UIntPtr)value;
throw new InvalidOperationException();
}
public virtual unsafe void* ToPointer()
{
throw new InvalidOperationException();
}
public virtual object Conv_ovf(Type type, bool un)
{
throw new InvalidOperationException();
}
}
abstract class StackableVariant : BaseVariant
{
public override StackableVariant ToStack()
{
return this;
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Empty;
}
}
sealed class IntVariant : StackableVariant
{
private int _value;
public IntVariant(int value)
{
_value = value;
}
public override Type Type()
{
return typeof(int);
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Int32;
}
public override BaseVariant Clone()
{
return new IntVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToInt32(value);
}
public override bool ToBoolean()
{
return _value != 0;
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override int ToInt32()
{
return _value;
}
public override long ToInt64()
{
return (long)_value;
}
public override char ToChar()
{
return (char)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override uint ToUInt32()
{
return (uint)_value;
}
public override ulong ToUInt64()
{
return (uint)_value;
}
public override float ToSingle()
{
return _value;
}
public override double ToDouble()
{
return (double)_value;
}
public override IntPtr ToIntPtr()
{
return new IntPtr(_value);
}
public override UIntPtr ToUIntPtr()
{
return new UIntPtr((uint)_value);
}
public override BaseVariant ToUnsigned()
{
return new UintVariant((uint)_value);
}
public override object Conv_ovf(Type type, bool un)
{
if (type == typeof(IntPtr))
{
if (IntPtr.Size == 4)
return new IntPtr(un ? checked((int)(uint)_value) : _value);
return new IntPtr(un ? (long)(uint)_value : _value);
}
if (type == typeof(UIntPtr))
return new UIntPtr(un ? (uint)_value : checked((uint)_value));
switch (System.Type.GetTypeCode(type)) {
case TypeCode.SByte:
return un ? checked((sbyte)(uint)_value) : checked((sbyte)_value);
case TypeCode.Int16:
return un ? checked((short)(uint)_value) : checked((short)_value);
case TypeCode.Int32:
return un ? checked((int)(uint)_value) : _value;
case TypeCode.Int64:
return un ? (long)(uint)_value : _value;
case TypeCode.Byte:
return un ? checked((byte)(uint)_value) : checked((byte)_value);
case TypeCode.UInt16:
return un ? checked((ushort)(uint)_value) : checked((ushort)_value);
case TypeCode.UInt32:
return un ? (uint)_value : checked((uint)_value);
case TypeCode.UInt64:
return un ? (uint)_value : checked((uint)_value);
case TypeCode.Double:
return un ? (double)(uint)_value : (double)_value;
}
throw new ArgumentException();
}
}
sealed class LongVariant : StackableVariant
{
private long _value;
public LongVariant(long value)
{
_value = value;
}
public override Type Type()
{
return typeof(long);
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Int64;
}
public override BaseVariant ToUnsigned()
{
return new UlongVariant((ulong)_value);
}
public override BaseVariant Clone()
{
return new LongVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToInt64(value);
}
public override bool ToBoolean()
{
return _value != 0;
}
public override char ToChar()
{
return (char)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override int ToInt32()
{
return (int)_value;
}
public override long ToInt64()
{
return _value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override uint ToUInt32()
{
return (uint)_value;
}
public override ulong ToUInt64()
{
return (ulong)_value;
}
public override float ToSingle()
{
return _value;
}
public override double ToDouble()
{
return (double)_value;
}
public override IntPtr ToIntPtr()
{
return new IntPtr(IntPtr.Size == 4 ? (int)_value : _value);
}
public override UIntPtr ToUIntPtr()
{
return new UIntPtr(UIntPtr.Size == 4 ? (uint)_value : (ulong)_value);
}
public override object Conv_ovf(Type type, bool un)
{
if (type == typeof(IntPtr))
return new IntPtr(un ? checked((long)(ulong)_value) : _value);
if (type == typeof(UIntPtr))
return new UIntPtr(un ? (ulong)_value : checked((ulong)_value));
switch (System.Type.GetTypeCode(type))
{
case TypeCode.SByte:
return un ? checked((sbyte)(ulong)_value) : checked((sbyte)_value);
case TypeCode.Int16:
return un ? checked((short)(ulong)_value) : checked((short)_value);
case TypeCode.Int32:
return un ? checked((int)(ulong)_value) : checked((int)_value);
case TypeCode.Int64:
return un ? checked((long)(ulong)_value) : _value;
case TypeCode.Byte:
return un ? checked((byte)(ulong)_value) : checked((byte)_value);
case TypeCode.UInt16:
return un ? checked((ushort)(uint)_value) : checked((ushort)_value);
case TypeCode.UInt32:
return un ? checked((uint)(ulong)_value) : checked((uint)_value);
case TypeCode.UInt64:
return un ? (ulong)_value : checked((ulong)_value);
case TypeCode.Double:
return un ? (double)(ulong)_value : (double)_value;
}
throw new ArgumentException();
}
}
sealed class SingleVariant : StackableVariant
{
private float _value;
public SingleVariant(float value)
{
_value = value;
}
public override Type Type()
{
return typeof(float);
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Single;
}
public override BaseVariant Clone()
{
return new SingleVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToSingle(value);
}
public override bool ToBoolean()
{
return System.Convert.ToBoolean(_value);
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override int ToInt32()
{
return (int)_value;
}
public override long ToInt64()
{
return (long)_value;
}
public override char ToChar()
{
return (char)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override uint ToUInt32()
{
return (uint)_value;
}
public override ulong ToUInt64()
{
return (ulong)_value;
}
public override float ToSingle()
{
return _value;
}
public override double ToDouble()
{
return _value;
}
public override IntPtr ToIntPtr()
{
return new IntPtr(IntPtr.Size == 4 ? (int)_value : (long)_value);
}
public override UIntPtr ToUIntPtr()
{
return new UIntPtr(IntPtr.Size == 4 ? (uint)_value : (ulong)_value);
}
public override object Conv_ovf(Type type, bool un)
{
if (type == typeof(IntPtr))
return new IntPtr(checked((long)_value));
if (type == typeof(UIntPtr))
return new UIntPtr(checked((ulong)_value));
switch (System.Type.GetTypeCode(type))
{
case TypeCode.SByte:
return un ? checked((sbyte)(uint)_value) : checked((sbyte)_value);
case TypeCode.Int16:
return un ? checked((short)(uint)_value) : checked((short)_value);
case TypeCode.Int32:
return checked((int)_value);
case TypeCode.Byte:
return checked((byte)_value);
case TypeCode.UInt16:
return checked((ushort)_value);
case TypeCode.UInt32:
return checked((uint)_value);
case TypeCode.UInt64:
return checked((ulong)_value);
}
throw new ArgumentException();
}
}
sealed class DoubleVariant : StackableVariant
{
private double _value;
public DoubleVariant(double value)
{
_value = value;
}
public override Type Type()
{
return typeof(double);
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Double;
}
public override BaseVariant Clone()
{
return new DoubleVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = (double)value;
}
public override bool ToBoolean()
{
return System.Convert.ToBoolean(_value);
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override int ToInt32()
{
return (int)_value;
}
public override long ToInt64()
{
return (long)_value;
}
public override char ToChar()
{
return (char)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override uint ToUInt32()
{
return (uint)_value;
}
public override ulong ToUInt64()
{
return (ulong)_value;
}
public override float ToSingle()
{
return (float)_value;
}
public override double ToDouble()
{
return _value;
}
public override IntPtr ToIntPtr()
{
return new IntPtr(IntPtr.Size == 4 ? (int)_value : (long)_value);
}
public override UIntPtr ToUIntPtr()
{
return new UIntPtr(IntPtr.Size == 4 ? (uint)_value : (ulong)_value);
}
public override object Conv_ovf(Type type, bool un)
{
if (type == typeof(IntPtr))
return new IntPtr(checked((long)_value));
if (type == typeof(UIntPtr))
return new UIntPtr(checked((ulong)_value));
switch (System.Type.GetTypeCode(type))
{
case TypeCode.SByte:
return un ? checked((sbyte)(uint)_value) : checked((sbyte)_value);
case TypeCode.Int16:
return un ? checked((short)(uint)_value) : checked((short)_value);
case TypeCode.Int32:
return checked((int)_value);
case TypeCode.Int64:
return checked((long)_value);
case TypeCode.Byte:
return checked((byte)_value);
case TypeCode.UInt16:
return checked((ushort)_value);
case TypeCode.UInt32:
return checked((uint)_value);
case TypeCode.UInt64:
return checked((ulong)_value);
case TypeCode.Double:
return _value;
}
throw new ArgumentException();
}
}
sealed class StringVariant : StackableVariant
{
private string _value;
public StringVariant(string value)
{
_value = value;
}
public override Type Type()
{
return typeof(string);
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Object;
}
public override BaseVariant Clone()
{
return new StringVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = (value != null) ? System.Convert.ToString(value) : null;
}
public override bool ToBoolean()
{
return _value != null;
}
public override string ToString()
{
return _value;
}
}
sealed class ShortVariant : BaseVariant
{
private short _value;
public ShortVariant(short value)
{
_value = value;
}
public override Type Type()
{
return typeof(short);
}
public override BaseVariant Clone()
{
return new ShortVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToInt16(value);
}
public override StackableVariant ToStack()
{
return new IntVariant(ToInt32());
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override short ToInt16()
{
return _value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override int ToInt32()
{
return _value;
}
public override uint ToUInt32()
{
return (uint)_value;
}
}
sealed class UshortVariant : BaseVariant
{
private ushort _value;
public UshortVariant(ushort value)
{
_value = value;
}
public override Type Type()
{
return typeof(ushort);
}
public override BaseVariant Clone()
{
return new UshortVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToUInt16(value);
}
public override StackableVariant ToStack()
{
return new IntVariant(ToInt32());
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override ushort ToUInt16()
{
return _value;
}
public override int ToInt32()
{
return _value;
}
public override uint ToUInt32()
{
return _value;
}
}
sealed class BoolVariant : BaseVariant
{
private bool _value;
public BoolVariant(bool value)
{
_value = value;
}
public override Type Type()
{
return typeof(bool);
}
public override BaseVariant Clone()
{
return new BoolVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToBoolean(value);
}
public override StackableVariant ToStack()
{
return new IntVariant(ToInt32());
}
public override int ToInt32()
{
return _value ? 1 : 0;
}
}
sealed class CharVariant : BaseVariant
{
private char _value;
public CharVariant(char value)
{
_value = value;
}
public override Type Type()
{
return typeof(char);
}
public override BaseVariant Clone()
{
return new CharVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToChar(value);
}
public override StackableVariant ToStack()
{
return new IntVariant(ToInt32());
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override ushort ToUInt16()
{
return _value;
}
public override int ToInt32()
{
return _value;
}
public override uint ToUInt32()
{
return _value;
}
}
sealed class ByteVariant : BaseVariant
{
private byte _value;
public ByteVariant(byte value)
{
_value = value;
}
public override Type Type()
{
return typeof(byte);
}
public override BaseVariant Clone()
{
return new ByteVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToByte(value);
}
public override StackableVariant ToStack()
{
return new IntVariant(ToInt32());
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override byte ToByte()
{
return _value;
}
public override short ToInt16()
{
return _value;
}
public override ushort ToUInt16()
{
return _value;
}
public override int ToInt32()
{
return _value;
}
public override uint ToUInt32()
{
return _value;
}
}
sealed class SbyteVariant : BaseVariant
{
private sbyte _value;
public SbyteVariant(sbyte value)
{
_value = value;
}
public override Type Type()
{
return typeof(sbyte);
}
public override BaseVariant Clone()
{
return new SbyteVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToSByte(value);
}
public override StackableVariant ToStack()
{
return new IntVariant(ToInt32());
}
public override sbyte ToSByte()
{
return _value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override short ToInt16()
{
return _value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override int ToInt32()
{
return _value;
}
public override uint ToUInt32()
{
return (uint)_value;
}
}
sealed class UintVariant : BaseVariant
{
private uint _value;
public UintVariant(uint value)
{
_value = value;
}
public override Type Type()
{
return typeof(uint);
}
public override BaseVariant Clone()
{
return new UintVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToUInt32(value);
}
public override StackableVariant ToStack()
{
return new IntVariant(ToInt32());
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override int ToInt32()
{
return (int)_value;
}
public override uint ToUInt32()
{
return _value;
}
}
sealed class UlongVariant : BaseVariant
{
private ulong _value;
public UlongVariant(ulong value)
{
_value = value;
}
public override Type Type()
{
return typeof(ulong);
}
public override BaseVariant Clone()
{
return new UlongVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = System.Convert.ToUInt64(value);
}
public override StackableVariant ToStack()
{
return new LongVariant(ToInt64());
}
public override sbyte ToSByte()
{
return (sbyte)_value;
}
public override byte ToByte()
{
return (byte)_value;
}
public override short ToInt16()
{
return (short)_value;
}
public override ushort ToUInt16()
{
return (ushort)_value;
}
public override int ToInt32()
{
return (int)_value;
}
public override uint ToUInt32()
{
return (uint)_value;
}
public override long ToInt64()
{
return (long)_value;
}
public override ulong ToUInt64()
{
return _value;
}
}
sealed class ObjectVariant : StackableVariant
{
private object _value;
public ObjectVariant(object value)
{
_value = value;
}
public override Type Type()
{
return typeof(object);
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Object;
}
public override BaseVariant Clone()
{
return new ObjectVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = value;
}
public override bool ToBoolean()
{
return _value != null;
}
}
sealed class PointerVariant : StackableVariant
{
private object _value;
private Type _type;
private BaseVariant _variant;
public PointerVariant(object value, Type type)
{
_value = value;
_type = type;
_variant = ToVariant(value);
}
private static BaseVariant ToVariant(object value)
{
unsafe
{
IntPtr ptr = value == null ? IntPtr.Zero : new IntPtr(Pointer.Unbox(value));
if (IntPtr.Size == 4)
return new IntVariant(ptr.ToInt32());
else
return new LongVariant(ptr.ToInt64());
}
}
public override Type Type()
{
return _type;
}
public override TypeCode CalcTypeCode()
{
return (IntPtr.Size == 4) ? TypeCode.UInt32 : TypeCode.UInt64;
}
public override BaseVariant Clone()
{
return new PointerVariant(_value, _type);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = value;
_variant = ToVariant(value);
}
public override bool ToBoolean()
{
return _value != null;
}
public override sbyte ToSByte()
{
return _variant.ToSByte();
}
public override short ToInt16()
{
return _variant.ToInt16();
}
public override int ToInt32()
{
return _variant.ToInt32();
}
public override long ToInt64()
{
return _variant.ToInt64();
}
public override byte ToByte()
{
return _variant.ToByte();
}
public override ushort ToUInt16()
{
return _variant.ToUInt16();
}
public override uint ToUInt32()
{
return _variant.ToUInt32();
}
public override ulong ToUInt64()
{
return _variant.ToUInt64();
}
public override float ToSingle()
{
return _variant.ToSingle();
}
public override double ToDouble()
{
return _variant.ToDouble();
}
public override IntPtr ToIntPtr()
{
return _variant.ToIntPtr();
}
public override UIntPtr ToUIntPtr()
{
return _variant.ToUIntPtr();
}
public override unsafe void* ToPointer()
{
return Pointer.Unbox(_value);
}
public override object Conv_ovf(Type type, bool un)
{
return _variant.Conv_ovf(type, un);
}
}
sealed class ValueTypeVariant : StackableVariant
{
private object _value;
public ValueTypeVariant(object value)
{
if (value != null && !(value is ValueType))
throw new ArgumentException();
_value = value;
}
public override Type Type()
{
return typeof(ValueType);
}
public override BaseVariant Clone()
{
object value;
if (_value == null)
{
value = null;
}
else
{
var type = _value.GetType();
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
value = Activator.CreateInstance(type);
foreach (var field in fields)
{
field.SetValue(value, field.GetValue(_value));
}
}
return new ValueTypeVariant(value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
if (value != null && !(value is ValueType))
throw new ArgumentException();
_value = value;
}
}
sealed class ArrayVariant : StackableVariant
{
private Array _value;
public ArrayVariant(Array value)
{
_value = value;
}
public override Type Type()
{
return typeof(Array);
}
public override BaseVariant Clone()
{
return new ArrayVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = (Array)value;
}
public override bool ToBoolean()
{
return _value != null;
}
}
abstract class BaseReferenceVariant : StackableVariant
{
public override bool IsReference()
{
return true;
}
}
sealed class ReferenceVariant : BaseReferenceVariant
{
private BaseVariant _variable;
public ReferenceVariant(BaseVariant variable)
{
_variable = variable;
}
public override Type Type()
{
return _variable.Type();
}
public override BaseVariant Clone()
{
return new ReferenceVariant(_variable);
}
public override object Value()
{
return _variable.Value();
}
public override void SetValue(object value)
{
_variable.SetValue(value);
}
public override bool ToBoolean()
{
return _variable != null;
}
public override void SetFieldValue(FieldInfo field, object value)
{
_variable.SetFieldValue(field, value);
}
}
sealed class NullReferenceVariant : BaseReferenceVariant
{
private Type _type;
public NullReferenceVariant(Type type)
{
_type = type;
}
public override Type Type()
{
return _type;
}
public override BaseVariant Clone()
{
return new NullReferenceVariant(_type);
}
public override object Value()
{
throw new InvalidOperationException();
}
public override void SetValue(object value)
{
throw new InvalidOperationException();
}
public override void SetFieldValue(FieldInfo field, object value)
{
throw new InvalidOperationException();
}
}
sealed class ArgReferenceVariant : BaseReferenceVariant
{
private BaseVariant _variable;
private BaseVariant _arg;
public ArgReferenceVariant(BaseVariant variable, BaseVariant arg)
{
_variable = variable;
_arg = arg;
}
public override Type Type()
{
return _variable.Type();
}
public override BaseVariant Clone()
{
return new ArgReferenceVariant(_variable, _arg);
}
public override object Value()
{
return _variable.Value();
}
public override void SetValue(object value)
{
_variable.SetValue(value);
_arg.SetValue(_variable.Value());
}
public override bool ToBoolean()
{
return _variable != null;
}
}
sealed class FieldReferenceVariant : BaseReferenceVariant
{
private FieldInfo _field;
private BaseVariant _variable;
public FieldReferenceVariant(FieldInfo field, BaseVariant variable)
{
_field = field;
_variable = variable;
}
public override Type Type()
{
return _field.FieldType;
}
public override BaseVariant Clone()
{
return new FieldReferenceVariant(_field, _variable);
}
public override object Value()
{
return _field.GetValue(_variable.Value());
}
public override void SetValue(object value)
{
_variable.SetFieldValue(_field, value);
}
}
sealed class ArrayElementVariant : BaseReferenceVariant
{
private Array _value;
private int _index;
public ArrayElementVariant(Array value, int index)
{
_value = value;
_index = index;
}
public override Type Type()
{
return _value.GetType().GetElementType();
}
public override BaseVariant Clone()
{
return new ArrayElementVariant(_value, _index);
}
public override object Value()
{
return _value.GetValue(_index);
}
public override void SetValue(object value)
{
switch (System.Type.GetTypeCode(_value.GetType().GetElementType()))
{
case TypeCode.SByte:
value = System.Convert.ToSByte(value);
break;
case TypeCode.Byte:
value = System.Convert.ToByte(value);
break;
case TypeCode.Char:
value = System.Convert.ToChar(value);
break;
case TypeCode.Int16:
value = System.Convert.ToInt16(value);
break;
case TypeCode.UInt16:
value = System.Convert.ToUInt16(value);
break;
case TypeCode.Int32:
value = System.Convert.ToInt32(value);
break;
case TypeCode.UInt32:
value = System.Convert.ToUInt32(value);
break;
case TypeCode.Int64:
value = System.Convert.ToInt64(value);
break;
case TypeCode.UInt64:
value = System.Convert.ToUInt64(value);
break;
}
_value.SetValue(value, _index);
}
public override void SetFieldValue(FieldInfo field, object value)
{
var obj = Value();
field.SetValue(obj, value);
if (obj is ValueType)
SetValue(obj);
}
public override UIntPtr ToUIntPtr()
{
var dynamicMethod = new DynamicMethod("", typeof(UIntPtr), new Type[] { _value.GetType(), typeof(int) }, typeof(VirtualMachine).Module, true);
var gen = dynamicMethod.GetILGenerator();
gen.Emit(System.Reflection.Emit.OpCodes.Ldarg, 0);
gen.Emit(System.Reflection.Emit.OpCodes.Ldarg, 1);
gen.Emit(System.Reflection.Emit.OpCodes.Ldelema, _value.GetType().GetElementType());
gen.Emit(System.Reflection.Emit.OpCodes.Conv_U);
gen.Emit(System.Reflection.Emit.OpCodes.Ret);
return (UIntPtr)dynamicMethod.Invoke(null, new object[] { _value, _index });
}
}
sealed class MethodVariant : StackableVariant
{
private MethodBase _value;
public MethodVariant(MethodBase value)
{
_value = value;
}
public override Type Type()
{
return typeof(MethodBase);
}
public override BaseVariant Clone()
{
return new MethodVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = (MethodBase)value;
}
public override bool ToBoolean()
{
return _value != null;
}
public override IntPtr ToIntPtr()
{
return _value.MethodHandle.GetFunctionPointer();
}
}
sealed class IntPtrVariant : StackableVariant
{
IntPtr _value;
private BaseVariant _variant;
public IntPtrVariant(IntPtr value)
{
_value = value;
_variant = ToVariant(_value);
}
private static BaseVariant ToVariant(IntPtr value)
{
if (IntPtr.Size == 4)
return new IntVariant(value.ToInt32());
else
return new LongVariant(value.ToInt64());
}
public override Type Type()
{
return typeof(IntPtr);
}
public override TypeCode CalcTypeCode()
{
return _variant.CalcTypeCode();
}
public override BaseVariant Clone()
{
return new IntPtrVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = (IntPtr)value;
_variant = ToVariant(_value);
}
public override bool ToBoolean()
{
return _value != IntPtr.Zero;
}
public override sbyte ToSByte()
{
return _variant.ToSByte();
}
public override short ToInt16()
{
return _variant.ToInt16();
}
public override int ToInt32()
{
return _variant.ToInt32();
}
public override long ToInt64()
{
return _variant.ToInt64();
}
public override byte ToByte()
{
return _variant.ToByte();
}
public override ushort ToUInt16()
{
return _variant.ToUInt16();
}
public override uint ToUInt32()
{
return _variant.ToUInt32();
}
public override ulong ToUInt64()
{
return _variant.ToUInt64();
}
public override float ToSingle()
{
return _variant.ToSingle();
}
public override double ToDouble()
{
return _variant.ToDouble();
}
public override IntPtr ToIntPtr()
{
return _value;
}
public override UIntPtr ToUIntPtr()
{
return _variant.ToUIntPtr();
}
public override unsafe void* ToPointer()
{
return _value.ToPointer();
}
public override object Conv_ovf(Type type, bool un)
{
return _variant.Conv_ovf(type, un);
}
}
sealed class UIntPtrVariant : StackableVariant
{
private UIntPtr _value;
private BaseVariant _variant;
public UIntPtrVariant(UIntPtr value)
{
_value = value;
_variant = ToVariant(_value);
}
private static BaseVariant ToVariant(UIntPtr value)
{
if (IntPtr.Size == 4)
return new IntVariant((int)value.ToUInt32());
else
return new LongVariant((long)value.ToUInt64());
}
public override Type Type()
{
return typeof(UIntPtr);
}
public override TypeCode CalcTypeCode()
{
return _variant.CalcTypeCode();
}
public override BaseVariant Clone()
{
return new UIntPtrVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
_value = (UIntPtr)value;
_variant = ToVariant(_value);
}
public override bool ToBoolean()
{
return _value != UIntPtr.Zero;
}
public override sbyte ToSByte()
{
return _variant.ToSByte();
}
public override short ToInt16()
{
return _variant.ToInt16();
}
public override int ToInt32()
{
return _variant.ToInt32();
}
public override long ToInt64()
{
return _variant.ToInt64();
}
public override byte ToByte()
{
return _variant.ToByte();
}
public override ushort ToUInt16()
{
return _variant.ToUInt16();
}
public override uint ToUInt32()
{
return _variant.ToUInt32();
}
public override ulong ToUInt64()
{
return _variant.ToUInt64();
}
public override float ToSingle()
{
return _variant.ToSingle();
}
public override double ToDouble()
{
return _variant.ToDouble();
}
public override IntPtr ToIntPtr()
{
return _variant.ToIntPtr();
}
public override UIntPtr ToUIntPtr()
{
return _value;
}
public override unsafe void* ToPointer()
{
return _value.ToPointer();
}
public override object Conv_ovf(Type type, bool un)
{
return _variant.Conv_ovf(type, un);
}
}
sealed class EnumVariant : StackableVariant
{
private Enum _value;
private BaseVariant _variant;
public EnumVariant(Enum value)
{
if (value == null)
throw new ArgumentException();
_value = value;
_variant = ToVariant(_value);
}
private static BaseVariant ToVariant(Enum value)
{
switch (value.GetTypeCode())
{
case TypeCode.Byte:
case TypeCode.UInt16:
case TypeCode.UInt32:
return new IntVariant((int)System.Convert.ToUInt32(value));
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
return new IntVariant(System.Convert.ToInt32(value));
case TypeCode.UInt64:
return new LongVariant((long)System.Convert.ToUInt64(value));
case TypeCode.Int64:
return new LongVariant(System.Convert.ToInt64(value));
default:
throw new InvalidOperationException();
}
}
public override BaseVariant ToUnsigned()
{
return _variant.ToUnsigned();
}
public override Type Type()
{
return _value.GetType();
}
public override TypeCode CalcTypeCode()
{
return _variant.CalcTypeCode();
}
public override BaseVariant Clone()
{
return new EnumVariant(_value);
}
public override object Value()
{
return _value;
}
public override void SetValue(object value)
{
if (value == null)
throw new ArgumentException();
_value = (Enum)value;
_variant = ToVariant(_value);
}
public override byte ToByte()
{
return _variant.ToByte();
}
public override sbyte ToSByte()
{
return _variant.ToSByte();
}
public override short ToInt16()
{
return _variant.ToInt16();
}
public override ushort ToUInt16()
{
return _variant.ToUInt16();
}
public override int ToInt32()
{
return _variant.ToInt32();
}
public override uint ToUInt32()
{
return _variant.ToUInt32();
}
public override long ToInt64()
{
return _variant.ToInt64();
}
public override ulong ToUInt64()
{
return _variant.ToUInt64();
}
public override float ToSingle()
{
return _variant.ToSingle();
}
public override double ToDouble()
{
return _variant.ToDouble();
}
public override IntPtr ToIntPtr()
{
return new IntPtr(IntPtr.Size == 4 ? ToInt32() : ToInt64());
}
public override UIntPtr ToUIntPtr()
{
return new UIntPtr(IntPtr.Size == 4 ? ToUInt32() : ToUInt64());
}
public override object Conv_ovf(Type type, bool un)
{
return _variant.Conv_ovf(type, un);
}
}
sealed class PointerReference : BaseReferenceVariant
{
private IntPtr _value;
private Type _type;
public PointerReference(IntPtr value, Type type)
{
_value = value;
_type = type;
}
public override Type Type()
{
return typeof(Pointer);
}
public override TypeCode CalcTypeCode()
{
return TypeCode.Empty;
}
public override BaseVariant Clone()
{
return new PointerReference(_value, _type);
}
public override object Value()
{
if (_type.IsValueType)
return Marshal.PtrToStructure(_value, _type);
throw new InvalidOperationException();
}
public override void SetValue(object value)
{
if (value == null)
throw new ArgumentException();
if (_type.IsValueType)
{
Marshal.StructureToPtr(value, _value, false);
return;
}
switch (System.Type.GetTypeCode(value.GetType()))
{
case TypeCode.SByte:
Marshal.WriteByte(_value, (byte)System.Convert.ToSByte(value));
break;
case TypeCode.Byte:
Marshal.WriteByte(_value, System.Convert.ToByte(value));
break;
case TypeCode.Char:
Marshal.WriteInt16(_value, System.Convert.ToChar(value));
break;
case TypeCode.Int16:
Marshal.WriteInt16(_value, System.Convert.ToInt16(value));
break;
case TypeCode.UInt16:
Marshal.WriteInt16(_value, (short)System.Convert.ToUInt16(value));
break;
case TypeCode.Int32:
Marshal.WriteInt32(_value, System.Convert.ToInt32(value));
break;
case TypeCode.UInt32:
Marshal.WriteInt32(_value, (int)System.Convert.ToUInt32(value));
break;
case TypeCode.Int64:
Marshal.WriteInt64(_value, System.Convert.ToInt64(value));
break;
case TypeCode.UInt64:
Marshal.WriteInt64(_value, (long)System.Convert.ToUInt64(value));
break;
case TypeCode.Single:
Marshal.WriteInt32(_value, BitConverter.ToInt32(BitConverter.GetBytes(System.Convert.ToSingle(value)), 0));
break;
case TypeCode.Double:
Marshal.WriteInt64(_value, BitConverter.ToInt64(BitConverter.GetBytes(System.Convert.ToDouble(value)), 0));
break;
default:
throw new ArgumentException();
}
}
public override sbyte ToSByte()
{
return (sbyte)Marshal.ReadByte(_value);
}
public override short ToInt16()
{
return Marshal.ReadInt16(_value);
}
public override int ToInt32()
{
return Marshal.ReadInt32(_value);
}
public override long ToInt64()
{
return Marshal.ReadInt64(_value);
}
public override char ToChar()
{
return (char)Marshal.ReadInt16(_value);
}
public override byte ToByte()
{
return Marshal.ReadByte(_value);
}
public override ushort ToUInt16()
{
return (ushort)Marshal.ReadInt16(_value);
}
public override uint ToUInt32()
{
return (uint)Marshal.ReadInt32(_value);
}
public override ulong ToUInt64()
{
return (ulong)Marshal.ReadInt64(_value);
}
public override float ToSingle()
{
return BitConverter.ToSingle(BitConverter.GetBytes(Marshal.ReadInt32(_value)), 0);
}
public override double ToDouble()
{
return BitConverter.ToDouble(BitConverter.GetBytes(Marshal.ReadInt64(_value)), 0);
}
public override IntPtr ToIntPtr()
{
return new IntPtr(IntPtr.Size == 4 ? Marshal.ReadInt32(_value) : Marshal.ReadInt64(_value));
}
public override UIntPtr ToUIntPtr()
{
return new UIntPtr(IntPtr.Size == 4 ? (uint)Marshal.ReadInt32(_value) : (ulong)Marshal.ReadInt64(_value));
}
}
private sealed class CatchBlock
{
private byte _type;
private int _handler;
private int _filter;
public CatchBlock(byte type, int handler, int filter)
{
_type = type;
_handler = handler;
_filter = filter;
}
public byte Type()
{
return _type;
}
public int Handler()
{
return _handler;
}
public int Filter()
{
return _filter;
}
}
private sealed class TryBlock
{
private int _begin;
private int _end;
private List<CatchBlock> _catchBlocks = new List<CatchBlock>();
public TryBlock(int begin, int end)
{
_begin = begin;
_end = end;
}
public int Begin()
{
return _begin;
}
public int End()
{
return _end;
}
public int CompareTo(TryBlock compare)
{
if (compare == null)
return 1;
int res = _begin.CompareTo(compare.Begin());
if (res == 0)
res = compare.End().CompareTo(_end);
return res;
}
public void AddCatchBlock(byte type, int handler, int filter)
{
_catchBlocks.Add(new CatchBlock(type, handler, filter));
}
public List<CatchBlock> CatchBlocks()
{
return _catchBlocks;
}
}
internal delegate void Handler();
private readonly Dictionary<uint, Handler> _handlers = new Dictionary<uint, Handler>();
private readonly Module _module = typeof(VirtualMachine).Module;
private readonly long _instance;
private int _pos;
private Type _constrained;
private Stack<StackableVariant> _stack = new Stack<StackableVariant>();
private static readonly Dictionary<int, object> _cache = new Dictionary<int, object>();
private static readonly Dictionary<MethodBase, DynamicMethod> _dynamicMethodCache = new Dictionary<MethodBase, DynamicMethod>();
private List<BaseVariant> _args = new List<BaseVariant>();
private List<TryBlock> _tryBlocks = new List<TryBlock>();
private Stack<TryBlock> _tryStack = new Stack<TryBlock>();
private Stack<int> _finallyStack = new Stack<int>();
private Exception _exception;
private CatchBlock _filterBlock;
private List<IntPtr> _localloc = new List<IntPtr>();
public VirtualMachine()
{
_instance = Marshal.GetHINSTANCE(_module).ToInt64();
_handlers[(uint)OpCodes.icInitarg] = Initarg;
_handlers[(uint)OpCodes.icInitcatchblock] = Initcatchblock;
_handlers[(uint)OpCodes.icEntertry] = Entertry;
_handlers[(uint)OpCodes.icLdc_i4] = Ldc_i4;
_handlers[(uint)OpCodes.icLdc_i8] = Ldc_i8;
_handlers[(uint)OpCodes.icLdc_r4] = Ldc_r4;
_handlers[(uint)OpCodes.icLdc_r8] = Ldc_r8;
_handlers[(uint)OpCodes.icLdnull] = Ldnull;
_handlers[(uint)OpCodes.icLdstr] = Ldstr;
_handlers[(uint)OpCodes.icDup] = Dup;
_handlers[(uint)OpCodes.icAdd] = Add_;
_handlers[(uint)OpCodes.icAdd_ovf] = Add_ovf;
_handlers[(uint)OpCodes.icAdd_ovf_un] = Add_ovf_un;
_handlers[(uint)OpCodes.icSub] = Sub_;
_handlers[(uint)OpCodes.icSub_ovf] = Sub_ovf;
_handlers[(uint)OpCodes.icSub_ovf_un] = Sub_ovf_un;
_handlers[(uint)OpCodes.icMul] = Mul_;
_handlers[(uint)OpCodes.icMul_ovf] = Mul_ovf;
_handlers[(uint)OpCodes.icMul_ovf_un] = Mul_ovf_un;
_handlers[(uint)OpCodes.icDiv] = Div_;
_handlers[(uint)OpCodes.icDiv_un] = Div_un;
_handlers[(uint)OpCodes.icRem] = Rem_;
_handlers[(uint)OpCodes.icRem_un] = Rem_un;
_handlers[(uint)OpCodes.icAnd] = And_;
_handlers[(uint)OpCodes.icOr] = Or_;
_handlers[(uint)OpCodes.icXor] = Xor_;
_handlers[(uint)OpCodes.icNot] = Not_;
_handlers[(uint)OpCodes.icNeg] = Neg_;
_handlers[(uint)OpCodes.icShr] = Shr_;
_handlers[(uint)OpCodes.icShr_un] = Shr_un;
_handlers[(uint)OpCodes.icShl] = Shl_;
_handlers[(uint)OpCodes.icConv] = Conv;
_handlers[(uint)OpCodes.icConv_ovf] = Conv_ovf;
_handlers[(uint)OpCodes.icConv_ovf_un] = Conv_ovf_un;
_handlers[(uint)OpCodes.icSizeof] = Sizeof;
_handlers[(uint)OpCodes.icLdind_ref] = Ldind;
_handlers[(uint)OpCodes.icLdfld] = Ldfld;
_handlers[(uint)OpCodes.icLdflda] = Ldflda;
_handlers[(uint)OpCodes.icStfld] = Stfld;
_handlers[(uint)OpCodes.icStsfld] = Stsfld;
_handlers[(uint)OpCodes.icStind_ref] = Stind;
_handlers[(uint)OpCodes.icLdarg] = Ldarg;
_handlers[(uint)OpCodes.icLdarga] = Ldarga;
_handlers[(uint)OpCodes.icStarg] = Starg;
_handlers[(uint)OpCodes.icConstrained] = Constrained;
_handlers[(uint)OpCodes.icCall] = Call_;
_handlers[(uint)OpCodes.icCallvirt] = Callvirt;
_handlers[(uint)OpCodes.icCalli] = Calli;
_handlers[(uint)OpCodes.icCallvm] = Callvm_;
_handlers[(uint)OpCodes.icCallvmvirt] = Callvmvirt;
_handlers[(uint)OpCodes.icNewobj] = Newobj_;
_handlers[(uint)OpCodes.icInitobj] = Initobj;
_handlers[(uint)OpCodes.icCmp] = Cmp;
_handlers[(uint)OpCodes.icCmp_un] = Cmp_un;
_handlers[(uint)OpCodes.icNewarr] = Newarr;
_handlers[(uint)OpCodes.icStelem_ref] = Stelem;
_handlers[(uint)OpCodes.icLdelem_ref] = Ldelem;
_handlers[(uint)OpCodes.icLdlen] = Ldlen;
_handlers[(uint)OpCodes.icLdelema] = Ldelema;
_handlers[(uint)OpCodes.icLdftn] = Ldftn;
_handlers[(uint)OpCodes.icLdvirtftn] = Ldvirtftn;
_handlers[(uint)OpCodes.icBr] = Br;
_handlers[(uint)OpCodes.icPop] = Pop_;
_handlers[(uint)OpCodes.icLeave] = Leave;
_handlers[(uint)OpCodes.icEndfinally] = Endfinally;
_handlers[(uint)OpCodes.icEndfilter] = Endfilter;
_handlers[(uint)OpCodes.icBox] = Box;
_handlers[(uint)OpCodes.icUnbox] = Unbox;
_handlers[(uint)OpCodes.icUnbox_any] = Unbox_any;
_handlers[(uint)OpCodes.icLdmem_i4] = Ldmem_i4;
_handlers[(uint)OpCodes.icLdtoken] = Ldtoken;
_handlers[(uint)OpCodes.icThrow] = Throw;
_handlers[(uint)OpCodes.icRethrow] = Rethrow;
_handlers[(uint)OpCodes.icCastclass] = Castclass;
_handlers[(uint)OpCodes.icIsinst] = Isinst;
_handlers[(uint)OpCodes.icCkfinite] = Ckfinite;
_handlers[(uint)OpCodes.icLocalloc] = Localloc;
}
private void Push(BaseVariant value)
{
_stack.Push(value.ToStack());
}
private BaseVariant Pop()
{
return _stack.Pop();
}
private BaseVariant Peek()
{
return _stack.Peek();
}
private byte ReadByte()
{
byte res = Marshal.ReadByte(new IntPtr(_instance + _pos));
_pos += sizeof(byte);
return res;
}
private short ReadInt16()
{
short res = Marshal.ReadInt16(new IntPtr(_instance + _pos));
_pos += sizeof(short);
return res;
}
private int ReadInt32()
{
int res = Marshal.ReadInt32(new IntPtr(_instance + _pos));
_pos += sizeof(int);
return res;
}
private long ReadInt64()
{
long res = Marshal.ReadInt64(new IntPtr(_instance + _pos));
_pos += sizeof(long);
return res;
}
private float ReadSingle()
{
return BitConverter.ToSingle(BitConverter.GetBytes(ReadInt32()), 0);
}
private double ReadDouble()
{
return BitConverter.ToDouble(BitConverter.GetBytes(ReadInt64()), 0);
}
private void Initcatchblock()
{
var type = ReadByte();
var tryBegin = ReadInt32();
var tryEnd = ReadInt32();
var handler = ReadInt32();
var filter = ReadInt32();
TryBlock tryBlock = null;
for (var i = 0; i < _tryBlocks.Count; i++)
{
var current = _tryBlocks[i];
if (current.Begin() == tryBegin && current.End() == tryEnd)
{
tryBlock = current;
break;
}
}
if (tryBlock == null)
{
bool isInserted = false;
tryBlock = new TryBlock(tryBegin, tryEnd);
for (var i = 0; i < _tryBlocks.Count; i++)
{
var current = _tryBlocks[i];
if (tryBlock.CompareTo(current) < 0)
{
_tryBlocks.Insert(i, tryBlock);
isInserted = true;
break;
}
}
if (!isInserted)
_tryBlocks.Add(tryBlock);
}
tryBlock.AddCatchBlock(type, handler, filter);
}
private TypeCode CalcTypeCode(BaseVariant v1, BaseVariant v2)
{
var type1 = v1.CalcTypeCode();
var type2 = v2.CalcTypeCode();
if (type1 == TypeCode.Empty || type1 == TypeCode.Object || type2 == TypeCode.Empty || type2 == TypeCode.Object)
return TypeCode.Empty;
// UInt32/UInt64 used for pointers
if (type1 == TypeCode.UInt32)
return (type2 == TypeCode.Int32) ? type1 : TypeCode.Empty;
if (type2 == TypeCode.UInt32)
return (type1 == TypeCode.Int32) ? type2 : TypeCode.Empty;
if (type1 == TypeCode.UInt64)
return (type2 == TypeCode.Int32 || type2 == TypeCode.Int64) ? type1 : TypeCode.Empty;
if (type2 == TypeCode.UInt64)
return (type1 == TypeCode.Int32 || type1 == TypeCode.Int64) ? type1 : TypeCode.Empty;
if (type1 == TypeCode.Double || type2 == TypeCode.Double)
return TypeCode.Double;
if (type1 == TypeCode.Single || type2 == TypeCode.Single)
return TypeCode.Single;
if (type1 == TypeCode.Int64 || type2 == TypeCode.Int64)
return TypeCode.Int64;
return TypeCode.Int32;
}
private BaseVariant Add(BaseVariant v1, BaseVariant v2, bool ovf, bool un)
{
var type = CalcTypeCode(v1, v2);
switch (type)
{
case TypeCode.Int32:
{
int value;
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToUInt32();
value = ovf ? (int)checked(value1 + value2) : (int)(value1 + value2);
}
else
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
value = ovf ? checked(value1 + value2) : (value1 + value2);
}
return new IntVariant(value);
}
case TypeCode.Int64:
{
long value;
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToUInt64();
value = ovf ? (long)checked(value1 + value2) : (long)(value1 + value2);
}
else
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
value = ovf ? checked(value1 + value2) : (value1 + value2);
}
return new LongVariant(value);
}
case TypeCode.Single:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToSingle();
var value2 = (un ? v2.ToUnsigned() : v2).ToSingle();
return new SingleVariant(ovf ? checked(value1 + value2) : (value1 + value2));
}
case TypeCode.Double:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToDouble();
var value2 = (un ? v2.ToUnsigned() : v2).ToDouble();
return new DoubleVariant(ovf ? checked(value1 + value2) : (value1 + value2));
}
case TypeCode.UInt32:
{
int value;
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToUInt32();
value = ovf ? (int)checked(value1 + value2) : (int)(value1 + value2);
}
else
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
value = ovf ? checked(value1 + value2) : (value1 + value2);
}
PointerVariant v = v1.CalcTypeCode() == type ? (PointerVariant)v1 : (PointerVariant)v2;
unsafe
{
return new PointerVariant(Pointer.Box(new IntPtr(value).ToPointer(), v.Type()), v.Type());
}
}
case TypeCode.UInt64:
{
long value;
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToUInt64();
value = ovf ? (long)checked(value1 + value2) : (long)(value1 + value2);
}
else
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
value = ovf ? checked(value1 + value2) : (value1 + value2);
}
PointerVariant v = v1.CalcTypeCode() == type ? (PointerVariant)v1 : (PointerVariant)v2;
unsafe
{
return new PointerVariant(Pointer.Box(new IntPtr(value).ToPointer(), v.Type()), v.Type());
}
}
}
throw new InvalidOperationException();
}
private BaseVariant Sub(BaseVariant v1, BaseVariant v2, bool ovf, bool un)
{
var type = CalcTypeCode(v1, v2);
switch (type)
{
case TypeCode.Int32:
{
int value;
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToUInt32();
value = ovf ? (int)checked(value1 - value2) : (int)(value1 - value2);
}
else
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
value = ovf ? checked(value1 - value2) : (value1 - value2);
}
return new IntVariant(value);
}
case TypeCode.Int64:
{
long value;
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToUInt64();
value = ovf ? (long)checked(value1 - value2) : (long)(value1 - value2);
}
else
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
value = ovf ? checked(value1 - value2) : (value1 - value2);
}
return new LongVariant(value);
}
case TypeCode.Single:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToSingle();
var value2 = (un ? v2.ToUnsigned() : v2).ToSingle();
return new SingleVariant(ovf ? checked(value1 - value2) : (value1 - value2));
}
case TypeCode.Double:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToDouble();
var value2 = (un ? v2.ToUnsigned() : v2).ToDouble();
return new DoubleVariant(ovf ? checked(value1 - value2) : (value1 - value2));
}
case TypeCode.UInt32:
{
int value;
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToUInt32();
value = ovf ? (int)checked(value1 - value2) : (int)(value1 - value2);
}
else
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
value = ovf ? checked(value1 - value2) : (value1 - value2);
}
PointerVariant v = v1.CalcTypeCode() == type ? (PointerVariant)v1 : (PointerVariant)v2;
unsafe
{
return new PointerVariant(Pointer.Box(new IntPtr(value).ToPointer(), v.Type()), v.Type());
}
}
case TypeCode.UInt64:
{
long value;
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToUInt64();
value = ovf ? (long)checked(value1 - value2) : (long)(value1 - value2);
}
else
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
value = ovf ? checked(value1 - value2) : (value1 - value2);
}
PointerVariant v = v1.CalcTypeCode() == type ? (PointerVariant)v1 : (PointerVariant)v2;
unsafe
{
return new PointerVariant(Pointer.Box(new IntPtr(value).ToPointer(), v.Type()), v.Type());
}
}
}
throw new InvalidOperationException();
}
private BaseVariant Mul(BaseVariant v1, BaseVariant v2, bool ovf, bool un)
{
var type = CalcTypeCode(v1, v2);
switch (type)
{
case TypeCode.Int32:
{
int value;
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToUInt32();
value = ovf ? (int)checked(value1 * value2) : (int)(value1 * value2);
}
else
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
value = ovf ? checked(value1 * value2) : (value1 * value2);
}
return new IntVariant(value);
}
case TypeCode.Int64:
{
long value;
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToUInt64();
value = ovf ? (long)checked(value1 * value2) : (long)(value1 * value2);
}
else
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
value = ovf ? checked(value1 * value2) : (value1 * value2);
}
return new LongVariant(value);
}
case TypeCode.Single:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToSingle();
var value2 = (un ? v2.ToUnsigned() : v2).ToSingle();
return new DoubleVariant(ovf ? checked(value1 * value2) : (value1 * value2));
}
case TypeCode.Double:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToDouble();
var value2 = (un ? v2.ToUnsigned() : v2).ToDouble();
return new DoubleVariant(ovf ? checked(value1 * value2) : (value1 * value2));
}
}
throw new InvalidOperationException();
}
private BaseVariant Div(BaseVariant v1, BaseVariant v2, bool un)
{
var type = CalcTypeCode(v1, v2);
switch (type)
{
case TypeCode.Int32:
{
int value;
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToUInt32();
value = (int)(value1 / value2);
}
else
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
value = value1 / value2;
}
return new IntVariant(value);
}
case TypeCode.Int64:
{
long value;
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToUInt64();
value = (long)(value1 / value2);
}
else
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
value = value1 / value2;
}
return new LongVariant(value);
}
case TypeCode.Single:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToSingle();
var value2 = (un ? v2.ToUnsigned() : v2).ToSingle();
return new SingleVariant(value1 / value2);
}
case TypeCode.Double:
{
var value1 = (un ? v1.ToUnsigned() : v1).ToDouble();
var value2 = (un ? v2.ToUnsigned() : v2).ToDouble();
return new DoubleVariant(value1 / value2);
}
}
throw new InvalidOperationException();
}
private BaseVariant Rem(BaseVariant v1, BaseVariant v2, bool un)
{
var type1 = v1.CalcTypeCode();
switch (type1)
{
case TypeCode.Int32:
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToUInt32();
return new IntVariant((int)(value1 % value2));
} else {
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
return new IntVariant(value1 % value2);
}
case TypeCode.Int64:
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToUInt64();
return new LongVariant((long)(value1 % value2));
} else {
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
return new LongVariant(value1 % value2);
}
}
throw new InvalidOperationException();
}
private BaseVariant Xor(BaseVariant v1, BaseVariant v2)
{
var type = CalcTypeCode(v1, v2);
switch (type)
{
case TypeCode.Int32:
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
return new IntVariant(value1 ^ value2);
}
case TypeCode.Int64:
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
return new LongVariant(value1 ^ value2);
}
case TypeCode.Single:
return new SingleVariant((IntPtr.Size == 4) ? float.NaN : (float)0);
case TypeCode.Double:
return new DoubleVariant((IntPtr.Size == 4) ? Double.NaN : (double)0);
}
throw new InvalidOperationException();
}
private BaseVariant Or(BaseVariant v1, BaseVariant v2)
{
var type = CalcTypeCode(v1, v2);
switch (type)
{
case TypeCode.Int32:
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
return new IntVariant(value1 | value2);
}
case TypeCode.Int64:
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
return new LongVariant(value1 | value2);
}
case TypeCode.Single:
return new SingleVariant((IntPtr.Size == 4) ? float.NaN : (float)0);
case TypeCode.Double:
return new DoubleVariant((IntPtr.Size == 4) ? Double.NaN : (double)0);
}
throw new InvalidOperationException();
}
private BaseVariant And(BaseVariant v1, BaseVariant v2)
{
var type = CalcTypeCode(v1, v2);
switch (type)
{
case TypeCode.Int32:
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
return new IntVariant(value1 & value2);
}
case TypeCode.Int64:
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt64();
return new LongVariant(value1 & value2);
}
case TypeCode.Single:
return new SingleVariant((IntPtr.Size == 4) ? float.NaN : (float)0);
case TypeCode.Double:
return new DoubleVariant((IntPtr.Size == 4) ? Double.NaN : (double)0);
}
throw new InvalidOperationException();
}
private int Compare(BaseVariant v1, BaseVariant v2, bool un, int def)
{
var res = def;
var type1 = v1.CalcTypeCode();
var type2 = v2.CalcTypeCode();
if (type1 == TypeCode.Object || type2 == TypeCode.Object)
{
var obj1 = v1.Value();
var obj2 = v2.Value();
if (obj1 == obj2)
return 0;
return (obj2 == null) ? 1 : -1;
}
else if (type1 == TypeCode.Double || type2 == TypeCode.Double)
res = v1.ToDouble().CompareTo(v2.ToDouble());
else if (type1 == TypeCode.Single || type2 == TypeCode.Single)
res = v1.ToSingle().CompareTo(v2.ToSingle());
else if (type1 == TypeCode.Int64 || type2 == TypeCode.Int64)
res = un ? v1.ToUInt64().CompareTo(v2.ToUInt64()) : v1.ToInt64().CompareTo(v2.ToInt64());
else if (type1 == TypeCode.Int32 || type2 == TypeCode.Int32)
res = un ? v1.ToUInt32().CompareTo(v2.ToUInt32()) : v1.ToInt32().CompareTo(v2.ToInt32());
if (res < 0)
res = -1;
else if (res > 0)
res = 1;
return res;
}
private BaseVariant Not(BaseVariant v)
{
switch (v.CalcTypeCode())
{
case TypeCode.Int32:
return new IntVariant(~v.ToInt32());
case TypeCode.Int64:
return new LongVariant(~v.ToInt64());
}
throw new InvalidOperationException();
}
private BaseVariant Neg(BaseVariant v)
{
switch (v.CalcTypeCode())
{
case TypeCode.Int32:
return new IntVariant(-v.ToInt32());
case TypeCode.Int64:
return new LongVariant(-v.ToInt64());
case TypeCode.Single:
return new SingleVariant(-v.ToSingle());
case TypeCode.Double:
return new DoubleVariant(-v.ToDouble());
}
throw new InvalidOperationException();
}
private BaseVariant Shr(BaseVariant v1, BaseVariant v2, bool un)
{
var type = v1.CalcTypeCode();
switch (type)
{
case TypeCode.Int32:
if (un)
{
var value1 = v1.ToUInt32();
var value2 = v2.ToInt32();
return new IntVariant((int)(value1 >> value2));
} else {
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
return new IntVariant(value1 >> value2);
}
case TypeCode.Int64:
if (un)
{
var value1 = v1.ToUInt64();
var value2 = v2.ToInt32();
return new LongVariant((long)(value1 >> value2));
} else {
var value1 = v1.ToInt64();
var value2 = v2.ToInt32();
return new LongVariant(value1 >> value2);
}
}
throw new InvalidOperationException();
}
private BaseVariant Shl(BaseVariant v1, BaseVariant v2)
{
var type = v1.CalcTypeCode();
switch (type)
{
case TypeCode.Int32:
{
var value1 = v1.ToInt32();
var value2 = v2.ToInt32();
return new IntVariant(value1 << value2);
}
case TypeCode.Int64:
{
var value1 = v1.ToInt64();
var value2 = v2.ToInt32();
return new LongVariant(value1 << value2);
}
}
throw new InvalidOperationException();
}
private BaseVariant Convert(object obj, Type t)
{
BaseVariant v = obj as BaseVariant;
if (t.IsEnum)
{
if (v != null)
obj = v.Value();
if (obj != null && !(obj is Enum))
obj = Enum.ToObject(t, obj);
return new EnumVariant(obj == null ? (Enum)Activator.CreateInstance(t) : (Enum)obj);
}
switch (Type.GetTypeCode(t))
{
case TypeCode.Boolean:
return new BoolVariant(v != null ? v.ToBoolean() : System.Convert.ToBoolean(obj));
case TypeCode.Char:
return new CharVariant(v != null ? v.ToChar() : System.Convert.ToChar(obj));
case TypeCode.SByte:
return new SbyteVariant(v != null ? v.ToSByte() : System.Convert.ToSByte(obj));
case TypeCode.Byte:
return new ByteVariant(v != null ? v.ToByte() : System.Convert.ToByte(obj));
case TypeCode.Int16:
return new ShortVariant(v != null ? v.ToInt16() : System.Convert.ToInt16(obj));
case TypeCode.UInt16:
return new UshortVariant(v != null ? v.ToUInt16() : System.Convert.ToUInt16(obj));
case TypeCode.Int32:
return new IntVariant(v != null ? v.ToInt32() : System.Convert.ToInt32(obj));
case TypeCode.UInt32:
return new UintVariant(v != null ? v.ToUInt32() : System.Convert.ToUInt32(obj));
case TypeCode.Int64:
return new LongVariant(v != null ? v.ToInt64() : System.Convert.ToInt64(obj));
case TypeCode.UInt64:
return new UlongVariant(v != null ? v.ToUInt64() : System.Convert.ToUInt64(obj));
case TypeCode.Single:
return new SingleVariant(v != null ? v.ToSingle() : System.Convert.ToSingle(obj));
case TypeCode.Double:
return new DoubleVariant(v != null ? v.ToDouble() : System.Convert.ToDouble(obj));
case TypeCode.String:
return new StringVariant(v != null ? v.ToString() : (string)obj);
}
if (t == typeof(IntPtr))
{
if (v != null)
return new IntPtrVariant(v.ToIntPtr());
return new IntPtrVariant(obj != null ? (IntPtr)obj : IntPtr.Zero);
}
if (t == typeof(UIntPtr))
{
if (v != null)
return new UIntPtrVariant(v.ToUIntPtr());
return new UIntPtrVariant(obj != null ? (UIntPtr)obj : UIntPtr.Zero);
}
if (t.IsValueType)
{
if (v != null)
return new ValueTypeVariant(v.Value());
return new ValueTypeVariant(obj == null ? Activator.CreateInstance(t) : obj);
}
if (t.IsArray)
return new ArrayVariant(v != null ? (Array)v.Value() : (Array)obj);
if (t.IsPointer)
{
unsafe
{
if (v != null)
return new PointerVariant(Pointer.Box(v.ToPointer(), t), t);
return new PointerVariant(Pointer.Box(obj != null ? Pointer.Unbox(obj) : null, t), t);
}
}
return new ObjectVariant(v != null ? v.Value() : obj);
}
string GetString(int token)
{
lock (_cache)
{
object stored;
if (_cache.TryGetValue(token, out stored))
return (string)stored;
else
{
var str = _module.ResolveString(token);
_cache.Add(token, str);
return str;
}
}
}
private Type GetType(int token)
{
lock (_cache)
{
object stored;
if (_cache.TryGetValue(token, out stored))
return (Type)stored;
else
{
var type = _module.ResolveType(token);
_cache.Add(token, type);
return type;
}
}
}
private MethodBase GetMethod(int token)
{
lock (_cache)
{
object stored;
if (_cache.TryGetValue(token, out stored))
return (MethodBase)stored;
else
{
var method = _module.ResolveMethod(token);
_cache.Add(token, method);
return method;
}
}
}
private FieldInfo GetField(int token)
{
lock (_cache)
{
object stored;
if (_cache.TryGetValue(token, out stored))
return (FieldInfo)stored;
else
{
var field = _module.ResolveField(token);
_cache.Add(token, field);
return field;
}
}
}
private BaseVariant Newobj(MethodBase method)
{
var parameters = method.GetParameters();
var refs = new Dictionary<int, BaseVariant>();
var args = new object[parameters.Length];
for (var i = parameters.Length - 1; i >= 0; i--)
{
var v = Pop();
if (v.IsReference())
refs[i] = v;
args[i] = Convert(v, parameters[i].ParameterType).Value();
}
var res = ((ConstructorInfo)method).Invoke(args);
foreach (var r in refs)
{
r.Value.SetValue(args[r.Key]);
}
return Convert(res, method.DeclaringType);
}
private bool IsFilteredMethod(MethodBase method, object obj, ref object result, object[] args)
{
var t = method.DeclaringType;
if (t == null)
return false;
if (Nullable.GetUnderlyingType(t) != null)
{
if (string.Equals(method.Name, "get_HasValue", StringComparison.Ordinal))
{
result = (obj != null);
return true;
}
else if (string.Equals(method.Name, "get_Value", StringComparison.Ordinal))
{
if (obj == null)
throw new InvalidOperationException();
result = obj;
return true;
}
else if (method.Name.Equals("GetValueOrDefault", StringComparison.Ordinal))
{
if (obj == null)
obj = Activator.CreateInstance(Nullable.GetUnderlyingType(method.DeclaringType));
result = obj;
return true;
}
}
return false;
}
private BaseVariant Call(MethodBase method, bool virt)
{
BindingFlags invokeFlags;
#if NETCOREAPP
invokeFlags = BindingFlags.DoNotWrapExceptions;
#else
invokeFlags = BindingFlags.Default;
#endif
var info = method as MethodInfo;
var parameters = method.GetParameters();
var refs = new Dictionary<int, BaseVariant>();
var args = new object[parameters.Length];
BaseVariant v;
for (var i = parameters.Length - 1; i >= 0; i--)
{
v = Pop();
if (v.IsReference())
refs[i] = v;
args[i] = Convert(v, parameters[i].ParameterType).Value();
}
v = method.IsStatic ? null : Pop();
object obj = v?.Value() ?? null;
if (virt && obj == null)
throw new NullReferenceException();
object res = null;
if (method.IsConstructor && method.DeclaringType.IsValueType)
{
obj = Activator.CreateInstance(method.DeclaringType, invokeFlags, null, args, null);
if (v != null && v.IsReference())
v.SetValue(Convert(obj, method.DeclaringType).Value());
}
else if (!IsFilteredMethod(method, obj, ref res, args))
{
if (!virt && method.IsVirtual && !method.IsFinal)
{
DynamicMethod dynamicMethod;
var paramValues = new object[parameters.Length + 1];
paramValues[0] = obj;
for (var i = 0; i < parameters.Length; i++)
{
paramValues[i + 1] = args[i];
}
lock (_dynamicMethodCache)
{
if (!_dynamicMethodCache.TryGetValue(method, out dynamicMethod))
{
var paramTypes = new Type[paramValues.Length];
paramTypes[0] = method.DeclaringType;
for (var i = 0; i < parameters.Length; i++)
{
paramTypes[i + 1] = parameters[i].ParameterType;
}
dynamicMethod = new DynamicMethod("", info != null && info.ReturnType != typeof(void) ? info.ReturnType : null, paramTypes, typeof(VirtualMachine).Module, true);
var gen = dynamicMethod.GetILGenerator();
gen.Emit(v.IsReference() ? System.Reflection.Emit.OpCodes.Ldarga : System.Reflection.Emit.OpCodes.Ldarg, 0);
for (var i = 1; i < paramTypes.Length; i++)
{
gen.Emit(refs.ContainsKey(i - 1) ? System.Reflection.Emit.OpCodes.Ldarga : System.Reflection.Emit.OpCodes.Ldarg, i);
}
gen.Emit(System.Reflection.Emit.OpCodes.Call, info);
gen.Emit(System.Reflection.Emit.OpCodes.Ret);
_dynamicMethodCache[method] = dynamicMethod;
}
}
res = dynamicMethod.Invoke(null, invokeFlags, null, paramValues, null);
foreach (var r in refs)
{
r.Value.SetValue(paramValues[r.Key + 1]);
}
refs.Clear();
}
else
{
res = method.Invoke(obj, invokeFlags, null, args, null);
}
}
foreach (var r in refs)
{
r.Value.SetValue(args[r.Key]);
}
return (info != null && info.ReturnType != typeof(void)) ? Convert(res, info.ReturnType) : null;
}
private BaseVariant Callvm(int pos, bool virt)
{
var oldPos = _pos;
_pos = pos;
var parameterCount = (ushort)ReadInt16();
var refs = new Dictionary<int, BaseVariant>();
object[] args = null;
if (parameterCount > 0)
{
args = new object[parameterCount];
for (var i = parameterCount - 1; i >= 0; i--)
{
BaseVariant v = Pop();
if (v.IsReference())
refs[i] = v;
args[i] = Convert(v, GetType(ReadInt32())).Value();
}
}
var returnToken = ReadInt32();
pos = _pos;
_pos = oldPos;
if (virt && (args == null || args[0] == null))
throw new NullReferenceException();
object res = new VirtualMachine().Invoke(args, pos);
foreach (var r in refs)
{
r.Value.SetValue(args[r.Key]);
}
if (returnToken != 0)
{
var returnType = GetType(returnToken);
if (returnType != typeof(void))
return Convert(res, returnType);
}
return null;
}
private bool IsInst(object obj, Type t)
{
if (obj == null)
return true;
var t2 = obj.GetType();
if (t2 == t || t.IsAssignableFrom(t2))
return true;
return false;
}
private void Unwind()
{
_stack.Clear();
_finallyStack.Clear();
while (_tryStack.Count != 0)
{
var catchBlocks = _tryStack.Peek().CatchBlocks();
int startIndex = (_filterBlock == null) ? 0 : catchBlocks.IndexOf(_filterBlock) + 1;
_filterBlock = null;
for (var i = startIndex; i < catchBlocks.Count; i++)
{
var current = catchBlocks[i];
switch (current.Type())
{
case 0:
var type = _exception.GetType();
var type2 = GetType(current.Filter());
if (type == type2 || type.IsSubclassOf(type2))
{
_tryStack.Pop();
_stack.Push(new ObjectVariant(_exception));
_pos = current.Handler();
return;
}
break;
case 1:
_filterBlock = current;
_stack.Push(new ObjectVariant(_exception));
_pos = current.Filter();
return;
}
}
_tryStack.Pop();
for (var i = catchBlocks.Count; i > 0; i--)
{
var current = catchBlocks[i - 1];
if (current.Type() == 2 || current.Type() == 4)
_finallyStack.Push(current.Handler());
}
if (_finallyStack.Count != 0)
{
_pos = _finallyStack.Pop();
return;
}
}
throw _exception;
}
private void Initarg()
{
var type = GetType(Pop().ToInt32());
var r = Pop();
var v = Pop();
if (r.IsReference())
v = new ArgReferenceVariant(Convert(v.Value(), type), r);
else if (r.ToInt32() == 0)
v = Convert(v.Value(), type);
else
v = new NullReferenceVariant(type);
_args.Add(v);
}
private void Entertry()
{
var i = Pop().ToInt32();
foreach (var current in _tryBlocks)
{
if (current.Begin() == i)
_tryStack.Push(current);
}
}
private void Ldc_i4()
{
Push(new IntVariant(ReadInt32()));
}
private void Ldc_i8()
{
Push(new LongVariant(ReadInt64()));
}
private void Ldc_r4()
{
Push(new SingleVariant(ReadSingle()));
}
private void Ldc_r8()
{
Push(new DoubleVariant(ReadDouble()));
}
private void Ldnull()
{
Push(new ObjectVariant(null));
}
private void Ldstr()
{
Push(new StringVariant(GetString(Pop().ToInt32())));
}
private void Dup()
{
Push(Peek().Clone());
}
private void Add_()
{
var v1 = Pop();
var v2 = Pop();
Push(Add(v1, v2, false, false));
}
private void Add_ovf()
{
var v1 = Pop();
var v2 = Pop();
Push(Add(v1, v2, true, false));
}
private void Add_ovf_un()
{
var v1 = Pop();
var v2 = Pop();
Push(Add(v1, v2, true, true));
}
private void Sub_()
{
var v2 = Pop();
var v1 = Pop();
Push(Sub(v1, v2, false, false));
}
private void Sub_ovf()
{
var v2 = Pop();
var v1 = Pop();
Push(Sub(v1, v2, true, false));
}
private void Sub_ovf_un()
{
var v2 = Pop();
var v1 = Pop();
Push(Sub(v1, v2, true, true));
}
private void Mul_()
{
var v2 = Pop();
var v1 = Pop();
Push(Mul(v1, v2, false, false));
}
private void Mul_ovf()
{
var v2 = Pop();
var v1 = Pop();
Push(Mul(v1, v2, true, false));
}
private void Mul_ovf_un()
{
var v2 = Pop();
var v1 = Pop();
Push(Mul(v1, v2, true, true));
}
private void Div_()
{
var v2 = Pop();
var v1 = Pop();
Push(Div(v1, v2, false));
}
private void Div_un()
{
var v2 = Pop();
var v1 = Pop();
Push(Div(v1, v2, true));
}
private void Rem_()
{
var v2 = Pop();
var v1 = Pop();
Push(Rem(v1, v2, false));
}
private void Rem_un()
{
var v2 = Pop();
var v1 = Pop();
Push(Rem(v1, v2, true));
}
private void And_()
{
var v2 = Pop();
var v1 = Pop();
Push(And(v1, v2));
}
private void Or_()
{
var v2 = Pop();
var v1 = Pop();
Push(Or(v1, v2));
}
private void Xor_()
{
var v2 = Pop();
var v1 = Pop();
Push(Xor(v1, v2));
}
private void Not_()
{
var v = Pop();
Push(Not(v));
}
private void Neg_()
{
var v = Pop();
Push(Neg(v));
}
private void Shr_()
{
var v2 = Pop();
var v1 = Pop();
Push(Shr(v1, v2, false));
}
private void Shr_un()
{
var v2 = Pop();
var v1 = Pop();
Push(Shr(v1, v2, true));
}
private void Shl_()
{
var v2 = Pop();
var v1 = Pop();
Push(Shl(v1, v2));
}
private void Conv()
{
var type = GetType(Pop().ToInt32());
Push(Convert(Pop(), type));
}
private void Conv_ovf()
{
var type = GetType(Pop().ToInt32());
Push(Convert(Pop().Conv_ovf(type, false), type));
}
private void Conv_ovf_un()
{
var type = GetType(Pop().ToInt32());
Push(Convert(Pop().Conv_ovf(type, true), type));
}
private void Sizeof()
{
var type = GetType(Pop().ToInt32());
var dynamicMethod = new DynamicMethod("", typeof(int), null, typeof(VirtualMachine).Module, true);
var gen = dynamicMethod.GetILGenerator();
gen.Emit(System.Reflection.Emit.OpCodes.Sizeof, type);
gen.Emit(System.Reflection.Emit.OpCodes.Ret);
Push(new IntVariant((int)dynamicMethod.Invoke(null, null)));
}
private void Ldind()
{
var type = GetType(Pop().ToInt32());
var v = Pop();
if (!v.IsReference())
{
if (v.Value() is Pointer)
unsafe { v = new PointerReference(new IntPtr(Pointer.Unbox(v.Value())), type); }
else
throw new ArgumentException();
}
Push(Convert(v, type));
}
private void Ldfld()
{
var field = GetField(Pop().ToInt32());
var v = Pop();
object obj;
if (v.Type().IsPointer)
obj = Marshal.PtrToStructure(v.ToIntPtr(), v.Type().GetElementType());
else
obj = v.Value();
Push(Convert(field.GetValue(obj), field.FieldType));
}
private void Ldflda()
{
var field = GetField(Pop().ToInt32());
var v = Pop();
Push(new FieldReferenceVariant(field, v));
}
private void Stfld()
{
var field = GetField(Pop().ToInt32());
var v = Pop();
var baseVariant = Pop();
var obj = baseVariant.Value();
baseVariant.SetFieldValue(field, Convert(v, field.FieldType).Value());
}
private void Stsfld()
{
var field = GetField(Pop().ToInt32());
var v = Pop();
field.SetValue(null, Convert(v, field.FieldType).Value());
}
private void Stind()
{
var type = GetType(Pop().ToInt32());
var v2 = Pop();
var v1 = Pop();
v2 = Convert(v2, type);
if (v1.IsReference())
v2 = Convert(v2, v1.Type());
else {
if (v1.Value() is Pointer)
unsafe { v1 = new PointerReference(new IntPtr(Pointer.Unbox(v1.Value())), type); }
else
throw new ArgumentException();
}
v1.SetValue(v2.Value());
}
private void Ldarg()
{
Push(_args[ReadInt16()].Clone());
}
private void Ldarga()
{
var v = _args[ReadInt16()];
if (v.IsReference())
throw new ArgumentException();
Push(new ReferenceVariant(v));
}
private void Starg()
{
var v2 = Pop();
int index = ReadInt16();
var v1 = _args[index];
if (v1.IsReference())
{
if (!v2.IsReference())
throw new ArgumentException();
_args[index] = v2;
}
else
{
v1.SetValue(Convert(v2, v1.Type()).Value());
}
}
private void Constrained()
{
_constrained = GetType(Pop().ToInt32());
}
private void Call_()
{
var method = GetMethod(Pop().ToInt32());
var v = Call(method, false);
if (v != null)
Push(v);
}
private void Callvirt()
{
var method = GetMethod(Pop().ToInt32());
if (_constrained != null)
{
var parameters = method.GetParameters();
var types = new Type[parameters.Length];
var num = 0;
foreach (var param in parameters)
{
types[num++] = param.ParameterType;
}
var new_method = _constrained.GetMethod(method.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.GetProperty | BindingFlags.SetProperty, null, types, null);
if (new_method != null)
method = new_method;
_constrained = null;
}
var v = Call(method, true);
if (v != null)
Push(v);
}
private void Calli()
{
var method = Pop().Value() as MethodBase;
if (method == null)
throw new ArgumentException();
var v = Call(method, false);
if (v != null)
Push(v);
}
private void Callvm_()
{
var v = Callvm(Pop().ToInt32(), false);
if (v != null)
Push(v);
}
private void Callvmvirt()
{
var v = Callvm(Pop().ToInt32(), true);
if (v != null)
Push(v);
}
private void Newobj_()
{
var method = GetMethod(Pop().ToInt32());
var v = Newobj(method);
if (v != null)
Push(v);
}
private void Initobj()
{
var type = GetType(Pop().ToInt32());
var v = Pop();
object obj = null;
if (type.IsValueType)
{
if (Nullable.GetUnderlyingType(type) == null)
obj = FormatterServices.GetUninitializedObject(type);
}
v.SetValue(obj);
}
private void Cmp()
{
var def = Pop().ToInt32();
var v2 = Pop();
var v1 = Pop();
Push(new IntVariant(Compare(v1, v2, false, def)));
}
private void Cmp_un()
{
var def = Pop().ToInt32();
var v2 = Pop();
var v1 = Pop();
Push(new IntVariant(Compare(v1, v2, true, def)));
}
private void Newarr()
{
var type = GetType(Pop().ToInt32());
Push(new ArrayVariant(Array.CreateInstance(type, Pop().ToInt32())));
}
private void Stelem()
{
var type = GetType(Pop().ToInt32());
var v2 = Pop();
var v1 = Pop();
var array = Pop().Value() as Array;
if (array == null)
throw new ArgumentException();
array.SetValue(Convert(Convert(v2, type), array.GetType().GetElementType()).Value(), v1.ToInt32());
}
private void Ldelem()
{
var type = GetType(Pop().ToInt32());
var v = Pop();
var array = Pop().Value() as Array;
if (array == null)
throw new ArgumentException();
Push(Convert(array.GetValue(v.ToInt32()), type));
}
private void Ldlen()
{
var array = Pop().Value() as Array;
if (array == null)
throw new ArgumentException();
Push(new IntVariant(array.Length));
}
private void Ldelema()
{
var v = Pop();
var array = Pop().Value() as Array;
if (array == null)
throw new ArgumentException();
Push(new ArrayElementVariant(array, v.ToInt32()));
}
private void Ldftn()
{
Push(new MethodVariant(GetMethod(Pop().ToInt32())));
}
private void Ldvirtftn()
{
var method = GetMethod(Pop().ToInt32());
var type = Pop().Value().GetType();
var declaringType = method.DeclaringType;
var parameters = method.GetParameters();
var types = new Type[parameters.Length];
var num = 0;
foreach (var param in parameters)
{
types[num++] = param.ParameterType;
}
while (type != null && type != declaringType)
{
var new_method = type.GetMethod(method.Name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.ExactBinding, null, CallingConventions.Any, types, null);
if (new_method != null && new_method.GetBaseDefinition() == method)
{
method = new_method;
break;
}
type = type.BaseType;
}
Push(new MethodVariant(method));
}
private void Br()
{
_pos = Pop().ToInt32();
}
private void Pop_()
{
Pop();
}
private void Leave()
{
_finallyStack.Push(Pop().ToInt32());
var offset = Pop().ToInt32();
while (_tryStack.Count != 0 && offset > _tryStack.Peek().End())
{
var catchBlocks = _tryStack.Pop().CatchBlocks();
for (var i = catchBlocks.Count; i > 0; i--)
{
var current = catchBlocks[i - 1];
if (current.Type() == 2)
_finallyStack.Push(current.Handler());
}
}
_exception = null;
_stack.Clear();
_pos = _finallyStack.Pop();
}
private void Endfinally()
{
if (_exception == null)
{
_pos = _finallyStack.Pop();
return;
}
Unwind();
}
private void Endfilter()
{
if (Pop().ToInt32() != 0)
{
_tryStack.Pop();
_stack.Push(new ObjectVariant(_exception));
_pos = _filterBlock.Handler();
_filterBlock = null;
return;
}
Unwind();
}
private void Box()
{
var type = GetType(Pop().ToInt32());
Push(new ObjectVariant(Convert(Pop(), type).Value()));
}
private void Unbox()
{
var type = GetType(Pop().ToInt32());
Push(Convert(Pop().Value(), type));
}
private void Unbox_any()
{
var type = GetType(Pop().ToInt32());
var v = Pop();
var obj = v.Value();
if (obj == null)
throw new NullReferenceException();
if (type.IsValueType)
{
if (type != obj.GetType())
throw new InvalidCastException();
Push(Convert(obj, type));
}
else switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
Push(new BoolVariant((bool)obj));
break;
case TypeCode.Char:
Push(new CharVariant((char)obj));
break;
case TypeCode.SByte:
Push(new SbyteVariant((sbyte)obj));
break;
case TypeCode.Byte:
Push(new ByteVariant((byte)obj));
break;
case TypeCode.Int16:
Push(new ShortVariant((short)obj));
break;
case TypeCode.UInt16:
Push(new UshortVariant((ushort)obj));
break;
case TypeCode.Int32:
Push(new IntVariant((int)obj));
break;
case TypeCode.UInt32:
Push(new UintVariant((uint)obj));
break;
case TypeCode.Int64:
Push(new LongVariant((long)obj));
break;
case TypeCode.UInt64:
Push(new UlongVariant((ulong)obj));
break;
case TypeCode.Single:
Push(new SingleVariant((float)obj));
break;
case TypeCode.Double:
Push(new DoubleVariant((double)obj));
break;
default:
throw new InvalidCastException();
}
}
private void Ldmem_i4()
{
Push(new IntVariant(Marshal.ReadInt32(new IntPtr(_instance + Pop().ToUInt32()))));
}
private void Ldtoken()
{
var i = Pop().ToInt32();
switch (i >> 24)
{
case 04:
Push(new ValueTypeVariant(_module.ModuleHandle.ResolveFieldHandle(i)));
break;
case 0x01:
case 0x02:
case 0x1b:
Push(new ValueTypeVariant(_module.ModuleHandle.ResolveTypeHandle(i)));
break;
case 0x06:
case 0x2b:
Push(new ValueTypeVariant(_module.ModuleHandle.ResolveMethodHandle(i)));
break;
case 0x0a:
try
{
Push(new ValueTypeVariant(_module.ModuleHandle.ResolveFieldHandle(i)));
}
catch
{
Push(new ValueTypeVariant(_module.ModuleHandle.ResolveMethodHandle(i)));
}
break;
default:
throw new InvalidOperationException();
}
}
private void Throw()
{
var e = Pop().Value() as Exception;
if (e == null)
throw new ArgumentException();
throw e;
}
private void Rethrow()
{
if (_exception == null)
throw new InvalidOperationException();
throw _exception;
}
private void Castclass()
{
var type = GetType(Pop().ToInt32());
var v = Pop();
if (!IsInst(v.Value(), type))
throw new InvalidCastException();
Push(v);
}
private void Isinst()
{
var type = GetType(Pop().ToInt32());
var v = Pop();
if (!IsInst(v.Value(), type))
v = new ObjectVariant(null);
Push(v);
}
private void Ckfinite()
{
var v = Pop();
if (v.Value() is IConvertible)
{
var d = v.ToDouble();
if (double.IsNaN(d) || double.IsInfinity(d))
throw new OverflowException();
}
else
{
v = new DoubleVariant(double.NaN);
}
Push(v);
}
private void Localloc()
{
var ptr = Marshal.AllocHGlobal(Pop().ToIntPtr());
_localloc.Add(ptr);
unsafe {
Push(new ObjectVariant(Pointer.Box(ptr.ToPointer(), typeof(void*))));
}
}
private void FreeAllLocalloc()
{
foreach (var ptr in _localloc)
{
Marshal.FreeHGlobal(ptr);
}
}
public object Invoke(object[] args, int pos)
{
_pos = pos;
Push(new ArrayVariant(args));
try
{
while (true)
{
try
{
_handlers[ReadByte()]();
if (_pos == 0)
break;
}
catch (Exception e)
{
if (_filterBlock == null)
_exception = e;
Unwind();
}
}
return Pop().Value();
}
finally
{
FreeAllLocalloc();
}
}
}
}