Пример #1
0
        private int ExecuteInstruction(Instruction instruction)
        {
            var wasExactInstructionProcessed = true;

            if (_currentCount >= _maxExecuteCount)
                return -1;

            #region big switch

            switch (instruction.OpCode.Code)
            {
                case Code.Nop:
                    break;
                case Code.Break:
                    break;
                case Code.Ldarg_0:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Ldarg_1:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Ldarg_2:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Ldarg_3:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Ldloc_0:
                    _stack.Push(LocalToStackEntry(instruction, _locals[0]));
                    break;
                case Code.Ldloc_1:
                    _stack.Push(LocalToStackEntry(instruction, _locals[1]));
                    break;
                case Code.Ldloc_2:
                    _stack.Push(LocalToStackEntry(instruction, _locals[2]));
                    break;
                case Code.Ldloc_3:
                    _stack.Push(LocalToStackEntry(instruction, _locals[3]));
                    break;
                case Code.Stloc_0:
                    SetLocalValue(0, StackToLocalEntry(instruction, _stack.Pop()));
                    break;
                case Code.Stloc_1:
                    SetLocalValue(1, StackToLocalEntry(instruction, _stack.Pop()));
                    break;
                case Code.Stloc_2:
                    SetLocalValue(2, StackToLocalEntry(instruction, _stack.Pop()));
                    break;
                case Code.Stloc_3:
                    SetLocalValue(3, StackToLocalEntry(instruction, _stack.Pop()));
                    break;
                case Code.Ldarg_S:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Ldarga_S:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Starg_S:
                    _stack.Pop();
                    break;
                case Code.Ldloc_S:
                    _stack.Push(LocalToStackEntry(instruction, _locals[0]));
                    break;
                case Code.Ldloca_S:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Stloc_S:
                    _stack.Pop();
                    break;
                case Code.Ldnull:
                    _stack.Push(new StackEntry(instruction, true, null));
                    break;
                case Code.Ldc_I4_M1:
                    _stack.Push(new StackEntry(instruction, true, (int)-1));
                    break;
                case Code.Ldc_I4_0:
                    _stack.Push(new StackEntry(instruction, true, (int)0));
                    break;
                case Code.Ldc_I4_1:
                    _stack.Push(new StackEntry(instruction, true, (int)1));
                    break;
                case Code.Ldc_I4_2:
                    _stack.Push(new StackEntry(instruction, true, (int)2));
                    break;
                case Code.Ldc_I4_3:
                    _stack.Push(new StackEntry(instruction, true, (int)3));
                    break;
                case Code.Ldc_I4_4:
                    _stack.Push(new StackEntry(instruction, true, (int)4));
                    break;
                case Code.Ldc_I4_5:
                    _stack.Push(new StackEntry(instruction, true, (int)5));
                    break;
                case Code.Ldc_I4_6:
                    _stack.Push(new StackEntry(instruction, true, (int)6));
                    break;
                case Code.Ldc_I4_7:
                    _stack.Push(new StackEntry(instruction, true, (int)7));
                    break;
                case Code.Ldc_I4_8:
                    _stack.Push(new StackEntry(instruction, true, (int)8));
                    break;
                case Code.Ldc_I4_S:
                case Code.Ldc_I4:
                    _stack.Push(new StackEntry(instruction, true, (int)Convert.ChangeType(instruction.Operand, typeof(int))));
                    break;
                case Code.Ldc_I8:
                    _stack.Push(new StackEntry(instruction, true, (long)instruction.Operand));
                    break;
                case Code.Ldc_R4:
                    _stack.Push(new StackEntry(instruction, true, instruction.Operand));
                    break;
                case Code.Ldc_R8:
                    _stack.Push(new StackEntry(instruction, true, instruction.Operand));
                    break;
                case Code.Dup:
                    var value = _stack.Pop();
                    _stack.Push(value);
                    value.PushedBy = instruction;
                    _stack.Push(value);
                    break;
                case Code.Pop:
                    _stack.Pop();
                    break;
                //TODO: Implement
                /*case Code.Jmp:
                    break;*/
                case Code.Call:
                    dynamic mr;

                    if (instruction.Operand is MethodSpec)
                        mr = (instruction.Operand as MethodSpec).Method;
                    else
                        mr = (instruction.Operand as MemberRef);

                    for (int i = 0; i < mr.Parameters.Count; i++)
                        _stack.Pop();

                    if ((instruction.Operand as MethodDef).ReturnType != mr.Module.ImportAsTypeSig(typeof(void)))
                    {
                        _stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Calli:
                    break;
                case Code.Ret:
                    break;
                case Code.Br:
                case Code.Br_S:
                    return _methodBody.Instructions.IndexOf(instruction.Operand as Instruction);
                case Code.Brfalse:
                case Code.Brfalse_S:
                    if (Stack.Peek().IsValueKnown && Stack.Peek().Value.GetType().CanCastTo<bool>(Stack.Peek().Value))
                        if (!Convert.ToBoolean(Stack.Pop().Value))
                            return _methodBody.Instructions.IndexOf(instruction.Operand as Instruction);
                    break;
                case Code.Brtrue:
                case Code.Brtrue_S:
                    if (Stack.Peek().IsValueKnown && Stack.Peek().Value.GetType().CanCastTo<bool>(Stack.Peek().Value))
                        if (Convert.ToBoolean(Stack.Pop().Value))
                            return _methodBody.Instructions.IndexOf(instruction.Operand as Instruction);
                    break;
                case Code.Add:
                    if (Stack.Count < 2)
                        Stack.Push(new StackEntry(null, false));
                    if (Stack.VerifyTop())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value + (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Sub:
                    if (Stack.Count < 2)
                        Stack.Push(new StackEntry(null, false));
                    if (Stack.VerifyTop())
                    {
                        var holder = Stack.Pop().Value;
                        Stack.Push(new StackEntry(instruction, true,
                                                  (dynamic)Stack.Pop().Value - (dynamic)holder));
                    }
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Mul:
                    if (Stack.Count < 2)
                        Stack.Push(new StackEntry(null, false));
                    if (Stack.VerifyTop())
                    {
                        var holder = Stack.Pop().Value;
                        Stack.Push(new StackEntry(instruction, true,
                                                  (dynamic)Stack.Pop().Value * (dynamic)holder));
                    }
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Div_Un:
                case Code.Div:
                    if (Stack.VerifyTop())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value / (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Rem:
                case Code.Rem_Un:
                    if (Stack.VerifyTop())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value % (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Xor:
                    if (Stack.Count < 2)
                        Stack.Push(new StackEntry(null, false));
                    if (Stack.VerifyTop())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value ^ (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.And:
                    if (Stack.VerifyTop<int>())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value & (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Or:
                    if (Stack.VerifyTop<int>())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value | (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Shl:
                    if (Stack.VerifyTop<int>())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value << (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Shr_Un:
                case Code.Shr:
                    if (Stack.VerifyTop<int>())
                        Stack.Push(new StackEntry(instruction, true, (dynamic)Stack.Pop().Value >> (dynamic)Stack.Pop().Value));
                    else
                    {
                        Stack.Pop();
                        Stack.Pop();
                        Stack.Push(new StackEntry(instruction, false));
                    }
                    break;
                case Code.Neg:
                    if (Stack.Peek().IsValueKnown)
                        if (Stack.Peek().Value.IsNumeric())
                        {
                            Stack.Push(new StackEntry(instruction, true, -((dynamic)Stack.Pop().Value)));
                        }
                    break;
                case Code.Ldstr:
                    Stack.Push(new StackEntry(instruction, true, instruction.Operand as string));
                    break;
                case Code.Conv_I8:
                    if (Stack.Peek().IsValueKnown)
                        if (Stack.Peek().Value is int)
                            Stack.Push(new StackEntry(instruction, true,
                                                      (long)Convert.ChangeType(Stack.Pop().Value, typeof(long))));
                    break;
                case Code.Conv_I1:
                    if (Stack.Peek().IsValueKnown)
                        if (Stack.Peek().Value.IsNumeric())
                            Stack.Push(new StackEntry(instruction, true, Convert.ToByte(Stack.Pop().Value)));
                    break;
                case Code.Conv_I2:
                    if (Stack.Peek().IsValueKnown)
                        if (Stack.Peek().Value.IsNumeric())
                            Stack.Push(new StackEntry(instruction, true, Convert.ToInt16(Stack.Pop().Value)));
                    break;
                case Code.Conv_I4:
                    if (Stack.Peek().IsValueKnown)
                        if (Stack.Peek().Value.IsNumeric())
                            Stack.Push(new StackEntry(instruction, true, Convert.ToInt32(Stack.Pop().Value)));
                    break;
                case Code.Conv_R4:
                    break;
                case Code.Conv_R8:
                    break;
                case Code.Conv_U4:
                    break;
                case Code.Conv_U8:
                    break;
                case Code.Beq_S:
                    if (Stack.VerifyTop<int>())
                    {
                        if (Stack != null && Stack.Pop().Value == Stack.Pop().Value)
                            return _methodBody.Instructions.IndexOf(instruction.Operand as Instruction);
                    }
                    else if (Stack.VerifyTop())
                        if (ReferenceEquals(Stack.Pop().Value, Stack.Pop().Value))
                            return _methodBody.Instructions.IndexOf(instruction.Operand as Instruction);
                    break;
                case Code.Bge:
                case Code.Bge_Un_S:
                case Code.Bge_S:

                    break;
                case Code.Bgt_S:
                    break;
                case Code.Ble_S:
                    break;
                case Code.Blt_S:
                    break;
                case Code.Bne_Un_S:
                    break;
                case Code.Bgt_Un_S:
                    break;
                case Code.Ble_Un_S:
                    break;
                case Code.Blt_Un_S:
                    break;
                case Code.Beq:
                    break;
                case Code.Bgt:
                    break;
                case Code.Ble:
                    break;
                case Code.Blt:
                    break;
                case Code.Bne_Un:
                    break;
                case Code.Bge_Un:
                    break;
                case Code.Bgt_Un:
                    break;
                case Code.Ble_Un:
                    break;
                case Code.Blt_Un:
                    break;
                case Code.Switch:
                    break;
                case Code.Ldind_I1:
                    break;
                case Code.Ldind_U1:
                    break;
                case Code.Ldind_I2:
                    break;
                case Code.Ldind_U2:
                    break;
                case Code.Ldind_I4:
                    break;
                case Code.Ldind_U4:
                    break;
                case Code.Ldind_I8:
                    break;
                case Code.Ldind_I:
                    break;
                case Code.Ldind_R4:
                    break;
                case Code.Ldind_R8:
                    break;
                case Code.Ldind_Ref:
                    break;
                case Code.Stind_Ref:
                    break;
                case Code.Stind_I1:
                    break;
                case Code.Stind_I2:
                    break;
                case Code.Stind_I4:
                    break;
                case Code.Stind_I8:
                    break;
                case Code.Stind_R4:
                    break;
                case Code.Stind_R8:
                    break;
                case Code.Not:
                    break;
                case Code.Callvirt:
                    break;
                case Code.Cpobj:
                    break;
                case Code.Ldobj:
                    break;
                case Code.Newobj:
                    _stack.Push(new StackEntry(instruction, false));
                    break;
                case Code.Castclass:
                    break;
                case Code.Isinst:
                    break;
                case Code.Conv_R_Un:
                    break;
                case Code.Unbox:
                    break;
                case Code.Throw:
                    break;
                case Code.Ldfld:
                    break;
                case Code.Ldflda:
                    break;
                case Code.Stfld:
                    break;
                case Code.Ldsfld:
                    break;
                case Code.Ldsflda:
                    break;
                case Code.Stsfld:
                    break;
                case Code.Stobj:
                    break;
                case Code.Conv_Ovf_I1_Un:
                    break;
                case Code.Conv_Ovf_I2_Un:
                    break;
                case Code.Conv_Ovf_I4_Un:
                    break;
                case Code.Conv_Ovf_I8_Un:
                    break;
                case Code.Conv_Ovf_U1_Un:
                    break;
                case Code.Conv_Ovf_U2_Un:
                    break;
                case Code.Conv_Ovf_U4_Un:
                    break;
                case Code.Conv_Ovf_U8_Un:
                    break;
                case Code.Conv_Ovf_I_Un:
                    break;
                case Code.Conv_Ovf_U_Un:
                    break;
                case Code.Box:
                    break;
                case Code.Newarr:
                    break;
                case Code.Ldlen:
                    break;
                case Code.Ldelema:
                    break;
                case Code.Ldelem_I1:
                    break;
                case Code.Ldelem_U1:
                    break;
                case Code.Ldelem_I2:
                    break;
                case Code.Ldelem_U2:
                    break;
                case Code.Ldelem_I4:
                    break;
                case Code.Ldelem_U4:
                    break;
                case Code.Ldelem_I8:
                    break;
                case Code.Ldelem_I:
                    break;
                case Code.Ldelem_R4:
                    break;
                case Code.Ldelem_R8:
                    break;
                case Code.Ldelem_Ref:
                    break;
                case Code.Stelem_I:
                    break;
                case Code.Stelem_I1:
                    break;
                case Code.Stelem_I2:
                    break;
                case Code.Stelem_I4:
                    break;
                case Code.Stelem_I8:
                    break;
                case Code.Stelem_R4:
                    break;
                case Code.Stelem_R8:
                    break;
                case Code.Stelem_Ref:
                    break;
                case Code.Unbox_Any:
                    break;
                case Code.Conv_Ovf_I1:
                    break;
                case Code.Conv_Ovf_U1:
                    break;
                case Code.Conv_Ovf_I2:
                    break;
                case Code.Conv_Ovf_U2:
                    break;
                case Code.Conv_Ovf_I4:
                    break;
                case Code.Conv_Ovf_U4:
                    break;
                case Code.Conv_Ovf_I8:
                    break;
                case Code.Conv_Ovf_U8:
                    break;
                case Code.Refanyval:
                    break;
                case Code.Ckfinite:
                    break;
                case Code.Mkrefany:
                    break;
                case Code.Ldtoken:
                    break;
                case Code.Conv_U2:
                    break;
                case Code.Conv_U1:
                    break;
                case Code.Conv_I:
                    break;
                case Code.Conv_Ovf_I:
                    break;
                case Code.Conv_Ovf_U:
                    break;
                case Code.Add_Ovf:
                    break;
                case Code.Add_Ovf_Un:
                    break;
                case Code.Mul_Ovf:
                    break;
                case Code.Mul_Ovf_Un:
                    break;
                case Code.Sub_Ovf:
                    break;
                case Code.Sub_Ovf_Un:
                    break;
                case Code.Endfinally:
                    break;
                case Code.Leave:
                    break;
                case Code.Leave_S:
                    break;
                case Code.Stind_I:
                    break;
                case Code.Conv_U:
                    break;
                case Code.Arglist:
                    break;
                case Code.Ceq:
                    break;
                case Code.Cgt:
                    break;
                case Code.Cgt_Un:
                    break;
                case Code.Clt:
                    break;
                case Code.Clt_Un:
                    break;
                case Code.Ldftn:
                    break;
                case Code.Ldvirtftn:
                    break;
                case Code.Ldarg:
                    break;
                case Code.Ldarga:
                    break;
                case Code.Starg:
                    break;
                case Code.Ldloc:
                    break;
                case Code.Ldloca:
                    break;
                case Code.Stloc:
                    break;
                case Code.Localloc:
                    break;
                case Code.Endfilter:
                    break;
                case Code.Unaligned:
                    break;
                case Code.Volatile:
                    break;
                case Code.Tailcall:
                    break;
                case Code.Initobj:
                    break;
                case Code.Constrained:
                    break;
                case Code.Cpblk:
                    break;
                case Code.Initblk:
                    break;
                case Code.Rethrow:
                    break;
                case Code.Sizeof:
                    break;
                case Code.Refanytype:
                    break;
                case Code.Readonly:
                    break;
                default:
                    wasExactInstructionProcessed = false;
                    break;
            }

            #endregion

            _currentCount++;

            Snapshots.Add(new Snapshot(new Stack<StackEntry>(Stack), new Dictionary<int, LocalEntry>(_locals),
                                       instruction, _methodBody, Snapshots[Snapshots.Count - 1]));

            if (!wasExactInstructionProcessed)
            {
                switch (instruction.OpCode.StackBehaviourPush)
                {
                    case StackBehaviour.Push0:
                    case StackBehaviour.Push1:
                    case StackBehaviour.Pushi:
                    case StackBehaviour.Pushi8:
                    case StackBehaviour.Pushr4:
                    case StackBehaviour.Pushr8:
                    case StackBehaviour.Pushref:
                        _stack.Push(new StackEntry(instruction, true, instruction.Operand));
                        break;
                    case StackBehaviour.Push1_push1:
                        _stack.Push(new StackEntry(instruction, false));
                        _stack.Push(new StackEntry(instruction, false));
                        break;
                }
                if (instruction.IsUnconditionalBranch())
                {
                    return _methodBody.Instructions.IndexOf(instruction);
                }
            }

            return ++_instructionPointer;
        }
Пример #2
0
 private static bool OnFunc(Instruction instr)
 {
     return instr.IsUnconditionalBranch();
 }