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)); }
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)); }
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())); }
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()); }
public void VisitCompare(CompareInstruction instruction) => IncrementCallCount(nameof(VisitCompare));
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); }
/// <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); }