public TStackFrame BuildAndExecute(List <ILInstruction> stream, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null) { return(BuildAndExecute(stream, 0, resolver, args, locals)); }
public TStackFrame Build(List <OpCode> opCodes, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null) { var streamWriter = new ILInstructionWriter(opCodes); var stream = streamWriter.GetInstructionStream(); return(Build(stream, resolver, args, locals)); }
public TStackFrame BuildAndExecute(List <OpCode> opCodes, int timeout, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null) { var frame = Build(opCodes, resolver, args, locals); Execute(frame, timeout); return(frame); }
protected TStackFrame BuildTestFrame(List <ILInstruction> stream, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null) { var result = NewFrame(); result.Stream = stream; result.Resolver = resolver; result.Args = args; result.Locals = locals; result.Reset(); return(result); }
public TStackFrame Build(List <ILInstruction> stream, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null) { var result = new TStackFrame { Stream = stream, Resolver = resolver, Args = args, Locals = locals }; return(result); }
//Execution using strongly typed enumerations. Working implementation will be converted native integer values // to allow native MSIL instruction public object ExecuteTyped(List <ILInstruction> stream, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null, ILOperandStack frameStack = null) { //getArglistHandle(__arglist(1, 2, "s", 8)); <-- can't support dynamic/reflection based invocation // probably best we can do is detect varargs, convert them to object[] and reinterprit msil. // for now will just have to throw excpetion. if (resolver is null) { resolver = ILInstructionResolver.ExecutingAssemblyResolver; } var resolveField = resolver.ResolveFieldToken; var resolveMember = resolver.ResolveMemberToken; var resolveMethod = resolver.ResolveMethodToken; var resolveSignature = resolver.ResolveSignatureToken; var resolveString = resolver.ResolveStringToken; var resolveType = resolver.ResolveTypeToken; var stack = frameStack ?? new ILOperandStack(); ILInstruction current; OpCode code; int pos = -1; Dictionary <int, int> jmptable = stream.ToDictionary(x => (int)x.ByteIndex, x => ++ pos); pos = -1; goto Inc; ReadNext: current = stream[pos]; code = current.OpCode; short opCodeValue = code.Value; switch (opCodeValue) { case (short)ILOpCodeValues.Nop: break; case (short)ILOpCodeValues.Ret: goto Ret; case (short)ILOpCodeValues.Stloc_0: locals[0].Value = stack.Pop(); break; case (short)ILOpCodeValues.Stloc_1: locals[1].Value = stack.Pop(); break; case (short)ILOpCodeValues.Stloc_2: locals[2].Value = stack.Pop(); break; case (short)ILOpCodeValues.Stloc_3: locals[3].Value = stack.Pop(); break; case unchecked ((short)ILOpCodeValues.Stloc): locals[(int)current.Arg].Value = stack.Pop(); break; case (short)ILOpCodeValues.Stloc_S: locals[(byte)current.Arg].Value = stack.Pop(); break; case (short)ILOpCodeValues.Stobj: throw new NotImplementedException(); case (short)ILOpCodeValues.Ldloc_0: stack.Push(locals[0].Value); break; case (short)ILOpCodeValues.Ldloc_1: stack.Push(locals[1].Value); break; case (short)ILOpCodeValues.Ldloc_2: stack.Push(locals[2].Value); break; case (short)ILOpCodeValues.Ldloc_3: stack.Push(locals[3].Value); break; case unchecked ((short)ILOpCodeValues.Ldloc): stack.Push(locals[(int)current.Arg].Value); break; case (short)ILOpCodeValues.Ldloc_S: stack.Push(locals[(byte)current.Arg].Value); break; case unchecked ((short)ILOpCodeValues.Ldloca): stack.Push(locals[(int)current.Arg]); break; case (short)ILOpCodeValues.Ldloca_S: stack.Push(locals[(byte)current.Arg]); break; case (short)ILOpCodeValues.Ldarg_0: stack.Push(args[0]); break; case (short)ILOpCodeValues.Ldarg_1: stack.Push(args[1]); break; case (short)ILOpCodeValues.Ldarg_2: stack.Push(args[2]); break; case (short)ILOpCodeValues.Ldarg_3: stack.Push(args[3]); break; case unchecked ((short)ILOpCodeValues.Ldarg): stack.Push(args[(int)current.Arg]); break; case unchecked ((short)ILOpCodeValues.Ldarg_S): stack.Push(args[(byte)current.Arg]); break; case (short)ILOpCodeValues.Ldarga_S: stack.Push(args[(byte)current.Arg]); break; case unchecked ((short)ILOpCodeValues.Ldarga): stack.Push(args[(int)current.Arg]); break; case (short)ILOpCodeValues.Ldc_I4: stack.Push((int)current.Arg); break; case (short)ILOpCodeValues.Ldc_I4_0: stack.Push(0); break; case (short)ILOpCodeValues.Ldc_I4_1: stack.Push(1); break; case (short)ILOpCodeValues.Ldc_I4_2: stack.Push(2); break; case (short)ILOpCodeValues.Ldc_I4_3: stack.Push(3); break; case (short)ILOpCodeValues.Ldc_I4_4: stack.Push(4); break; case (short)ILOpCodeValues.Ldc_I4_5: stack.Push(5); break; case (short)ILOpCodeValues.Ldc_I4_6: stack.Push(6); break; case (short)ILOpCodeValues.Ldc_I4_7: stack.Push(7); break; case (short)ILOpCodeValues.Ldc_I4_8: stack.Push(8); break; case (short)ILOpCodeValues.Ldc_I4_S: stack.Push(Convert.ToInt32(current.Arg)); break; case (short)ILOpCodeValues.Ldc_I4_M1: stack.Push(-1); break; case (short)ILOpCodeValues.Ldc_I8: stack.Push(Convert.ToInt64(current.Arg)); break; case (short)ILOpCodeValues.Ldc_R4: stack.Push(Convert.ToSingle(current.Arg)); break; case (short)ILOpCodeValues.Ldc_R8: stack.Push(Convert.ToDouble(current.Arg)); break; case (short)ILOpCodeValues.Box: // 140: //box stack.Push(((object)stack.Pop())); break; case (short)ILOpCodeValues.Ckfinite: // 195: //ckfinite var ckval = stack.Pop(); stack.Push((ckval is float?float.IsInfinity((float)ckval) : double.IsInfinity((double)ckval))); break; case (short)ILOpCodeValues.Conv_I1: // 103: //conv.i1 stack.Push(unchecked ((sbyte)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_I2: //104: //conv.i2 stack.Push(unchecked ((short)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_I4: //105: //conv.i4 stack.Push(unchecked ((int)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_I8: //106: //conv.i8 { var arg = stack.Pop(); try { stack.Push(unchecked (Convert.ToInt64(arg))); } catch { stack.Push(unchecked ((long)Convert.ToUInt64(arg))); } } break; case (short)ILOpCodeValues.Conv_Ovf_I1: //179: //conv.ovf.i1 stack.Push(checked ((sbyte)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_I1_Un: //130: //conv.ovf.i1.un stack.Push(checked ((sbyte)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_I2: //181: //conv.ovf.i2 stack.Push(checked ((short)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_I2_Un: //131: //conv.ovf.i2.un stack.Push(checked ((short)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_I4: //183: //conv.ovf.i4 stack.Push(checked ((int)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_I4_Un: //132: //conv.ovf.i4.un stack.Push(checked ((int)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_I8: //185: //conv.ovf.i8 stack.Push(checked ((long)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_I8_Un: //133: //conv.ovf.i8.un stack.Push(checked ((long)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U1: //180: //conv.ovf.u1 stack.Push(checked ((byte)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U1_Un: //134: //conv.ovf.u1.un stack.Push(checked ((byte)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U2: //182: //conv.ovf.u2 stack.Push(checked ((ushort)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U2_Un: //135: //conv.ovf.u2.un stack.Push(checked ((ushort)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U4: //184: //conv.ovf.u4 stack.Push(checked ((uint)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U4_Un: //136: //conv.ovf.u4.un stack.Push(checked ((uint)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U8: //186: //conv.ovf.u8 stack.Push(checked ((ulong)Convert.ToInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_Ovf_U8_Un: //137: //conv.ovf.u8.un stack.Push(checked ((ulong)Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_R4: //107: //conv.r4 stack.Push(Convert.ToSingle(stack.Pop())); break; case (short)ILOpCodeValues.Conv_R8: //108: //conv.r8 stack.Push(Convert.ToDouble(stack.Pop())); break; case (short)ILOpCodeValues.Conv_R_Un: //118: //conv.r.un stack.Push(Convert.ToSingle(stack.Pop())); break; case (short)ILOpCodeValues.Conv_U1: //210: //conv.u1 stack.Push(unchecked (Convert.ToByte(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_U2: //209: //conv.u2 stack.Push(unchecked (Convert.ToUInt16(stack.Pop()))); break; case (short)ILOpCodeValues.Conv_U4: //109: //conv.u4 stack.Push(unchecked ((uint)(Convert.ToInt64(stack.Pop())))); break; case (short)ILOpCodeValues.Conv_U8: //110: //conv.u8 stack.Push(unchecked (Convert.ToUInt64(stack.Pop()))); break; case (short)ILOpCodeValues.Neg: //101: //neg stack.Push(-((dynamic)stack.Pop())); break; case (short)ILOpCodeValues.Newarr: //141: //newarr stack.Push(Array.CreateInstance(((current.Arg is int) ? resolveType((int)current.Arg) : (Type)current.Arg), (int)stack.Pop())); break; case (short)ILOpCodeValues.Not: //102: //not stack.Push(!((dynamic)stack.Pop())); break; case (short)ILOpCodeValues.Pop: //38: //pop stack.Pop(); // no push break; case (short)ILOpCodeValues.Shl: //98: //shl stack.Push(((dynamic)stack.Pop()) << ((int)current.Arg)); break; case (short)ILOpCodeValues.Shr: //99: //shr stack.Push(((dynamic)stack.Pop()) >> ((int)current.Arg)); break; case (short)ILOpCodeValues.Shr_Un: //100: //shr.un stack.Push(((dynamic)stack.Pop()) >> ((int)current.Arg)); break; case (short)ILOpCodeValues.Unbox: //121: //unbox stack.Push(Convert.ChangeType(stack.Pop(), resolveType((int)current.Arg))); break; case (short)ILOpCodeValues.Unbox_Any: //165: //unbox.any stack.Push(Convert.ChangeType(stack.Pop(), resolveType((int)current.Arg))); break; case (short)ILOpCodeValues.Add: //: //add stack.Push(unchecked ((dynamic)stack.Pop() + (dynamic)stack.Pop())); break; case (short)ILOpCodeValues.Add_Ovf: // 214: //add.ovf stack.Push(checked ((dynamic)stack.Pop() + (dynamic)stack.Pop())); break; case (short)ILOpCodeValues.Add_Ovf_Un: // 215: //add.ovf.un stack.Push(checked ((dynamic)stack.Pop() + (dynamic)stack.Pop())); break; case (short)ILOpCodeValues.And: //95: //and stack.Push(((dynamic)stack.Pop()) & ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Ceq): //: //ceq { var opa = stack.Pop(); var opb = stack.Pop(); if (opa is IConvertible && opb is IConvertible) { var compc = ((IComparable)(opa)).CompareTo(Convert.ChangeType(opb, Convert.GetTypeCode(opa))); stack.Push(compc == 0 ? 1 : 0); } else { stack.Push(Convert.ToInt32(((dynamic)opa) == ((dynamic)opb))); } } break; case unchecked ((short)ILOpCodeValues.Cgt): // -510: //cgt stack.Push(Convert.ToInt32(((dynamic)stack.Pop()) < ((dynamic)stack.Pop()))); break; case unchecked ((short)ILOpCodeValues.Cgt_Un): //- 509: //cgt.un stack.Push(Convert.ToInt32(((dynamic)stack.Pop()) < ((dynamic)stack.Pop()))); break; case unchecked ((short)ILOpCodeValues.Clt): // -508: //clt stack.Push(Convert.ToInt32(((dynamic)stack.Pop()) > ((dynamic)stack.Pop()))); //either swap pop order or sign break; case unchecked ((short)ILOpCodeValues.Clt_Un): // -507: //clt.un stack.Push(Convert.ToInt32(((dynamic)stack.Pop()) > ((dynamic)stack.Pop()))); break; case unchecked ((short)ILOpCodeValues.Div): // 91: //div stack.Push(((dynamic)stack.Pop()) / ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Div_Un): // 92: //div.un stack.Push(((dynamic)stack.Pop()) / ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Mul): // 90: //mul stack.Push(unchecked (((dynamic)stack.Pop()) * ((dynamic)stack.Pop()))); break; case unchecked ((short)ILOpCodeValues.Mul_Ovf): // 216: //mul.ovf stack.Push(((dynamic)stack.Pop()) * ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Mul_Ovf_Un): // 217: //mul.ovf.un stack.Push(((dynamic)stack.Pop()) * ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Or): // 96: //or stack.Push(((dynamic)stack.Pop()) | ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Rem): // 93: //rem stack.Push(((dynamic)stack.Pop()) % ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Rem_Un): // 94: //rem.un stack.Push(((dynamic)stack.Pop()) % ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Sub): // 89: //sub stack.Push(unchecked (((dynamic)stack.Pop()) - ((dynamic)stack.Pop()))); break; case unchecked ((short)ILOpCodeValues.Sub_Ovf): // 218: //sub.ovf stack.Push(((dynamic)stack.Pop()) - ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Sub_Ovf_Un): // 219: //sub.ovf.un stack.Push(((dynamic)stack.Pop()) - ((dynamic)stack.Pop())); break; case unchecked ((short)ILOpCodeValues.Xor): // 97: //xor stack.Push(((dynamic)stack.Pop()) ^ ((dynamic)stack.Pop())); break; case (short)ILOpCodeValues.Ldstr: { if (current.Arg is string) { stack.Push((string)current.Arg); } else { stack.Push(resolveString((int)current.Arg)); } break; } case (short)ILOpCodeValues.Newobj: { var ctor = (System.Reflection.ConstructorInfo)resolveMethod((int)current.Arg); var ctorArgs = new object[ctor.GetParameters().Length]; for (var i = ctorArgs.Length - 1; i > -1; i--) { ctorArgs[i] = stack.Pop(); } //var reversed = ctorArgs.Reverse().ToArray(); var ctorResult = ctor.Invoke(ctorArgs); stack.Push(ctorResult); break; } case (short)ILOpCodeValues.Ldfld: { var field = resolveField((int)current.Arg); var target = stack.Pop(); var value = field.GetValue(target); stack.Push(value); break; } case (short)ILOpCodeValues.Ldsfld: { var field = resolveField((int)current.Arg); var value = field.GetValue(null); stack.Push(value); break; } case (short)ILOpCodeValues.Stfld: { var field = resolveField((int)current.Arg); var fo = stack.Pop(); var target = stack.Pop(); field.SetValue(target, fo); //stack.Push(value); break; } case (short)ILOpCodeValues.Stsfld: { var field = resolveField((int)current.Arg); var fo = stack.Pop(); //var target = stack.Pop(); field.SetValue(null, fo); break; } case (short)ILOpCodeValues.Ldlen: { var array = stack.Pop(); var arr = (Array)array; stack.Push(arr.Length); break; } case (short)ILOpCodeValues.Stelem: { object el = stack.Pop(); int index = (int)stack.Pop(); var array = (Array)stack.Pop(); array.GetType() .GetMethod("SetValue", new[] { typeof(object), typeof(int) }) .Invoke(array, new object[] { el, index }); break; } case (short)ILOpCodeValues.Stelem_I1: { object el = stack.Pop(); int index = (int)stack.Pop(); var array = stack.Pop(); var arrType = array.GetType(); var arrElType = arrType.GetElementType(); var elType = el.GetType(); if (elType == arrElType) { ((Array)array).SetValue(el, index); } else if (arrElType == typeof(sbyte)) { ((sbyte[])array)[index] = (sbyte)(int)el; } else { ((byte[])array)[index] = (byte)(int)el; } break; } case (short)ILOpCodeValues.Stelem_I2: { object el = stack.Pop(); int index = (int)stack.Pop(); var array = stack.Pop(); var arrType = array.GetType(); var arrElType = arrType.GetElementType(); var elType = el.GetType(); if (elType == arrElType) { ((Array)array).SetValue(el, index); } else if (arrElType == typeof(short)) { ((Array)array).SetValue((short)(int)el, index); } else if (arrElType == typeof(short)) { ((Array)array).SetValue((ushort)(int)el, index); } else { ((Array)array).SetValue(Convert.ChangeType(el, arrElType), index); } break; } case (short)ILOpCodeValues.Stelem_I4: { object el = stack.Pop(); int index = (int)stack.Pop(); var array = stack.Pop(); var arrType = array.GetType(); var arrElType = arrType.GetElementType(); var elType = el.GetType(); if (elType == arrElType) { ((Array)array).SetValue(el, index); } else if (arrElType == typeof(int)) { ((int[])array)[index] = (int)el; } else { ((uint[])array)[index] = (uint)el; } break; } case (short)ILOpCodeValues.Stelem_I8: { object el = stack.Pop(); int index = (int)stack.Pop(); var array = stack.Pop(); var arrType = array.GetType(); var arrElType = arrType.GetElementType(); var elType = el.GetType(); if (elType == arrElType) { ((Array)array).SetValue(el, index); } else if (arrElType == typeof(long)) { ((long[])array)[index] = (long)el; } else { ((ulong[])array)[index] = (ulong)el; } break; } case (short)ILOpCodeValues.Stelem_R4: { object el = stack.Pop(); int index = (int)stack.Pop(); var array = stack.Pop(); var arrType = array.GetType(); var arrElType = arrType.GetElementType(); var elType = el.GetType(); if (elType == arrElType) { ((Array)array).SetValue(el, index); } else if (arrElType == typeof(float)) { ((float[])array)[index] = (float)el; } //else ((ulong[])array)[index] = (ulong)el; break; } case (short)ILOpCodeValues.Stelem_R8: { object el = stack.Pop(); int index = (int)stack.Pop(); var array = stack.Pop(); var arrType = array.GetType(); var arrElType = arrType.GetElementType(); var elType = el.GetType(); if (elType == arrElType) { ((Array)array).SetValue(el, index); } else if (arrElType == typeof(double)) { ((double[])array)[index] = (double)el; } //else ((ulong[])array)[index] = (ulong)el; break; } case (short)ILOpCodeValues.Stelem_Ref: { object val = stack.Pop(); int index = (int)stack.Pop(); var array = stack.Pop(); ((Array)array).SetValue(val, index); break; } case (short)ILOpCodeValues.Ldelem: case (short)ILOpCodeValues.Ldelema: case (short)ILOpCodeValues.Ldelem_I: case (short)ILOpCodeValues.Ldelem_Ref: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); stack.Push(val); break; } case (short)ILOpCodeValues.Ldelem_I1: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = (sbyte)Convert.ToInt32(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_I2: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = (short)Convert.ToInt32(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_I4: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = Convert.ToInt32(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_I8: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = Convert.ToInt64(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_U1: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = (byte)Convert.ToUInt32(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_U2: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = (ushort)Convert.ToUInt32(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_U4: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = Convert.ToUInt32(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_R4: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = Convert.ToSingle(val); stack.Push(target); break; } case (short)ILOpCodeValues.Ldelem_R8: { var idx = (int)stack.Pop(); var array = (Array)stack.Pop(); var val = array.GetValue(idx); var target = Convert.ToDouble(val); stack.Push(target); break; } case (short)ILOpCodeValues.Conv_I: case (short)ILOpCodeValues.Conv_Ovf_I_Un: case (short)ILOpCodeValues.Conv_Ovf_I: //Todo: native int operations throw new OpCodeNotImplementedException(code); case (short)ILOpCodeValues.Dup: stack.Push(stack.Peek()); break; //TODO: Implemented scopre validation for branch: (EG, inside try, catch, finally,etc) case (short)ILOpCodeValues.Leave_S: case (short)ILOpCodeValues.Br_S: //0x2b: { var delta = (int)(sbyte)Convert.ToByte(current.Arg); var directpos = (int)stream[pos + 1].ByteIndex + delta; pos = jmptable[directpos]; goto MoveNext; } case (short)ILOpCodeValues.Leave: case (short)ILOpCodeValues.Br: // 0x38: { var delta = Convert.ToInt32(current.Arg); var directpos = (int)stream[pos + 1].ByteIndex + delta; pos = jmptable[directpos]; goto MoveNext; } case (short)ILOpCodeValues.Beq: { var opa = stack.Pop(); var opb = stack.Pop(); if (opa is IConvertible && opb is IConvertible) { var compc = ((IComparable)(opa)).CompareTo(Convert.ChangeType(opb, Convert.GetTypeCode(opa))); stack.Push(compc == 0 ? 1 : 0); } else { stack.Push(Convert.ToInt32(((dynamic)opa) == ((dynamic)opb))); } goto case (short)ILOpCodeValues.Brtrue; } case (short)ILOpCodeValues.Beq_S: { var opa = stack.Pop(); var opb = stack.Pop(); if (opa is IConvertible && opb is IConvertible) { var compc = ((IComparable)(opa)).CompareTo(Convert.ChangeType(opb, Convert.GetTypeCode(opa))); stack.Push(compc == 0 ? 1 : 0); } else { stack.Push(Convert.ToInt32(((dynamic)opa) == ((dynamic)opb))); } goto case (short)ILOpCodeValues.Brtrue_S; } case (short)ILOpCodeValues.Brfalse: //00111001 { var chk = stack.Pop(); int cond = Convert.ToInt32((chk is IConvertible) ? Convert.ToBoolean(chk) : Convert.ToBoolean(!(chk is null))); var condtarget = -1; if (cond == 0) { condtarget = (int)stream[pos + 1].ByteIndex + Convert.ToInt32(current.Arg); pos = jmptable[condtarget]; goto MoveNext; } break; } case (short)ILOpCodeValues.Brfalse_S: { var chk = stack.Pop(); int cond = Convert.ToInt32((chk is IConvertible) ? Convert.ToBoolean(chk) : Convert.ToBoolean(!(chk is null))); var condtarget = -1; if (cond == 0) { condtarget = (int)stream[pos + 1].ByteIndex + (int)(sbyte)Convert.ToByte(current.Arg); pos = jmptable[condtarget]; goto MoveNext; } break; } case (short)ILOpCodeValues.Brtrue: { var chk = stack.Pop(); int cond = Convert.ToInt32((chk is IConvertible) ? Convert.ToBoolean(chk) : Convert.ToBoolean(!(chk is null))); var condtarget = -1; if (cond == 1) { condtarget = (int)stream[pos + 1].ByteIndex + Convert.ToInt32(current.Arg); pos = jmptable[condtarget]; goto MoveNext; } break; } case (short)ILOpCodeValues.Brtrue_S: { var chk = stack.Pop(); int cond = Convert.ToInt32((chk is IConvertible) ? Convert.ToBoolean(chk) : Convert.ToBoolean(!(chk is null))); var condtarget = -1; if (cond == 1) { condtarget = (int)stream[pos + 1].ByteIndex + (int)(sbyte)Convert.ToByte(current.Arg); pos = jmptable[condtarget]; goto MoveNext; } break; } case (short)ILOpCodeValues.Call: case (short)ILOpCodeValues.Calli: case (short)ILOpCodeValues.Callvirt: System.Reflection.MethodBase method = null; object resolved = null; if (current.Arg is System.Reflection.MethodInfo) { method = (System.Reflection.MethodInfo)current.Arg; } else { resolved = resolveMethod((int)current.Arg); } if (resolved is ConstructorInfo) { method = (ConstructorInfo)resolved; } else { method = (System.Reflection.MethodInfo)resolved; } var parameters = method.GetParameters(); var methodArgs = new object[parameters.Length]; for (var i = methodArgs.Length - 1; i >= 0; i--) { var val = stack.Pop(); if (val is ILVariable) { methodArgs[i] = ((ILVariable)(val)).Value; } else { methodArgs[i] = val; } } object methodTarget = null; if (!method.IsStatic && !method.IsConstructor) { methodTarget = stack.Pop(); } if (methodTarget is ILVariable) { methodTarget = ((ILVariable)methodTarget).Value; } //var t = default(RuntimeTypeHandle); //var t1 = default(ArgIterator); //var tobject = new object[] { t, t }; //var del = Delegate.CreateDelegate() //((ConstructorInfo)method).Invoke( new object[]{ t}); for (var i = methodArgs.Length - 1; i >= 0; i--) { if (methodArgs[i] is IConvertible) { methodArgs[i] = Convert.ChangeType(methodArgs[i], parameters[i].ParameterType); } } //if the current method is invoking another method then convert the arguments for the inner method. if (methodTarget is MethodBase && methodArgs.Length == 2 && methodArgs[1] is Array) { var invokeArgs = (Array)methodArgs[1]; var invokeParameters = ((MethodInfo)methodTarget).GetParameters(); for (var i = invokeArgs.Length - 1; i >= 0; i--) { var arg = invokeArgs.GetValue(i); if (arg is IConvertible) { invokeArgs.SetValue(Convert.ChangeType(arg, invokeParameters[i].ParameterType), i); } } //if (invokeArgs.GetValue(i) is IConvertible) // invokeArgs.SetValue(Convert.ChangeType(invokeArgs[i], invokeParameters[i].ParameterType)); } // Roadblock here: Int.CompareTo(object value) -> argument value must be of type int but there is no way to programatically determine the expected destination type. var methodresult = (method is MethodInfo) ? method.Invoke(methodTarget, methodArgs) : ((ConstructorInfo)method).Invoke(methodArgs); if (code.StackBehaviourPush == StackBehaviour.Varpush) { if ((method as MethodInfo)?.ReturnType != typeof(void) || method.IsConstructor) { stack.Push(methodresult); } } break; case unchecked ((short)ILOpCodeValues.Ldobj): stack.Push(current.Arg); break; case (short)ILOpCodeValues.Ldnull: stack.Push(null); break; case unchecked ((short)ILOpCodeValues.Ldftn): var ftnToken = (int)current.Arg; var ftnMethod = resolver.ResolveMethodToken(ftnToken); stack.Push(ftnMethod.MethodHandle.GetFunctionPointer()); break; case unchecked ((short)ILOpCodeValues.Initobj): var newObj = Activator.CreateInstance(resolver.ResolveTypeToken((int)current.Arg)); var inst = stack.Pop(); if (inst is ILVariable ilvar) { ilvar.Value = newObj; locals[ilvar.Index] = ilvar; } else { inst = newObj; } break; case (short)ILOpCodeValues.Ldtoken: var metaToken = (int)current.Arg; var memToken = resolver.ResolveMemberToken(metaToken); var tokenType = memToken.GetType(); switch (tokenType.Name) { case "RtFieldInfo": { var fieldInfo = resolver.ResolveFieldToken(metaToken); var handle = (FieldInfo)fieldInfo; stack.Push(handle.FieldHandle); } break; case "RuntimeType": { var type = resolver.ResolveTypeToken(metaToken); var handle = (Type)type; stack.Push(handle.TypeHandle); } break; default: throw new OpCodeNotImplementedException(code); } break; case (short)ILOpCodeValues.Castclass: var targetClassToken = (int)current.Arg; var targetType = resolver.ResolveTypeToken(targetClassToken); var listType = typeof(List <>).MakeGenericType(new[] { targetType }); var instance = Activator.CreateInstance(listType); var prop = listType.GetProperty("Item"); var src = stack.Pop(); var add = listType.GetMethod("Add"); add.Invoke(instance, new[] { src }); var get = listType.GetMethod("get_Item"); var listresult = get.Invoke(instance, new object[] { 0 }); stack.Push(listresult); break; case (short)ILOpCodeValues.Break: if (TriggerBreak) { System.Diagnostics.Debugger.Break(); } break; default: throw new OpCodeNotImplementedException(code); } Inc: pos++; MoveNext: if (pos < stream.Count) { goto ReadNext; } Ret: var result = (stack.Count > 0) ? stack.Pop() : null; if (TriggerBreak) { System.Diagnostics.Debug.Assert(stack.Count == 0); } else { //if (stack.Count > 0) throw new InvalidProgramException("Stack is not empty {stack.Count}"); } return(result); }
public T ExecuteTyped <T>(List <ILInstruction> stream, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null) { var result = ExecuteTyped(stream, resolver, args, locals); return((T)result); }
public object ExecuteTyped(Stream stream, IILInstructionResolver resolver = null, object[] args = null, ILVariable[] locals = null) { var stack = new Stack <object>(); var br = new BinaryReader(stream); int op = 0; int i = 0; MethodBase method = null; Type type; object obj = null; object[] arr = null; Read: op = stream.ReadByte(); //Execute: // can we keep tables at 255 to implement br_S. else jumps will be BR and use 4 bytes. // to implement need two switches to keep table at 127 entries switch (op) { case 0: goto Nop; // 0x00 case 1: goto Break; // 0x01 case 2: goto Ldarg_0; // 0x02 case 3: goto Ldarg_1; // 0x03 case 4: goto Ldarg_2; // 0x04 case 5: goto Ldarg_3; // 0x05 case 6: goto Ldloc_0; // 0x06 case 7: goto Ldloc_1; // 0x07 case 8: goto Ldloc_2; // 0x08 case 9: goto Ldloc_3; // 0x09 case 10: goto Stloc_0; // 0x0a case 11: goto Stloc_1; // 0x0b case 12: goto Stloc_2; // 0x0c case 13: goto Stloc_3; // 0x0d case 14: goto Ldarg_S; // 0x0e case 15: goto Ldarga_S; // 0x0f case 16: goto Starg_S; // 0x10 case 17: goto Ldloc_S; // 0x11 case 18: goto Ldloca_S; // 0x12 case 19: goto Stloc_S; // 0x13 case 20: goto Ldnull; // 0x14 case 21: goto Ldc_I4_M1; // 0x15 case 22: goto Ldc_I4_0; // 0x16 case 23: goto Ldc_I4_1; // 0x17 case 24: goto Ldc_I4_2; // 0x18 case 25: goto Ldc_I4_3; // 0x19 case 26: goto Ldc_I4_4; // 0x1a case 27: goto Ldc_I4_5; // 0x1b case 28: goto Ldc_I4_6; // 0x1c case 29: goto Ldc_I4_7; // 0x1d case 30: goto Ldc_I4_8; // 0x1e case 31: goto Ldc_I4_S; // 0x1f case 32: goto Ldc_I4; // 0x20 case 33: goto Ldc_I8; // 0x21 case 34: goto Ldc_R4; // 0x22 case 35: goto Ldc_R8; // 0x23 case 36: goto Exec_MSIL_I; // 0x24 case 37: goto Dup; // 0x25 case 38: goto Pop; // 0x26 case 39: goto Jmp; // 0x27 case 40: goto Call; // 0x28 case 41: goto Calli; // 0x29 case 42: goto Ret; // 0x2a case 43: goto Br_S; // 0x2b case 44: goto Brfalse_S; // 0x2c case 45: goto Brtrue_S; // 0x2d case 46: goto Beq_S; // 0x2e case 47: goto Bge_S; // 0x2f case 48: goto Bgt_S; // 0x30 case 49: goto Ble_S; // 0x31 case 50: goto Blt_S; // 0x32 case 51: goto Bne_Un_S; // 0x33 case 52: goto Bge_Un_S; // 0x34 case 53: goto Bgt_Un_S; // 0x35 case 54: goto Ble_Un_S; // 0x36 case 55: goto Blt_Un_S; // 0x37 case 56: goto Br; // 0x38 case 57: goto Brfalse; // 0x39 case 58: goto Brtrue; // 0x3a case 59: goto Beq; // 0x3b case 60: goto Bge; // 0x3c case 61: goto Bgt; // 0x3d case 62: goto Ble; // 0x3e case 63: goto Blt; // 0x3f case 64: goto Bne_Un; // 0x40 case 65: goto Bge_Un; // 0x41 case 66: goto Bgt_Un; // 0x42 case 67: goto Ble_Un; // 0x43 case 68: goto Blt_Un; // 0x44 case 69: goto Switch; // 0x45 case 70: goto Ldind_I1; // 0x46 case 71: goto Ldind_U1; // 0x47 case 72: goto Ldind_I2; // 0x48 case 73: goto Ldind_U2; // 0x49 case 74: goto Ldind_I4; // 0x4a case 75: goto Ldind_U4; // 0x4b case 76: goto Ldind_I8; // 0x4c case 77: goto Ldind_I; // 0x4d case 78: goto Ldind_R4; // 0x4e case 79: goto Ldind_R8; // 0x4f case 80: goto Ldind_Ref; // 0x50 case 81: goto Stind_Ref; // 0x51 case 82: goto Stind_I1; // 0x52 case 83: goto Stind_I2; // 0x53 case 84: goto Stind_I4; // 0x54 case 85: goto Stind_I8; // 0x55 case 86: goto Stind_R4; // 0x56 case 87: goto Stind_R8; // 0x57 case 88: goto Add; // 0x58 case 89: goto Sub; // 0x59 case 90: goto Mul; // 0x5a case 91: goto Div; // 0x5b case 92: goto Div_Un; // 0x5c case 93: goto Rem; // 0x5d case 94: goto Rem_Un; // 0x5e case 95: goto And; // 0x5f case 96: goto Or; // 0x60 case 97: goto Xor; // 0x61 case 98: goto Shl; // 0x62 case 99: goto Shr; // 0x63 case 100: goto Shr_Un; // 0x64 case 101: goto Neg; // 0x65 case 102: goto Not; // 0x66 case 103: goto Conv_I1; // 0x67 case 104: goto Conv_I2; // 0x68 case 105: goto Conv_I4; // 0x69 case 106: goto Conv_I8; // 0x6a case 107: goto Conv_R4; // 0x6b case 108: goto Conv_R8; // 0x6c case 109: goto Conv_U4; // 0x6d case 110: goto Conv_U8; // 0x6e case 111: goto Callvirt; // 0x6f case 112: goto Cpobj; // 0x70 case 113: goto Ldobj; // 0x71 case 114: goto Ldstr; // 0x72 case 115: goto Newobj; // 0x73 case 116: goto Castclass; // 0x74 case 117: goto Isinst; // 0x75 case 118: goto Conv_R_Un; // 0x76 case 119: goto Exec_MSIL_S; // 0x77 case 120: goto NotSupported_S; //0x78 case 121: goto Unbox; // 0x79 case 122: goto Throw; // 0x7a case 123: goto Ldfld; // 0x7b case 124: goto Ldflda; // 0x7c case 125: goto Stfld; // 0x7d case 126: goto Ldsfld; // 0x7e case 127: goto Ldsflda; // 0x7f case 128: goto Stsfld; // 0x80 case 129: goto Stobj; // 0x81 case 130: goto Conv_Ovf_I1_Un; // 0x82 case 131: goto Conv_Ovf_I2_Un; // 0x83 case 132: goto Conv_Ovf_I4_Un; // 0x84 case 133: goto Conv_Ovf_I8_Un; // 0x85 case 134: goto Conv_Ovf_U1_Un; // 0x86 case 135: goto Conv_Ovf_U2_Un; // 0x87 case 136: goto Conv_Ovf_U4_Un; // 0x88 case 137: goto Conv_Ovf_U8_Un; // 0x89 case 138: goto Conv_Ovf_I_Un; // 0x8a case 139: goto Conv_Ovf_U_Un; // 0x8b case 140: goto Box; // 0x8c case 141: goto Newarr; // 0x8d case 142: goto Ldlen; // 0x8e case 143: goto Ldelema; // 0x8f case 144: goto Ldelem_I1; // 0x90 case 145: goto Ldelem_U1; // 0x91 case 146: goto Ldelem_I2; // 0x92 case 147: goto Ldelem_U2; // 0x93 case 148: goto Ldelem_I4; // 0x94 case 149: goto Ldelem_U4; // 0x95 case 150: goto Ldelem_I8; // 0x96 case 151: goto Ldelem_I; // 0x97 case 152: goto Ldelem_R4; // 0x98 case 153: goto Ldelem_R8; // 0x99 case 154: goto Ldelem_Ref; // 0x9a case 155: goto Stelem_I; // 0x9b case 156: goto Stelem_I1; // 0x9c case 157: goto Stelem_I2; // 0x9d case 158: goto Stelem_I4; // 0x9e case 159: goto Stelem_I8; // 0x9f case 160: goto Stelem_R4; // 0xa0 case 161: goto Stelem_R8; // 0xa1 case 162: goto Stelem_Ref; // 0xa2 case 163: goto Ldelem; // 0xa3 case 164: goto Stelem; // 0xa4 case 165: goto Unbox_Any; // 0xa5 case 166: goto NotSupported_S; //0xA6 case 167: goto NotSupported_S; //0xA7 case 168: goto NotSupported_S; //0xA8 case 169: goto NotSupported_S; //0xA9 case 170: goto NotSupported_S; //0xAA case 171: goto NotSupported_S; //0xAB case 172: goto NotSupported_S; //0xAC case 173: goto NotSupported_S; //0xAD case 174: goto NotSupported_S; //0xAE case 175: goto NotSupported_S; //0xAF case 176: goto NotSupported_S; //0xB0 case 177: goto NotSupported_S; //0xB1 case 178: goto NotSupported_S; //0xB2 case 179: goto Conv_Ovf_I1; // 0xb3 case 180: goto Conv_Ovf_U1; // 0xb4 case 181: goto Conv_Ovf_I2; // 0xb5 case 182: goto Conv_Ovf_U2; // 0xb6 case 183: goto Conv_Ovf_I4; // 0xb7 case 184: goto Conv_Ovf_U4; // 0xb8 case 185: goto Conv_Ovf_I8; // 0xb9 case 186: goto Conv_Ovf_U8; // 0xba case 187: goto NotSupported_S; //0xBB case 188: goto NotSupported_S; //0xBC case 189: goto NotSupported_S; //0xBD case 190: goto NotSupported_S; //0xBE case 191: goto NotSupported_S; //0xBF case 192: goto NotSupported_S; //0xC0 case 193: goto NotSupported_S; //0xC1 case 194: goto Refanyval; // 0xc2 case 195: goto Ckfinite; // 0xc3 case 196: goto NotSupported_S; //0xC4 case 197: goto NotSupported_S; //0xC5 case 198: goto Mkrefany; // 0xc6 case 199: goto NotSupported_S; //0xC7 case 200: goto NotSupported_S; //0xC8 case 201: goto NotSupported_S; //0xC9 case 202: goto NotSupported_S; //0xCA case 203: goto NotSupported_S; //0xCB case 204: goto NotSupported_S; //0xCC case 205: goto NotSupported_S; //0xCD case 206: goto NotSupported_S; //0xCE case 207: goto NotSupported_S; //0xCF case 208: goto Ldtoken; // 0xd0 case 209: goto Conv_U2; // 0xd1 case 210: goto Conv_U1; // 0xd2 case 211: goto Conv_I; // 0xd3 case 212: goto Conv_Ovf_I; // 0xd4 case 213: goto Conv_Ovf_U; // 0xd5 case 214: goto Add_Ovf; // 0xd6 case 215: goto Add_Ovf_Un; // 0xd7 case 216: goto Mul_Ovf; // 0xd8 case 217: goto Mul_Ovf_Un; // 0xd9 case 218: goto Sub_Ovf; // 0xda case 219: goto Sub_Ovf_Un; // 0xdb case 220: goto Endfinally; // 0xdc case 221: goto Leave; // 0xdd case 222: goto Leave_S; // 0xde case 223: goto Stind_I; // 0xdf case 224: goto Conv_U; // 0xe0 case 225: goto NotSupported_S; //0xE1 case 226: goto NotSupported_S; //0xE2 case 227: goto NotSupported_S; //0xE3 case 228: goto NotSupported_S; //0xE4 case 229: goto NotSupported_S; //0xE5 case 230: goto NotSupported_S; //0xE6 case 231: goto NotSupported_S; //0xE7 case 232: goto NotSupported_S; //0xE8 case 233: goto NotSupported_S; //0xE9 case 234: goto NotSupported_S; //0xEA case 235: goto NotSupported_S; //0xEB case 236: goto NotSupported_S; //0xEC case 237: goto NotSupported_S; //0xED case 238: goto NotSupported_S; //0xEE case 239: goto NotSupported_S; //0xEF case 240: goto NotSupported_S; //0xF0 case 241: goto NotSupported_S; //0xF1 case 242: goto NotSupported_S; //0xF2 case 243: goto NotSupported_S; //0xF3 case 244: goto NotSupported_S; //0xF4 case 245: goto NotSupported_S; //0xF5 case 246: goto NotSupported_S; //0xF6 case 247: goto NotSupported_S; //0xF7 case 248: goto Prefix7; // 0xf8 case 249: goto Prefix6; // 0xf9 case 250: goto Prefix5; // 0xfa case 251: goto Prefix4; // 0xfb case 252: goto Prefix3; // 0xfc case 253: goto Prefix2; // 0xfd case 254: goto Prefix1; // 0xfe case 255: goto Prefixref; // 0xff default: throw new NotImplementedException(); } NotSupported_S : goto NotSupported; NotImplemented_S : goto NotImplemented; Nop : goto Read; Break : System.Diagnostics.Debugger.Break(); goto Read; Ldarg_0 : stack.Push(args[0]); goto Read; Ldarg_1 : stack.Push(args[1]); goto Read; Ldarg_2 : stack.Push(args[2]); goto Read; Ldarg_3 : stack.Push(args[3]); goto Read; Ldloc_0 : stack.Push(locals[0].Value); goto Read; Ldloc_1 : stack.Push(locals[1].Value); goto Read; Ldloc_2 : stack.Push(locals[2].Value); goto Read; Ldloc_3 : stack.Push(locals[3].Value); goto Read; Stloc_0 : locals[0].Value = stack.Pop(); goto Read; Stloc_1 : locals[2].Value = stack.Pop(); goto Read; Stloc_2 : locals[3].Value = stack.Pop(); goto Read; Stloc_3 : locals[4].Value = stack.Pop(); goto Read; Ldarg_S : stack.Push(args[stream.ReadByte()]); goto Read; Ldarga_S : stack.Push(args[stream.ReadByte()]); goto Read; Starg_S : args[stream.ReadByte()] = stack.Pop(); goto Read; Ldloc_S : stack.Push(locals[stream.ReadByte()].Value); goto Read; Ldloca_S : stack.Push(locals[stream.ReadByte()].Value); goto Read; Stloc_S : locals[stream.ReadByte()].Value = stack.Pop(); goto Read; Ldnull : stack.Push(null); goto Read; Ldc_I4_M1 : stack.Push(-1); goto Read; Ldc_I4_0 : stack.Push(0); goto Read; Ldc_I4_1 : stack.Push(1); goto Read; Ldc_I4_2 : stack.Push(2); goto Read; Ldc_I4_3 : stack.Push(3); goto Read; Ldc_I4_4 : stack.Push(4); goto Read; Ldc_I4_5 : stack.Push(5); goto Read; Ldc_I4_6 : stack.Push(6); goto Read; Ldc_I4_7 : stack.Push(7); goto Read; Ldc_I4_8 : stack.Push(8); goto Read; Ldc_I4_S : stack.Push(stream.ReadByte()); goto Read; Ldc_I4 : stack.Push(br.ReadInt32()); goto Read; Ldc_I8 : stack.Push(br.ReadInt64()); goto Read; Ldc_R4 : stack.Push(br.ReadSingle()); goto Read; Ldc_R8 : stack.Push(br.ReadDouble()); goto Read; Exec_MSIL_I : goto NotSupported_S; Dup : stack.Push(stack.Peek()); goto Read; Pop : stack.Pop(); goto Read; Jmp : goto NotImplemented_S; Call: method = resolver.ResolveMethodToken(br.ReadInt32()); arr = new object[method.GetParameters().Length]; for (i = arr.Length - 1; i >= 0; i--) { arr[i] = stack.Pop(); } var methodResult = method.Invoke(method.IsStatic ? null : stack.Pop(), arr); if (((MethodInfo)method).ReturnType != typeof(void)) { stack.Push(methodResult); } goto Read; Calli : goto Call; Ret : goto RetResult; //Br_S: stream.Position += br.ReadByte(); goto Read; //Brfalse_S: //jmp = stream.ReadByte(); if ((int)stack.Pop() == 0) stream.Position += jmp; goto Read; //Brtrue_S: jmp = stream.ReadByte(); if ((int)stack.Pop() == 1) stream.Position += jmp; goto Read; //Beq_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() == (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bge_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() <= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bgt_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() < (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Ble_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() >= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Blt_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() > (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bne_Un_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() != (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bge_Un_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() <= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bgt_Un_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() < (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Ble_Un_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() >= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Blt_Un_S: jmp = stream.ReadByte(); if ((dynamic)stack.Pop() > (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Br: stream.Position += br.ReadInt32(); goto Execute; //Brfalse: jmp = br.ReadInt32(); if ((int)stack.Pop() == 0) stream.Position += jmp; goto Read; //Brtrue: jmp = br.ReadInt32(); if ((int)stack.Pop() == 1) stream.Position += jmp; goto Read; //Beq: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() == (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bge: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() <= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bgt: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() < (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Ble: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() >= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Blt: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() > (dynamic)stack.Pop()) stream.Position += jmp; goto Read; ; //Bne_Un: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() != (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bge_Un: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() <= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Bgt_Un: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() < (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Ble_Un: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() >= (dynamic)stack.Pop()) stream.Position += jmp; goto Read; //Blt_Un: jmp = br.ReadInt32(); if ((dynamic)stack.Pop() > (dynamic)stack.Pop()) stream.Position += jmp; goto Read; Br_S : stream.Seek(br.ReadByte(), SeekOrigin.Current); goto Read; Brfalse_S : stream.Seek((int)stack.Pop() == 0 ? br.ReadByte() : 1, SeekOrigin.Current); goto Read;//jmp = stream.ReadByte(); if ((int)stack.Pop() == 0) stream.Position += jmp; goto Read; Brtrue_S : stream.Seek((int)stack.Pop() == 1 ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Beq_S : stream.Seek((dynamic)stack.Pop() == (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Bge_S : stream.Seek((dynamic)stack.Pop() <= (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Bgt_S : stream.Seek((dynamic)stack.Pop() < (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Ble_S : stream.Seek((dynamic)stack.Pop() >= (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Blt_S : stream.Seek((dynamic)stack.Pop() > (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Bne_Un_S : stream.Seek((dynamic)stack.Pop() != (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Bge_Un_S : stream.Seek((dynamic)stack.Pop() <= (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Bgt_Un_S : stream.Seek((dynamic)stack.Pop() < (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Ble_Un_S : stream.Seek((dynamic)stack.Pop() >= (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Blt_Un_S : stream.Seek((dynamic)stack.Pop() > (dynamic)stack.Pop() ? br.ReadByte() : 1, SeekOrigin.Current); goto Read; Br : stream.Seek(br.ReadInt32(), SeekOrigin.Current); goto Read; Brfalse : stream.Seek((int)stack.Pop() == 0 ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Brtrue : stream.Seek((int)stack.Pop() == 1 ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Beq : stream.Seek((dynamic)stack.Pop() == (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Bge : stream.Seek((dynamic)stack.Pop() <= (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Bgt : stream.Seek((dynamic)stack.Pop() < (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Ble : stream.Seek((dynamic)stack.Pop() >= (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Blt : stream.Seek((dynamic)stack.Pop() > (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Bne_Un : stream.Seek((dynamic)stack.Pop() != (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Bge_Un : stream.Seek((dynamic)stack.Pop() <= (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Bgt_Un : stream.Seek((dynamic)stack.Pop() < (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Ble_Un : stream.Seek((dynamic)stack.Pop() >= (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Blt_Un : stream.Seek((dynamic)stack.Pop() > (dynamic)stack.Pop() ? br.ReadInt32() : 4, SeekOrigin.Current); goto Read; Switch : goto NotImplemented_S; //TODO: implementation requrires full scan of msil instructions, jmp table, etc. Ldind_I1 : goto NotImplemented_S; Ldind_U1 : goto NotImplemented_S; Ldind_I2 : goto NotImplemented_S; Ldind_U2 : goto NotImplemented_S; Ldind_I4 : goto NotImplemented_S; Ldind_U4 : goto NotImplemented_S; Ldind_I8 : goto NotImplemented_S; Ldind_I : goto NotImplemented_S; Ldind_R4 : goto NotImplemented_S; Ldind_R8 : goto NotImplemented_S; Ldind_Ref : goto NotImplemented_S; Stind_Ref : goto NotImplemented_S; Stind_I1 : goto NotImplemented_S; Stind_I2 : goto NotImplemented_S; Stind_I4 : goto NotImplemented_S; Stind_I8 : goto NotImplemented_S; Stind_R4 : goto NotImplemented_S; Stind_R8 : goto NotImplemented_S; Add : stack.Push((dynamic)stack.Pop() + (dynamic)stack.Pop()); goto Read; Sub : stack.Push((dynamic)stack.Pop() - (dynamic)stack.Pop()); goto Read; Mul : stack.Push((dynamic)stack.Pop() * (dynamic)stack.Pop()); goto Read; Div : stack.Push((dynamic)stack.Pop() / (dynamic)stack.Pop()); goto Read; Div_Un : stack.Push((dynamic)stack.Pop() / (dynamic)stack.Pop()); goto Read; Rem : stack.Push((dynamic)stack.Pop() % (dynamic)stack.Pop()); goto Read; Rem_Un : stack.Push((dynamic)stack.Pop() % (dynamic)stack.Pop()); goto Read; And : stack.Push((dynamic)stack.Pop() & (dynamic)stack.Pop()); goto Read; Or : stack.Push((dynamic)stack.Pop() | (dynamic)stack.Pop()); goto Read; Xor : stack.Push((dynamic)stack.Pop() ^ (dynamic)stack.Pop()); goto Read; Shl : stack.Push((dynamic)stack.Pop() << br.ReadInt32()); goto Read; Shr : stack.Push((dynamic)stack.Pop() >> br.ReadInt32()); goto Read; Shr_Un : stack.Push((dynamic)stack.Pop() >> br.ReadInt32()); goto Read; Neg : stack.Push(-(dynamic)stack.Pop()); goto Read; Not : stack.Push(!(dynamic)stack.Pop()); goto Read; Conv_I1 : stack.Push(Convert.ToSByte(stack.Pop())); goto Read; Conv_I2 : stack.Push(Convert.ToInt16(stack.Pop())); goto Read; Conv_I4 : stack.Push(Convert.ToInt32(stack.Pop())); goto Read; Conv_I8 : stack.Push(Convert.ToInt64(stack.Pop())); goto Read; Conv_R4 : stack.Push(Convert.ToSingle(stack.Pop())); goto Read; Conv_R8 : stack.Push(Convert.ToDouble(stack.Pop())); goto Read; Conv_U4 : stack.Push(Convert.ToUInt32(stack.Pop())); goto Read; Conv_U8 : stack.Push(Convert.ToUInt64(stack.Pop())); goto Read; Callvirt : goto Call; Cpobj : goto NotImplemented_S; Ldobj : goto NotImplemented_S; Ldstr : stack.Push(resolver.ResolveStringToken(br.ReadInt32())); goto Read; Newobj: method = resolver.ResolveMethodToken(br.ReadInt32()); arr = new object[method.GetParameters().Length]; for (i = arr.Length - 1; i >= 0; i--) { arr[i] = stack.Pop(); } stack.Push(((ConstructorInfo)method).Invoke(arr)); goto Read; Castclass : stack.Push(Convert.ChangeType(stack.Pop(), resolver.ResolveTypeToken(br.ReadInt32()))); goto Read; Isinst: type = resolver.ResolveTypeToken(br.ReadInt32()); obj = stack.Pop(); if (obj.GetType().IsAssignableFrom(type)) { stack.Push(Convert.ChangeType(obj, type)); } else { stack.Push(0); } Conv_R_Un : stack.Push(Convert.ToSingle(stack.Pop())); goto Read; Exec_MSIL_S : goto NotSupported_S; Unbox : stack.Push(Convert.ChangeType(stack.Pop(), resolver.ResolveTypeToken(br.ReadInt32()))); Throw : goto NotSupported_S; Ldfld : stack.Push(resolver.ResolveFieldToken(br.ReadInt32()).GetValue(stack.Pop())); goto Read; Ldflda : goto NotSupported_S; Stfld : var val = stack.Pop(); resolver.ResolveFieldToken(br.ReadInt32()).SetValue(stack.Pop(), val); goto Read; Ldsfld : stack.Push(resolver.ResolveFieldToken(br.ReadInt32()).GetValue(null)); goto Read; Ldsflda : goto NotSupported_S; Stsfld : resolver.ResolveFieldToken(br.ReadInt32()).SetValue(null, stack.Pop()); goto Read; Stobj : goto NotSupported_S; Conv_Ovf_I1_Un : stack.Push(Convert.ToSByte(stack.Pop())); goto Read; Conv_Ovf_I2_Un : stack.Push(Convert.ToInt16(stack.Pop())); goto Read; Conv_Ovf_I4_Un : stack.Push(Convert.ToInt32(stack.Pop())); goto Read; Conv_Ovf_I8_Un : stack.Push(Convert.ToInt64(stack.Pop())); goto Read; Conv_Ovf_U1_Un : stack.Push(Convert.ToByte(stack.Pop())); goto Read; Conv_Ovf_U2_Un : stack.Push(Convert.ToUInt16(stack.Pop())); goto Read; Conv_Ovf_U4_Un : stack.Push(Convert.ToUInt32(stack.Pop())); goto Read; Conv_Ovf_U8_Un : stack.Push(Convert.ToUInt64(stack.Pop())); goto Read; Conv_Ovf_I_Un : goto NotSupported_S; Conv_Ovf_U_Un : goto NotSupported_S; Box : stack.Push((object)stack.Pop()); goto Read; Newarr : stack.Push(Array.CreateInstance(resolver.ResolveTypeToken(br.ReadInt32()), (int)(stack.Pop()))); goto Read; Ldlen : stack.Push(((Array)stack.Pop()).Length); goto Read; Ldelema : goto Read; Ldelem_I1 : i = (int)stack.Pop(); stack.Push(Convert.ToSByte(((object[])stack.Pop())[i])); goto Read; Ldelem_U1 : i = (int)stack.Pop(); stack.Push(Convert.ToByte(((object[])stack.Pop())[i])); goto Read; Ldelem_I2 : i = (int)stack.Pop(); stack.Push(Convert.ToInt16(((object[])stack.Pop())[i])); goto Read; Ldelem_U2 : i = (int)stack.Pop(); stack.Push(Convert.ToUInt32(((object[])stack.Pop())[i])); goto Read; Ldelem_I4 : i = (int)stack.Pop(); stack.Push(Convert.ToInt32(((object[])stack.Pop())[i])); goto Read; Ldelem_U4 : i = (int)stack.Pop(); stack.Push(Convert.ToUInt32(((object[])stack.Pop())[i])); goto Read; Ldelem_I8 : i = (int)stack.Pop(); stack.Push(Convert.ToInt64(((object[])stack.Pop())[i])); goto Read; Ldelem_I : goto NotSupported_S; Ldelem_R4 : i = (int)stack.Pop(); stack.Push((float)((object[])stack.Pop())[i]); goto Read; Ldelem_R8 : i = (int)stack.Pop(); stack.Push((double)((object[])stack.Pop())[i]); goto Read; Ldelem_Ref : i = (int)stack.Pop(); stack.Push(((object[])stack.Pop())[i]); goto Read; Stelem_I : goto NotSupported_S; Stelem_I1 : obj = Convert.ToSByte(stack.Pop()); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Stelem_I2 : obj = Convert.ToInt16(stack.Pop()); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Stelem_I4 : obj = Convert.ToInt32(stack.Pop()); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Stelem_I8 : obj = Convert.ToInt64(stack.Pop()); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Stelem_R4 : obj = Convert.ToSingle(stack.Pop()); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Stelem_R8 : obj = Convert.ToInt64(stack.Pop()); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Stelem_Ref : obj = stack.Pop(); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Ldelem : i = (int)stack.Pop(); stack.Push(Convert.ChangeType(((object[])stack.Pop())[i], resolver.ResolveTypeToken(br.ReadInt32()))); goto Read; Stelem : obj = Convert.ChangeType(stack.Pop(), resolver.ResolveTypeToken(br.ReadInt32())); i = (int)stack.Pop(); ((object[])stack.Pop())[i] = obj; goto Read; Unbox_Any : stack.Push(Convert.ChangeType(stack.Pop(), resolver.ResolveTypeToken(br.ReadInt32()))); goto Read; Conv_Ovf_I1 : stack.Push(Convert.ToSByte(stack.Pop())); goto Read; Conv_Ovf_U1 : stack.Push(Convert.ToByte(stack.Pop())); goto Read; Conv_Ovf_I2 : stack.Push(Convert.ToInt16(stack.Pop())); goto Read; Conv_Ovf_U2 : stack.Push(Convert.ToUInt16(stack.Pop())); goto Read; Conv_Ovf_I4 : stack.Push(Convert.ToInt32(stack.Pop())); goto Read; Conv_Ovf_U4 : stack.Push(Convert.ToUInt32(stack.Pop())); goto Read; Conv_Ovf_I8 : stack.Push(Convert.ToInt32(stack.Pop())); goto Read; Conv_Ovf_U8 : stack.Push(Convert.ToUInt64(stack.Pop())); goto Read; Refanyval : goto NotSupported_S; Ckfinite : var ckval = stack.Pop(); stack.Push(Convert.ToInt32(ckval is float?float.IsInfinity((float)ckval) : double.IsInfinity((double)ckval))); goto Read; Mkrefany : goto NotSupported_S; Ldtoken : stack.Push(resolver.ResolveMemberToken(br.ReadInt32())); goto Read; Conv_U2 : stack.Push(unchecked ((ushort)stack.Pop())); goto Read; Conv_U1 : stack.Push(unchecked ((byte)stack.Pop())); goto Read; Conv_I : goto NotSupported_S; Conv_Ovf_I : goto NotSupported_S; Conv_Ovf_U : goto NotSupported_S; Add_Ovf : goto Add; Add_Ovf_Un : goto Add; Mul_Ovf : goto Mul; Mul_Ovf_Un : goto Mul; Sub_Ovf : goto Sub; Sub_Ovf_Un : goto Sub; Endfinally : goto NotSupported_S; Leave : goto NotSupported_S; Leave_S : goto NotSupported_S; Stind_I : goto NotSupported_S; Conv_U : goto NotSupported_S; Prefix7 : goto NotSupported_S; Prefix6 : goto NotSupported_S; Prefix5 : goto NotSupported_S; Prefix4 : goto NotSupported_S; Prefix3 : goto NotSupported_S; Prefix2 : goto NotSupported_S; Prefix1: switch (op = stream.ReadByte()) { case 0: goto NotSupportedLong; //arglist case 1: stack.Push(Convert.ToInt32((dynamic)stack.Pop() == (dynamic)stack.Pop())); goto Read; // Ceq = 0xfe01, case 2: stack.Push(Convert.ToInt32((dynamic)stack.Pop() < (dynamic)stack.Pop())); goto Read; // Cgt = 0xfe02, case 3: stack.Push(Convert.ToInt32((dynamic)stack.Pop() < (dynamic)stack.Pop())); goto Read; // Cgt_Un = 0xfe03, case 4: stack.Push(Convert.ToInt32((dynamic)stack.Pop() > (dynamic)stack.Pop())); goto Read; // Clt = 0xfe04, case 5: stack.Push(Convert.ToInt32((dynamic)stack.Pop() < (dynamic)stack.Pop())); goto Read; // Clt_Un = 0xfe05, case 6: goto NotSupportedLong; // Ldftn = 0xfe06, case 7: goto NotSupportedLong; // Ldvirtftn = 0xfe07, case 8: goto NotImplementedLong; // 0xfe08, case 9: stack.Push(args[br.ReadInt16()]); goto Read; // Ldarg = 0xfe09, case 10: stack.Push(args[br.ReadInt16()]); goto Read; // Ldarga = 0xfe0a, case 11: args[br.ReadInt16()] = stack.Pop(); goto Read; // Starg = 0xfe0b, case 12: stack.Push(locals[br.ReadInt16()].Value); goto Read; // Ldloc = 0xfe0c, case 13: stack.Push(locals[br.ReadInt16()].Value); goto Read; // Ldloca = 0xfe0d, case 14: locals[br.ReadInt16()].Value = stack.Pop(); goto Read; // Stloc = 0xfe0e, case 15: goto NotSupportedLong; // Localloc = 0xfe0f, case 16: goto NotImplementedLong; //0xfe10, case 17: goto NotSupportedLong; // Endfilter = 0xfe11, case 18: goto NotSupportedLong; // Unaligned_ = 0xfe12, case 19: goto NotSupportedLong; // Volatile_ = 0xfe13, case 20: goto NotSupportedLong; // Tail_ = 0xfe14, case 21: goto NotSupportedLong; // Initobj = 0xfe15, case 22: goto NotSupportedLong; // Constrained_ = 0xfe16, case 23: goto NotSupportedLong; // Cpblk = 0xfe17, case 24: goto NotSupportedLong; // Initblk = 0xfe18, case 25: goto NotImplementedLong; //0xfe19 case 26: goto NotSupportedLong; // Rethrow = 0xfe1a case 27: goto NotImplementedLong; // = 0xfe1b case 28: goto NotSupportedLong; // Sizeof = 0xfe1c, case 29: goto NotSupportedLong; // Refanytype = 0xfe1d, case 30: goto NotSupportedLong; // Readonly_ = 0xfe1e, } Prefixref : goto Read; NotImplemented : throw new NotImplementedException($"OpCode {op} is not implemented"); NotImplementedLong : throw new NotImplementedException($"OpCode { (short)((ushort)(0xFE00) | op)} is not implemented"); NotSupported : throw new NotImplementedException($"OpCode { OpCodeLookup.GetILOpcode(op)} is not supported"); NotSupportedLong : throw new NotImplementedException($"OpCode { OpCodeLookup.GetILOpcode((short)((ushort)(0xFE00) | op))} is not supported"); RetResult : return((stack.Count > 0) ? stack.Pop() : null); }