/* Copyright (C) 2011-2015 de4dot@gmail.com This file is part of de4dot. de4dot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. de4dot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with de4dot. If not, see . */ using System; using System.Collections.Generic; using dnlib.DotNet; using dnlib.DotNet.Emit; namespace de4dot.blocks.cflow { public class InstructionEmulator { ValueStack valueStack = new ValueStack(); Dictionary protectedStackValues = new Dictionary(); IList parameterDefs; IList localDefs; List args = new List(); List locals = new List(); MethodDef prev_method; List cached_args = new List(); List cached_locals = new List(); List cached_zeroed_locals = new List(); public InstructionEmulator() { } public InstructionEmulator(MethodDef method) { Initialize(method, false); } public void Initialize(Blocks blocks, bool emulateFromFirstInstruction) { Initialize(blocks.Method, emulateFromFirstInstruction); } public void Initialize(MethodDef method) { Initialize(method, false); } public void Initialize(MethodDef method, bool emulateFromFirstInstruction) { Initialize(method, method.Parameters, method.Body.Variables, method.Body.InitLocals, emulateFromFirstInstruction); } public void Initialize(MethodDef method, IList methodParameters, IList methodLocals, bool initLocals, bool emulateFromFirstInstruction) { this.parameterDefs = methodParameters; this.localDefs = methodLocals; valueStack.Initialize(); protectedStackValues.Clear(); if (method != prev_method) { prev_method = method; cached_args.Clear(); for (int i = 0; i < parameterDefs.Count; i++) cached_args.Add(GetUnknownValue(parameterDefs[i].Type)); cached_locals.Clear(); cached_zeroed_locals.Clear(); for (int i = 0; i < localDefs.Count; i++) { cached_locals.Add(GetUnknownValue(localDefs[i].Type)); cached_zeroed_locals.Add(GetDefaultValue(localDefs[i].Type)); } } args.Clear(); args.AddRange(cached_args); locals.Clear(); locals.AddRange(initLocals && emulateFromFirstInstruction ? cached_zeroed_locals : cached_locals); } public void SetProtected(Value value) { protectedStackValues[value] = true; } static Value GetUnknownValue(ITypeDefOrRef type) { return GetUnknownValue(type.ToTypeSig(false)); } static Value GetUnknownValue(TypeSig type) { if (type == null) return new UnknownValue(); switch (type.ElementType) { case ElementType.Boolean: return Int32Value.CreateUnknownBool(); case ElementType.I1: return Int32Value.CreateUnknown(); case ElementType.U1: return Int32Value.CreateUnknownUInt8(); case ElementType.I2: return Int32Value.CreateUnknown(); case ElementType.U2: return Int32Value.CreateUnknownUInt16(); case ElementType.I4: return Int32Value.CreateUnknown(); case ElementType.U4: return Int32Value.CreateUnknown(); case ElementType.I8: return Int64Value.CreateUnknown(); case ElementType.U8: return Int64Value.CreateUnknown(); } return new UnknownValue(); } static Value GetDefaultValue(TypeSig type) { if (type == null) return new UnknownValue(); switch (type.ElementType) { case ElementType.Boolean: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: return Int32Value.Zero; case ElementType.I8: case ElementType.U8: return Int64Value.Zero; } return new UnknownValue(); } Value TruncateValue(Value value, TypeSig type) { if (type == null) return value; if (protectedStackValues.ContainsKey(value)) return value; switch (type.ElementType) { case ElementType.Boolean: if (value.IsInt32()) return ((Int32Value)value).ToBoolean(); return Int32Value.CreateUnknownBool(); case ElementType.I1: if (value.IsInt32()) return ((Int32Value)value).ToInt8(); return Int32Value.CreateUnknown(); case ElementType.U1: if (value.IsInt32()) return ((Int32Value)value).ToUInt8(); return Int32Value.CreateUnknownUInt8(); case ElementType.I2: if (value.IsInt32()) return ((Int32Value)value).ToInt16(); return Int32Value.CreateUnknown(); case ElementType.U2: if (value.IsInt32()) return ((Int32Value)value).ToUInt16(); return Int32Value.CreateUnknownUInt16(); case ElementType.I4: case ElementType.U4: if (value.IsInt32()) return value; return Int32Value.CreateUnknown(); case ElementType.I8: case ElementType.U8: if (value.IsInt64()) return value; return Int64Value.CreateUnknown(); case ElementType.R4: if (value.IsReal8()) return ((Real8Value)value).ToSingle(); return new UnknownValue(); case ElementType.R8: if (value.IsReal8()) return value; return new UnknownValue(); } return value; } static Value GetValue(List list, int i) { if (0 <= i && i < list.Count) return list[i]; return new UnknownValue(); } public Value GetArg(int i) { return GetValue(args, i); } public Value GetArg(Parameter arg) { if (arg == null) return new UnknownValue(); return GetArg(arg.Index); } TypeSig GetArgType(int index) { if (0 <= index && index < parameterDefs.Count) return parameterDefs[index].Type; return null; } public void SetArg(Parameter arg, Value value) { if (arg != null) SetArg(arg.Index, value); } public void MakeArgUnknown(Parameter arg) { if (arg != null) SetArg(arg, GetUnknownArg(arg.Index)); } void SetArg(int index, Value value) { if (0 <= index && index < args.Count) args[index] = TruncateValue(value, GetArgType(index)); } Value GetUnknownArg(int index) { return GetUnknownValue(GetArgType(index)); } public Value GetLocal(int i) { return GetValue(locals, i); } public Value GetLocal(Local local) { if (local == null) return new UnknownValue(); return GetLocal(local.Index); } public void SetLocal(Local local, Value value) { if (local != null) SetLocal(local.Index, value); } public void MakeLocalUnknown(Local local) { if (local != null) SetLocal(local.Index, GetUnknownLocal(local.Index)); } void SetLocal(int index, Value value) { if (0 <= index && index < locals.Count) locals[index] = TruncateValue(value, localDefs[index].Type); } Value GetUnknownLocal(int index) { if (0 <= index && index < localDefs.Count) return GetUnknownValue(localDefs[index].Type); return new UnknownValue(); } public int StackSize() { return valueStack.Size; } public void Push(Value value) { valueStack.Push(value); } public void ClearStack() { valueStack.Clear(); } public void Pop(int num) { if (num < 0) valueStack.Clear(); else valueStack.Pop(num); } public Value Pop() { return valueStack.Pop(); } public Value Peek() { return valueStack.Peek(); } public void Emulate(IEnumerable instructions) { foreach (var instr in instructions) Emulate(instr.Instruction); } public void Emulate(IList instructions, int start, int end) { for (int i = start; i < end; i++) Emulate(instructions[i].Instruction); } public void Emulate(Instruction instr) { switch (instr.OpCode.Code) { case Code.Starg: case Code.Starg_S: Emulate_Starg((Parameter)instr.Operand); break; case Code.Stloc: case Code.Stloc_S: Emulate_Stloc((Local)instr.Operand); break; case Code.Stloc_0: Emulate_Stloc(0); break; case Code.Stloc_1: Emulate_Stloc(1); break; case Code.Stloc_2: Emulate_Stloc(2); break; case Code.Stloc_3: Emulate_Stloc(3); break; case Code.Ldarg: case Code.Ldarg_S: valueStack.Push(GetArg((Parameter)instr.Operand)); break; case Code.Ldarg_0: valueStack.Push(GetArg(0)); break; case Code.Ldarg_1: valueStack.Push(GetArg(1)); break; case Code.Ldarg_2: valueStack.Push(GetArg(2)); break; case Code.Ldarg_3: valueStack.Push(GetArg(3)); break; case Code.Ldloc: case Code.Ldloc_S: valueStack.Push(GetLocal((Local)instr.Operand)); break; case Code.Ldloc_0: valueStack.Push(GetLocal(0)); break; case Code.Ldloc_1: valueStack.Push(GetLocal(1)); break; case Code.Ldloc_2: valueStack.Push(GetLocal(2)); break; case Code.Ldloc_3: valueStack.Push(GetLocal(3)); break; case Code.Ldarga: case Code.Ldarga_S: Emulate_Ldarga((Parameter)instr.Operand); break; case Code.Ldloca: case Code.Ldloca_S: Emulate_Ldloca((Local)instr.Operand); break; case Code.Dup: valueStack.CopyTop(); break; case Code.Ldc_I4: valueStack.Push(new Int32Value((int)instr.Operand)); break; case Code.Ldc_I4_S: valueStack.Push(new Int32Value((sbyte)instr.Operand)); break; case Code.Ldc_I8: valueStack.Push(new Int64Value((long)instr.Operand)); break; case Code.Ldc_R4: valueStack.Push(new Real8Value((float)instr.Operand)); break; case Code.Ldc_R8: valueStack.Push(new Real8Value((double)instr.Operand)); break; case Code.Ldc_I4_0: valueStack.Push(Int32Value.Zero); break; case Code.Ldc_I4_1: valueStack.Push(Int32Value.One); break; case Code.Ldc_I4_2: valueStack.Push(new Int32Value(2)); break; case Code.Ldc_I4_3: valueStack.Push(new Int32Value(3)); break; case Code.Ldc_I4_4: valueStack.Push(new Int32Value(4)); break; case Code.Ldc_I4_5: valueStack.Push(new Int32Value(5)); break; case Code.Ldc_I4_6: valueStack.Push(new Int32Value(6)); break; case Code.Ldc_I4_7: valueStack.Push(new Int32Value(7)); break; case Code.Ldc_I4_8: valueStack.Push(new Int32Value(8)); break; case Code.Ldc_I4_M1:valueStack.Push(new Int32Value(-1)); break; case Code.Ldnull: valueStack.Push(NullValue.Instance); break; case Code.Ldstr: valueStack.Push(new StringValue((string)instr.Operand)); break; case Code.Box: valueStack.Push(new BoxedValue(valueStack.Pop())); break; case Code.Conv_U1: Emulate_Conv_U1(instr); break; case Code.Conv_U2: Emulate_Conv_U2(instr); break; case Code.Conv_U4: Emulate_Conv_U4(instr); break; case Code.Conv_U8: Emulate_Conv_U8(instr); break; case Code.Conv_I1: Emulate_Conv_I1(instr); break; case Code.Conv_I2: Emulate_Conv_I2(instr); break; case Code.Conv_I4: Emulate_Conv_I4(instr); break; case Code.Conv_I8: Emulate_Conv_I8(instr); break; case Code.Add: Emulate_Add(instr); break; case Code.Sub: Emulate_Sub(instr); break; case Code.Mul: Emulate_Mul(instr); break; case Code.Div: Emulate_Div(instr); break; case Code.Div_Un: Emulate_Div_Un(instr); break; case Code.Rem: Emulate_Rem(instr); break; case Code.Rem_Un: Emulate_Rem_Un(instr); break; case Code.Neg: Emulate_Neg(instr); break; case Code.And: Emulate_And(instr); break; case Code.Or: Emulate_Or(instr); break; case Code.Xor: Emulate_Xor(instr); break; case Code.Not: Emulate_Not(instr); break; case Code.Shl: Emulate_Shl(instr); break; case Code.Shr: Emulate_Shr(instr); break; case Code.Shr_Un: Emulate_Shr_Un(instr); break; case Code.Ceq: Emulate_Ceq(instr); break; case Code.Cgt: Emulate_Cgt(instr); break; case Code.Cgt_Un: Emulate_Cgt_Un(instr); break; case Code.Clt: Emulate_Clt(instr); break; case Code.Clt_Un: Emulate_Clt_Un(instr); break; case Code.Unbox_Any:Emulate_Unbox_Any(instr); break; case Code.Call: Emulate_Call(instr); break; case Code.Callvirt: Emulate_Callvirt(instr); break; case Code.Castclass: Emulate_Castclass(instr); break; case Code.Isinst: Emulate_Isinst(instr); break; case Code.Add_Ovf: Emulate_Add_Ovf(instr); break; case Code.Add_Ovf_Un: Emulate_Add_Ovf_Un(instr); break; case Code.Sub_Ovf: Emulate_Sub_Ovf(instr); break; case Code.Sub_Ovf_Un: Emulate_Sub_Ovf_Un(instr); break; case Code.Mul_Ovf: Emulate_Mul_Ovf(instr); break; case Code.Mul_Ovf_Un: Emulate_Mul_Ovf_Un(instr); break; case Code.Conv_Ovf_I1: Emulate_Conv_Ovf_I1(instr); break; case Code.Conv_Ovf_I1_Un: Emulate_Conv_Ovf_I1_Un(instr); break; case Code.Conv_Ovf_I2: Emulate_Conv_Ovf_I2(instr); break; case Code.Conv_Ovf_I2_Un: Emulate_Conv_Ovf_I2_Un(instr); break; case Code.Conv_Ovf_I4: Emulate_Conv_Ovf_I4(instr); break; case Code.Conv_Ovf_I4_Un: Emulate_Conv_Ovf_I4_Un(instr); break; case Code.Conv_Ovf_I8: Emulate_Conv_Ovf_I8(instr); break; case Code.Conv_Ovf_I8_Un: Emulate_Conv_Ovf_I8_Un(instr); break; case Code.Conv_Ovf_U1: Emulate_Conv_Ovf_U1(instr); break; case Code.Conv_Ovf_U1_Un: Emulate_Conv_Ovf_U1_Un(instr); break; case Code.Conv_Ovf_U2: Emulate_Conv_Ovf_U2(instr); break; case Code.Conv_Ovf_U2_Un: Emulate_Conv_Ovf_U2_Un(instr); break; case Code.Conv_Ovf_U4: Emulate_Conv_Ovf_U4(instr); break; case Code.Conv_Ovf_U4_Un: Emulate_Conv_Ovf_U4_Un(instr); break; case Code.Conv_Ovf_U8: Emulate_Conv_Ovf_U8(instr); break; case Code.Conv_Ovf_U8_Un: Emulate_Conv_Ovf_U8_Un(instr); break; case Code.Ldelem_I1: valueStack.Pop(2); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldelem_I2: valueStack.Pop(2); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldelem_I4: valueStack.Pop(2); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldelem_I8: valueStack.Pop(2); valueStack.Push(Int64Value.CreateUnknown()); break; case Code.Ldelem_U1: valueStack.Pop(2); valueStack.Push(Int32Value.CreateUnknownUInt8()); break; case Code.Ldelem_U2: valueStack.Pop(2); valueStack.Push(Int32Value.CreateUnknownUInt16()); break; case Code.Ldelem_U4: valueStack.Pop(2); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldelem: valueStack.Pop(2); valueStack.Push(GetUnknownValue(instr.Operand as ITypeDefOrRef)); break; case Code.Ldind_I1: valueStack.Pop(); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldind_I2: valueStack.Pop(); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldind_I4: valueStack.Pop(); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldind_I8: valueStack.Pop(); valueStack.Push(Int64Value.CreateUnknown()); break; case Code.Ldind_U1: valueStack.Pop(); valueStack.Push(Int32Value.CreateUnknownUInt8()); break; case Code.Ldind_U2: valueStack.Pop(); valueStack.Push(Int32Value.CreateUnknownUInt16()); break; case Code.Ldind_U4: valueStack.Pop(); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldlen: valueStack.Pop(); valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Sizeof: valueStack.Push(Int32Value.CreateUnknown()); break; case Code.Ldfld: Emulate_Ldfld(instr); break; case Code.Ldsfld: Emulate_Ldsfld(instr); break; case Code.Ldftn: valueStack.Push(new ObjectValue(instr.Operand)); break; case Code.Ldsflda: valueStack.Push(new ObjectValue(instr.Operand)); break; case Code.Ldtoken: valueStack.Push(new ObjectValue(instr.Operand)); break; case Code.Ldvirtftn:valueStack.Pop(); valueStack.Push(new ObjectValue()); break; case Code.Ldflda: valueStack.Pop(); valueStack.Push(new ObjectValue()); break; case Code.Unbox: case Code.Conv_R_Un:Emulate_Conv_R_Un(instr); break; case Code.Conv_R4: Emulate_Conv_R4(instr); break; case Code.Conv_R8: Emulate_Conv_R8(instr); break; case Code.Arglist: case Code.Beq: case Code.Beq_S: case Code.Bge: case Code.Bge_S: case Code.Bge_Un: case Code.Bge_Un_S: case Code.Bgt: case Code.Bgt_S: case Code.Bgt_Un: case Code.Bgt_Un_S: case Code.Ble: case Code.Ble_S: case Code.Ble_Un: case Code.Ble_Un_S: case Code.Blt: case Code.Blt_S: case Code.Blt_Un: case Code.Blt_Un_S: case Code.Bne_Un: case Code.Bne_Un_S: case Code.Brfalse: case Code.Brfalse_S: case Code.Brtrue: case Code.Brtrue_S: case Code.Br: case Code.Br_S: case Code.Break: case Code.Calli: case Code.Ckfinite: case Code.Constrained: case Code.Conv_I: case Code.Conv_Ovf_I: case Code.Conv_Ovf_I_Un: case Code.Conv_Ovf_U: case Code.Conv_Ovf_U_Un: case Code.Conv_U: case Code.Cpblk: case Code.Cpobj: case Code.Endfilter: case Code.Endfinally: case Code.Initblk: case Code.Initobj: case Code.Jmp: case Code.Ldelema: case Code.Ldelem_I: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldind_I: case Code.Ldind_R4: case Code.Ldind_R8: case Code.Ldind_Ref: case Code.Ldobj: case Code.Leave: case Code.Leave_S: case Code.Localloc: case Code.Mkrefany: case Code.Newarr: case Code.Newobj: case Code.Nop: case Code.Pop: case Code.Readonly: case Code.Refanytype: case Code.Refanyval: case Code.Ret: case Code.Rethrow: case Code.Stelem: case Code.Stelem_I: case Code.Stelem_I1: case Code.Stelem_I2: case Code.Stelem_I4: case Code.Stelem_I8: case Code.Stelem_R4: case Code.Stelem_R8: case Code.Stelem_Ref: case Code.Stfld: case Code.Stind_I: case Code.Stind_I1: case Code.Stind_I2: case Code.Stind_I4: case Code.Stind_I8: case Code.Stind_R4: case Code.Stind_R8: case Code.Stind_Ref: case Code.Stobj: case Code.Stsfld: case Code.Switch: case Code.Tailcall: case Code.Throw: case Code.Unaligned: case Code.Volatile: default: UpdateStack(instr); break; } } void UpdateStack(Instruction instr) { int pushes, pops; instr.CalculateStackUsage(out pushes, out pops); if (pops == -1) valueStack.Clear(); else { valueStack.Pop(pops); valueStack.Push(pushes); } } void Emulate_Conv_U1(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_U1((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int32Value.Conv_U1((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int32Value.Conv_U1((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknownUInt8()); break; } } void Emulate_Conv_I1(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_I1((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int32Value.Conv_I1((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int32Value.Conv_I1((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_U2(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_U2((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int32Value.Conv_U2((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int32Value.Conv_U2((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknownUInt16()); break; } } void Emulate_Conv_I2(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_I2((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int32Value.Conv_I2((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int32Value.Conv_I2((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_U4(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_U4((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int32Value.Conv_U4((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int32Value.Conv_U4((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_I4(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_I4((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int32Value.Conv_I4((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int32Value.Conv_I4((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_U8(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int64Value.Conv_U8((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_U8((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int64Value.Conv_U8((Real8Value)val1)); break; default: valueStack.Push(Int64Value.CreateUnknown()); break; } } void Emulate_Conv_I8(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int64Value.Conv_I8((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_I8((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Int64Value.Conv_I8((Real8Value)val1)); break; default: valueStack.Push(Int64Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I1(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I1((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I1((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I1((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I1_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I1_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I1_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I1_Un((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I2(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I2((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I2((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I2((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I2_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I2_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I2_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I2_Un((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I4(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I4((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I4((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I4((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I4_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I4_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I4_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I4_Un((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I8(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I8((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I8((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I8((Real8Value)val1)); break; default: valueStack.Push(Int64Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_I8_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_I8_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_I8_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_I8_Un((Real8Value)val1)); break; default: valueStack.Push(Int64Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_U1(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U1((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U1((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U1((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknownUInt8()); break; } } void Emulate_Conv_Ovf_U1_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U1_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U1_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U1_Un((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknownUInt8()); break; } } void Emulate_Conv_Ovf_U2(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U2((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U2((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U2((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknownUInt16()); break; } } void Emulate_Conv_Ovf_U2_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U2_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U2_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U2_Un((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknownUInt16()); break; } } void Emulate_Conv_Ovf_U4(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U4((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U4((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U4((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_U4_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U4_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U4_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U4_Un((Real8Value)val1)); break; default: valueStack.Push(Int32Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_U8(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U8((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U8((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U8((Real8Value)val1)); break; default: valueStack.Push(Int64Value.CreateUnknown()); break; } } void Emulate_Conv_Ovf_U8_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_Ovf_U8_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_Ovf_U8_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_Ovf_U8_Un((Real8Value)val1)); break; default: valueStack.Push(Int64Value.CreateUnknown()); break; } } void Emulate_Conv_R_Un(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_R_Un((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_R_Un((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_R_Un((Real8Value)val1)); break; default: valueStack.Push(Real8Value.CreateUnknown()); break; } } void Emulate_Conv_R4(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_R4((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_R4((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_R4((Real8Value)val1)); break; default: valueStack.Push(Real8Value.CreateUnknown()); break; } } void Emulate_Conv_R8(Instruction instr) { var val1 = valueStack.Pop(); switch (val1.valueType) { case ValueType.Int32: valueStack.Push(Int32Value.Conv_R8((Int32Value)val1)); break; case ValueType.Int64: valueStack.Push(Int64Value.Conv_R8((Int64Value)val1)); break; case ValueType.Real8: valueStack.Push(Real8Value.Conv_R8((Real8Value)val1)); break; default: valueStack.Push(Real8Value.CreateUnknown()); break; } } void Emulate_Add(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Add((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Add((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Add((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Sub(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Sub((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Sub((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Sub((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Mul(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Mul((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Mul((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Mul((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Div(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Div((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Div((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Div((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Div_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Div_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Div_Un((Int64Value)val1, (Int64Value)val2)); else valueStack.PushUnknown(); } void Emulate_Rem(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Rem((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Rem((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Rem((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Rem_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Rem_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Rem_Un((Int64Value)val1, (Int64Value)val2)); else valueStack.PushUnknown(); } void Emulate_Neg(Instruction instr) { var val1 = valueStack.Pop(); if (val1.IsInt32()) valueStack.Push(Int32Value.Neg((Int32Value)val1)); else if (val1.IsInt64()) valueStack.Push(Int64Value.Neg((Int64Value)val1)); else if (val1.IsReal8()) valueStack.Push(Real8Value.Neg((Real8Value)val1)); else valueStack.PushUnknown(); } void Emulate_Add_Ovf(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Add_Ovf((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Add_Ovf((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Add_Ovf((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Add_Ovf_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Add_Ovf_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Add_Ovf_Un((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Add_Ovf_Un((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Sub_Ovf(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Sub_Ovf((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Sub_Ovf((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Sub_Ovf((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Sub_Ovf_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Sub_Ovf_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Sub_Ovf_Un((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Sub_Ovf_Un((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Mul_Ovf(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Mul_Ovf((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Mul_Ovf((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Mul_Ovf((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_Mul_Ovf_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Mul_Ovf_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Mul_Ovf_Un((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Mul_Ovf_Un((Real8Value)val1, (Real8Value)val2)); else valueStack.PushUnknown(); } void Emulate_And(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.And((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.And((Int64Value)val1, (Int64Value)val2)); else valueStack.PushUnknown(); } void Emulate_Or(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Or((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Or((Int64Value)val1, (Int64Value)val2)); else valueStack.PushUnknown(); } void Emulate_Xor(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Xor((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Xor((Int64Value)val1, (Int64Value)val2)); else valueStack.PushUnknown(); } void Emulate_Not(Instruction instr) { var val1 = valueStack.Pop(); if (val1.IsInt32()) valueStack.Push(Int32Value.Not((Int32Value)val1)); else if (val1.IsInt64()) valueStack.Push(Int64Value.Not((Int64Value)val1)); else valueStack.PushUnknown(); } void Emulate_Shl(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Shl((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt32()) valueStack.Push(Int64Value.Shl((Int64Value)val1, (Int32Value)val2)); else valueStack.PushUnknown(); } void Emulate_Shr(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Shr((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt32()) valueStack.Push(Int64Value.Shr((Int64Value)val1, (Int32Value)val2)); else valueStack.PushUnknown(); } void Emulate_Shr_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Shr_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt32()) valueStack.Push(Int64Value.Shr_Un((Int64Value)val1, (Int32Value)val2)); else valueStack.PushUnknown(); } void Emulate_Ceq(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Ceq((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Ceq((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Ceq((Real8Value)val1, (Real8Value)val2)); else if (val1.IsNull() && val2.IsNull()) valueStack.Push(Int32Value.One); else valueStack.Push(Int32Value.CreateUnknownBool()); } void Emulate_Cgt(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Cgt((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Cgt((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Cgt((Real8Value)val1, (Real8Value)val2)); else valueStack.Push(Int32Value.CreateUnknownBool()); } void Emulate_Cgt_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Cgt_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Cgt_Un((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Cgt_Un((Real8Value)val1, (Real8Value)val2)); else valueStack.Push(Int32Value.CreateUnknownBool()); } void Emulate_Clt(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Clt((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Clt((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Clt((Real8Value)val1, (Real8Value)val2)); else valueStack.Push(Int32Value.CreateUnknownBool()); } void Emulate_Clt_Un(Instruction instr) { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.Clt_Un((Int32Value)val1, (Int32Value)val2)); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.Clt_Un((Int64Value)val1, (Int64Value)val2)); else if (val1.IsReal8() && val2.IsReal8()) valueStack.Push(Real8Value.Clt_Un((Real8Value)val1, (Real8Value)val2)); else valueStack.Push(Int32Value.CreateUnknownBool()); } void Emulate_Unbox_Any(Instruction instr) { var val1 = valueStack.Pop(); if (val1.IsBoxed()) valueStack.Push(((BoxedValue)val1).value); else valueStack.PushUnknown(); } void Emulate_Starg(Parameter arg) { SetArg(arg == null ? -1 : arg.Index, valueStack.Pop()); } void Emulate_Stloc(Local local) { Emulate_Stloc(local == null ? -1 : local.Index); } void Emulate_Stloc(int index) { SetLocal(index, valueStack.Pop()); } void Emulate_Ldarga(Parameter arg) { valueStack.PushUnknown(); MakeArgUnknown(arg); } void Emulate_Ldloca(Local local) { Emulate_Ldloca(local == null ? -1 : local.Index); } void Emulate_Ldloca(int index) { valueStack.PushUnknown(); SetLocal(index, GetUnknownLocal(index)); } void Emulate_Call(Instruction instr) { Emulate_Call(instr, (IMethod)instr.Operand); } void Emulate_Callvirt(Instruction instr) { Emulate_Call(instr, (IMethod)instr.Operand); } void Emulate_Call(Instruction instr, IMethod method) { int pushes, pops; instr.CalculateStackUsage(out pushes, out pops); valueStack.Pop(pops); if (pushes == 1) valueStack.Push(GetUnknownValue(method.MethodSig.GetRetType())); else valueStack.Push(pushes); } void Emulate_Castclass(Instruction instr) { var val1 = valueStack.Pop(); if (val1.IsNull()) valueStack.Push(val1); else valueStack.PushUnknown(); } void Emulate_Isinst(Instruction instr) { var val1 = valueStack.Pop(); if (val1.IsNull()) valueStack.Push(val1); else valueStack.PushUnknown(); } void Emulate_Ldfld(Instruction instr) { /*var val1 =*/ valueStack.Pop(); EmulateLoadField(instr.Operand as IField); } void Emulate_Ldsfld(Instruction instr) { EmulateLoadField(instr.Operand as IField); } void EmulateLoadField(IField field) { if (field != null) valueStack.Push(GetUnknownValue(field.FieldSig.GetFieldType())); else valueStack.PushUnknown(); } void EmulateIntOps2() { var val2 = valueStack.Pop(); var val1 = valueStack.Pop(); if (val1.IsInt32() && val2.IsInt32()) valueStack.Push(Int32Value.CreateUnknown()); else if (val1.IsInt64() && val2.IsInt64()) valueStack.Push(Int64Value.CreateUnknown()); else valueStack.PushUnknown(); } } }