示例#1
0
        public void ShouldOnlyReturnTrueWhenHitCountIsReached()
        {
            EvaluatorContext context = new EvaluatorContext();

            FakeConsoleRam ram = new FakeConsoleRam(0xFF);

            ram.Data[4] = 42;

            // 0xH0004 == 42
            ReadMemoryValue readMemory = new ReadMemoryValue
            {
                Address = 0x0004,
                Kind    = MemoryAddressKind.Int8
            };

            ConstValue constValue = new ConstValue(42);

            CompareInstruction compareInst = new CompareInstruction
            {
                Left      = readMemory,
                Right     = constValue,
                Operation = ConditionCompare.Equals
            };

            ConditionInstruction condition = new ConditionInstruction
            {
                TargetHitCount     = 2,
                CompareInstruction = compareInst
            };

            Assert.False(condition.Evaluate(ram, context));
            Assert.True(condition.Evaluate(ram, context));
        }
示例#2
0
        public void ShouldEvaluateDeltaValue()
        {
            EvaluatorContext context = new EvaluatorContext();

            FakeConsoleRam ram = new FakeConsoleRam(0xFF);

            ram.Data[4] = 4;

            // 0xH0004 < d0xH004
            ReadMemoryValue readMemory = new ReadMemoryValue
            {
                Address = 0x0004,
                Kind    = MemoryAddressKind.Int8
            };

            DeltaValue deltaValue = new DeltaValue(readMemory);

            CompareInstruction compareInst = new CompareInstruction
            {
                Left      = readMemory,
                Right     = deltaValue,
                Operation = ConditionCompare.Less
            };

            Assert.False(compareInst.Evaluate(ram, context));

            ram.Data[4] = 2;

            Assert.True(compareInst.Evaluate(ram, context));
            Assert.False(compareInst.Evaluate(ram, context));
        }
示例#3
0
        public void ShouldEvalEqualsMemoryWithConstValue()
        {
            EvaluatorContext context = new EvaluatorContext();

            FakeConsoleRam ram = new FakeConsoleRam(0xFF);

            ram.Data[4] = 42;

            // 0xH0004 == 42
            ReadMemoryValue readMemory = new ReadMemoryValue
            {
                Address = 0x0004,
                Kind    = MemoryAddressKind.Int8
            };

            ConstValue constValue = new ConstValue(42);

            CompareInstruction compareInst = new CompareInstruction
            {
                Left      = readMemory,
                Right     = constValue,
                Operation = ConditionCompare.Equals
            };

            var result = compareInst.Evaluate(ram, context);

            Assert.True(result);
        }
        public void GetBytes_CompareInstruction(CompareKind compareKind)
        {
            var instruction   = new CompareInstruction(compareKind);
            var expectedBytes = InstructionByteBuilder.Create()
                                .Opcode(Opcode.Compare, compareKind)
                                .AsSpan();

            Assert.True(expectedBytes.SequenceEqual(instruction.GetBytes()));
        }
示例#5
0
        public bool MoveNext()
        {
            if (lookahead.Count > 0)
            {
                lookahead.RemoveAt(0);
            }

            var rewritten = default(bool);

            do
            {
                rewritten = false;
                if (EnsureLookahead(1))
                {
                    var i = lookahead[0];
                    if (i.Flavor == InstructionFlavor.ArgLocal)
                    {
                        var argloci = (ArgLocalInstruction)i;
                        if (argloci.Op == ArgLocalOp.St)
                        {
                            if (!argloci.AfterState.ArgLocalIsAlive(argloci.ArgLocal, argloci.Index))
                            {
                                // starg.n (where arg n is dead) ==> pop
                                // stloc.n (where local n is dead) ==> pop
                                lookahead[0] = new MiscInstruction(argloci.Offset, MiscOp.Pop)
                                {
                                    BeforeState = argloci.BeforeState, AfterState = argloci.AfterState
                                };
                                Trace(1, argloci);
                                rewritten = true;
                            }
                            else if (EnsureLookahead(2))
                            {
                                var j = lookahead[1];
                                if (j.Flavor == InstructionFlavor.ArgLocal)
                                {
                                    var arglocj = (ArgLocalInstruction)j;
                                    if (arglocj.Op == ArgLocalOp.Ld && argloci.ArgLocal == arglocj.ArgLocal && argloci.Index == arglocj.Index)
                                    {
                                        if (!arglocj.AfterState.ArgLocalIsAlive(arglocj.ArgLocal, arglocj.Index))
                                        {
                                            // stloc.n; ldloc.n (where local n is dead) ==> <empty>
                                            // starg.n; ldarg.n (where arg n is dead) ==> <empty>
                                            lookahead.RemoveAt(0);
                                            lookahead.RemoveAt(0);
                                            Trace(0, argloci, arglocj);
                                            rewritten = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else if (i.Flavor == InstructionFlavor.LdInt32)
                    {
                        var ldinti = (LdInt32Instruction)i;
                        if (ldinti.Value == 0)
                        {
                            if (EnsureLookahead(2))
                            {
                                var j = lookahead[1];
                                if (j.Flavor == InstructionFlavor.Compare)
                                {
                                    var compj = (CompareInstruction)j;
                                    if (compj.Op == CompareOp.Cgt && compj.IsUnsigned)
                                    {
                                        // ldc.i4 0; cgt.u => ctrue
                                        lookahead.RemoveAt(0);
                                        lookahead[0] = new CompareInstruction(compj.Offset, CompareOp.CtruePseudo, false)
                                        {
                                            Type = compj.Type, BeforeState = ldinti.BeforeState, AfterState = compj.AfterState
                                        };
                                        Trace(1, ldinti, compj);
                                        rewritten = true;
                                    }
                                    else if (compj.Op == CompareOp.Ceq)
                                    {
                                        // ldc.i4 0; ceq => cfalse
                                        lookahead.RemoveAt(0);
                                        lookahead[0] = new CompareInstruction(compj.Offset, CompareOp.CfalsePseudo, false)
                                        {
                                            Type = compj.Type, BeforeState = ldinti.BeforeState, AfterState = compj.AfterState
                                        };
                                        Trace(1, ldinti, compj);
                                        rewritten = true;
                                    }
                                }
                            }
                        }
                    }
                    else if (i.Flavor == InstructionFlavor.Misc)
                    {
                        var misci = (MiscInstruction)i;
                        if (misci.Op == MiscOp.Nop)
                        {
                            // nop ==> <empty>
                            lookahead.RemoveAt(0);
                            Trace(0, misci);
                            rewritten = true;
                        }
                        else if (misci.Op == MiscOp.Ldnull)
                        {
                            if (EnsureLookahead(2))
                            {
                                var j = lookahead[1];
                                if (j.Flavor == InstructionFlavor.Compare)
                                {
                                    var compj = (CompareInstruction)j;
                                    if (compj.Op == CompareOp.Cgt)
                                    {
                                        // ldnull; cgt => ctrue
                                        lookahead.RemoveAt(0);
                                        lookahead[0] = new CompareInstruction(compj.Offset, CompareOp.CtruePseudo, false)
                                        {
                                            Type = compj.Type, BeforeState = misci.BeforeState, AfterState = compj.AfterState
                                        };
                                        Trace(1, misci, compj);
                                        rewritten = true;
                                    }
                                    else if (compj.Op == CompareOp.Ceq)
                                    {
                                        // ldnull; ceq => cfalse
                                        lookahead.RemoveAt(0);
                                        lookahead[0] = new CompareInstruction(compj.Offset, CompareOp.CfalsePseudo, false)
                                        {
                                            Type = compj.Type, BeforeState = misci.BeforeState, AfterState = compj.AfterState
                                        };
                                        Trace(1, misci, compj);
                                        rewritten = true;
                                    }
                                }
                            }
                        }
                        else if (misci.Op == MiscOp.Dup)
                        {
                            if (EnsureLookahead(2))
                            {
                                var j = lookahead[1];
                                if (j.Flavor == InstructionFlavor.Misc)
                                {
                                    var miscj = (MiscInstruction)j;
                                    if (miscj.Op == MiscOp.Pop)
                                    {
                                        // dup; pop ==> <empty>
                                        lookahead.RemoveAt(0);
                                        lookahead.RemoveAt(0);
                                        Trace(0, misci, miscj);
                                        rewritten = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }while (rewritten);

            return(lookahead.Count > 0);
        }
        public void ToString_CompareInstruction(CompareKind compareKind, string expectedString)
        {
            var compareInstruction = new CompareInstruction(compareKind);

            Assert.Equal(expectedString, compareInstruction.ToString());
        }
示例#7
0
 public void VisitCompare(CompareInstruction instruction) => IncrementCallCount(nameof(VisitCompare));
示例#8
0
        ExecuteComparisonInstructionBackward(CompareInstruction compareInstruction,
                                             Operand varOperand, Path path)
        {
            Expression result             = null;
            Operator   comparisonOperator = null;

            switch (compareInstruction.ConditionCode)
            {
            case ConditionCode.GT:
                comparisonOperator = OperatorStore.GreaterThanOp;
                break;

            case ConditionCode.UGT:
                comparisonOperator = OperatorStore.UGreaterThanOp;
                break;

            case ConditionCode.FGT:
                comparisonOperator = OperatorStore.FGreaterThanOp;
                break;

            case ConditionCode.GE:
                comparisonOperator = OperatorStore.GreaterThanEqualOp;
                break;

            case ConditionCode.UGE:
                comparisonOperator = OperatorStore.UGreaterThanEqualOp;
                break;

            case ConditionCode.FGE:
                comparisonOperator = OperatorStore.FGreaterThanEqualOp;
                break;

            case ConditionCode.LT:
                comparisonOperator = OperatorStore.LessThanOp;
                break;

            case ConditionCode.ULT:
                comparisonOperator = OperatorStore.ULessThanOp;
                break;

            case ConditionCode.FLT:
                comparisonOperator = OperatorStore.FLessThanOp;
                break;

            case ConditionCode.LE:
                comparisonOperator = OperatorStore.LessThanEqualOp;
                break;

            case ConditionCode.ULE:
                comparisonOperator = OperatorStore.ULessThanEqualOp;
                break;

            case ConditionCode.FLE:
                comparisonOperator = OperatorStore.FLessThanEqualOp;
                break;

            case ConditionCode.EQ:
                comparisonOperator = OperatorStore.EqualOp;
                break;

            case ConditionCode.NE:
                comparisonOperator = OperatorStore.NotEqualOp;
                break;

            default:
                throw new NotImplementedException("PHOENIX: Compare instruction Opcode " +
                                                  "not implemented in symbolic tracer: " + compareInstruction.ToString());
            }

            Operand    srcOp1   = compareInstruction.SourceOperand1;
            Operand    srcOp2   = compareInstruction.SourceOperand2;
            Expression srcExpr1 = TraceOperandBackward(srcOp1, varOperand, path);
            Expression srcExpr2 = TraceOperandBackward(srcOp2, varOperand, path);

            result = new Expression(comparisonOperator, srcExpr1, srcExpr2,
                                    path.Config.WORD_BITSIZE);
            result.Type = compareInstruction.DestinationOperand.Type;

            BranchInstruction branchInstruction = compareInstruction.Next.AsBranchInstruction;

            if (branchInstruction != null)
            {
                if (path.Blocks[path.Blocks.IndexOf(compareInstruction.BasicBlock) + 1] ==
                    branchInstruction.FalseLabelInstruction.BasicBlock)
                {
                    result      = new Expression(OperatorStore.NotOp, result, result.BitSize);
                    result.Type = compareInstruction.DestinationOperand.Type;
                }
            }

            return(result);
        }
示例#9
0
        /// <summary>
        /// Traces the definition of the input operand and returns its symbolic
        /// Expression at the source level.
        /// </summary>
        ///
        /// <param name="operand">Operand whose definition needs to be traced.</param>
        /// <param name="varOperand">Current variable operand whose definition is being traced,
        /// which may be different from <paramref name="operand"/>.</param>
        /// <param name="path">Path along which to trace the definition.</param>
        ///
        /// <returns>Symbolic Expression that corresponds to the input operand.</returns>
        /// <remarks>Precondition: <paramref name="operand"/> and <paramref name="varOperand"/>
        /// are not null.</remarks>
        /// <remarks>Postcondition: The resulting Expression is not null.</remarks>
        public static Expression TraceOperandBackward(Operand operand,
                                                      Operand varOperand, Path path)
        {
            Trace.Assert(operand != null, "PHOENIX: operand cannot be null.");
            Trace.Assert(varOperand != null, "PHOENIX: varOperand cannot be null.");

            if (path.ProjectConfig.debugConfig.DUMP_INSTRUCTION_TRACE)
            {
                Console.Out.WriteLine();
                Console.Out.WriteLine(operand.Instruction.ToString());
                Console.Out.WriteLine("{ Exploring " + operand +
                                      " while converting " + varOperand);
            }

            Expression result = null;

            if (path.OperandExpressions.ContainsKey(operand))
            {
                result = path.OperandExpressions[operand].Clone();
                if (path.ProjectConfig.debugConfig.DUMP_INSTRUCTION_TRACE)
                {
                    Console.Out.WriteLine("  Memoization provides the result.");
                    Console.Out.WriteLine("  Result is " + result + " }");
                }
                return(result);
            }

            Instruction defInstruction = operand.DefinitionInstruction;

            if (operand.IsImmediateOperand)
            {
                string opValue = "";

                ImmediateOperand immOperand = operand.AsImmediateOperand;
                if (immOperand.Value.IsIntValue)
                {
                    opValue = immOperand.IntValue.ToString();
                }
                else if (immOperand.Value.IsFloatValue)
                {
                    double floatValue = immOperand.FloatValue64;
                    long   longValue  = Convert.ToInt64(floatValue);
                    Console.Out.WriteLine("PHOENIX: WARNING: Floating point constant " +
                                          "discovered during backward symbolic execution: " + floatValue + ". " +
                                          "It will be cast to the integer " + longValue + ".");
                    opValue = longValue.ToString();
                }
                else
                {
                    throw new NotSupportedException("PHOENIX: " +
                                                    "Support for this type of immediate operand not implemented.");
                }

                result      = new Constant(opValue, operand.BitSize);
                result.Type = operand.Type;
            }
            else if (operand.IsMemoryOperand)
            {
                /* This case implies a source-level dereference. */
                result = TraceMemoryOperandBackward(operand, varOperand, path);
            }
            else if ((defInstruction != null) &&
                     (defInstruction.Opcode.Id == Phx.Common.Opcode.Index.Chi) &&
                     (defInstruction.SourceOperand1.DefinitionInstruction.Opcode.Id ==
                      Phx.Common.Opcode.Index.Start))
            {
                result = PhoenixHelper.MakeVariableExpression(operand,
                                                              PhoenixHelper.GetOperandName(operand), path);
            }
            else if (defInstruction == null)
            {
                /* We are tracing a global operand. */
                result = PhoenixHelper.MakeVariableExpression(operand,
                                                              PhoenixHelper.GetOperandName(operand), path);
            }
            else if (!path.Blocks.Contains(defInstruction.BasicBlock))
            {
                result = PhoenixHelper.MakeVariableExpression(operand,
                                                              PhoenixHelper.GetOperandName(operand), path);
            }
            else
            {
                switch (defInstruction.InstructionKind)
                {
                case InstructionKind.ValueInstruction:
                    ValueInstruction valueInstruction = defInstruction.AsValueInstruction;
                    result =
                        ExecuteValueInstructionBackward(valueInstruction,
                                                        varOperand, false, path);
                    break;

                case InstructionKind.CallInstruction:
                    result =
                        PhoenixHelper.MakeCallVariableExpression(operand, defInstruction,
                                                                 varOperand, path);
                    break;

                case InstructionKind.CompareInstruction:
                    CompareInstruction compareInstruction =
                        defInstruction.AsCompareInstruction;
                    result =
                        ExecuteComparisonInstructionBackward(compareInstruction,
                                                             varOperand, path);
                    break;

                default:
                    result =
                        ExecuteSpecialInstructionBackward(operand, defInstruction,
                                                          varOperand, path);
                    break;
                }
            }

            Trace.Assert(result != null, "PHOENIX: Result Expression should not be null.");
            Trace.Assert(result.Type != null, "PHOENIX: Result Expression should have a type.");

            if (path.ProjectConfig.debugConfig.DUMP_INSTRUCTION_TRACE)
            {
                Console.Out.WriteLine("  Result is " + result + " }");
            }

            /* Remember the result for later, in case it is ever needed. */
            path.OperandExpressions[operand] = result;
            return(result);
        }