public bool SolveBlock(Block source, Block block) { this.block = block; if (!block.LastInstr.IsConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch) { return(false); } ctx = new Context(); CflowTranslatorCtx translator = this.TranslatorInit(source == block && !(source.Parent is HandlerBlock)); var instructions = block.Instructions; if (instructions.Count == 0) { return(false); } try { for (int i = 0; i < instructions.Count - 1; i++) { var instr = instructions[i].Instruction; TranslateInstruction(translator, instr); } } catch (NullReferenceException) { return(false); } return(TranslateBranch(translator)); }
private CflowTranslatorCtx TranslatorInit(bool fromFirstBlock) { ParameterList methodParameters = this.blocks.Method.Parameters; LocalList methodLocals = this.blocks.Method.Body.Variables; CflowTranslatorCtx translator = new CflowTranslatorCtx(ctx, new CflowStack(), new List <BitVecExpr>(), new List <BitVecExpr>()); for (int i = 0; i < methodParameters.Count; i++) { translator.Args.Add(ctx.MkBVConst("Arg" + i.ToString(), 32)); } for (int i = 0; i < methodLocals.Count; i++) { if (fromFirstBlock) { translator.Locals.Add(ctx.MkBV(0, 32)); } else { translator.Locals.Add(ctx.MkBVConst("Loc" + i.ToString(), 32)); } } return(translator); }
public bool TranslateBranch(CflowTranslatorCtx translator) { var stack = translator.Stack; Instruction instr = block.LastInstr.Instruction; switch (instr.OpCode.Code) { case Code.Beq: case Code.Beq_S: return(Solve_Beq(stack)); case Code.Bge: case Code.Bge_S: return(Solve_Bge(stack)); case Code.Bge_Un: case Code.Bge_Un_S: return(Solve_Bge_Un(stack)); case Code.Bgt: case Code.Bgt_S: return(Solve_Bgt(stack)); case Code.Bgt_Un: case Code.Bgt_Un_S: return(Solve_Bgt_Un(stack)); case Code.Ble: case Code.Ble_S: return(Solve_Ble(stack)); case Code.Ble_Un: case Code.Ble_Un_S: return(Solve_Ble_Un(stack)); case Code.Blt: case Code.Blt_S: return(Solve_Blt(stack)); case Code.Blt_Un: case Code.Blt_Un_S: return(Solve_Blt_Un(stack)); case Code.Bne_Un: case Code.Bne_Un_S: return(Solve_Bne_Un(stack)); case Code.Brfalse: case Code.Brfalse_S: return(Solve_Brfalse(stack)); case Code.Brtrue: case Code.Brtrue_S: return(Solve_Brtrue(stack)); case Code.Switch: return(Solve_Switch(stack)); default: return(false); } }
private bool Solve_Switch(CflowStack stack) { Block target; List <Block> targets; bool modified = false; int index; var val1 = stack.Pop(); if (val1 is BitVecExpr && (val1 as BitVecExpr).Simplify().IsNumeral != true) { var cfg = CflowCFG.ControlFlow; foreach (List <Block> list in cfg) { token.ThrowIfCancellationRequested(); CflowTranslatorCtx translator = TranslatorInit(true); List <Instr> instructions = new List <Instr>(); foreach (Block b in list) { instructions.AddRange(b.Instructions); } for (int i = 0; i < instructions.Count - 1; i++) { var instr = instructions[i].Instruction; TranslateInstruction(translator, instr); } object val2 = translator.Stack.Pop(); if (val2 is BitVecExpr && (val2 as BitVecExpr).Simplify().IsNumeral == true) { this.BifurcateBlocks(cfg, list); if (!int.TryParse((val2 as BitVecExpr).Simplify().ToString(), out index)) { index = -1; } var beforeSwitch = list[list.Count - 2]; if (beforeSwitch.LastInstr.IsConditionalBranch()) { var newBlock = new Block(); for (int i = 0; i < list.Last().Instructions.Count - 1; i++) { var instr = list.Last().Instructions[i]; if (instr.OpCode != OpCodes.Nop) { newBlock.Instructions.Add(true ? new Instr(instr.Instruction.Clone()) : instr); } } newBlock.Insert(newBlock.Instructions.Count, OpCodes.Pop.ToInstruction()); // for switch if (beforeSwitch.FallThrough != null && beforeSwitch.FallThrough == list.Last()) { targets = block.Targets; if (targets == null || index < 0 || index >= targets.Count) { target = block.FallThrough; } else { target = targets[index]; } beforeSwitch.FallThrough.Parent.Add(newBlock); beforeSwitch.SetNewFallThrough(newBlock); newBlock.SetNewFallThrough(target); modified = true; } if (beforeSwitch.Targets != null && beforeSwitch.Targets[0] == list.Last()) { targets = block.Targets; if (targets == null || index < 0 || index >= targets.Count) { target = block.FallThrough; } else { target = targets[index]; } beforeSwitch.FallThrough.Parent.Add(newBlock); beforeSwitch.SetNewTarget(0, newBlock); newBlock.SetNewFallThrough(target); modified = true; } } else if (beforeSwitch.LastInstr.OpCode.Code == Code.Switch) { //just skip } else { var newBlock = new Block(); for (int i = 0; i < list.Last().Instructions.Count - 1; i++) { var instr = list.Last().Instructions[i]; if (instr.OpCode != OpCodes.Nop) { newBlock.Instructions.Add(true ? new Instr(instr.Instruction.Clone()) : instr); } } newBlock.Insert(newBlock.Instructions.Count, OpCodes.Pop.ToInstruction()); // for switch targets = block.Targets; if (targets == null || index < 0 || index >= targets.Count) { target = block.FallThrough; } else { target = targets[index]; } beforeSwitch.FallThrough.Parent.Add(newBlock); beforeSwitch.SetNewFallThrough(newBlock); newBlock.SetNewFallThrough(target); modified = true; } if (modified == true) { break; } } } return(modified); } else if (val1 is BitVecExpr) { index = int.Parse((val1 as BitVecExpr).Simplify().ToString()); targets = block.Targets; if (targets == null || index < 0 || index >= targets.Count) { target = block.FallThrough; } else { target = targets[index]; } block.Insert(block.Instructions.Count - 1, OpCodes.Pop.ToInstruction()); block.ReplaceSwitchWithBranch(target); return(true); } return(false); }
public void TranslateInstruction(CflowTranslatorCtx translator, Instruction instr) { var stack = translator.Stack; var args = translator.Args; var locals = translator.Locals; switch (instr.OpCode.Code) { case Code.Starg: case Code.Starg_S: Translate_Starg(stack, args, (Parameter)instr.Operand); break; case Code.Stloc: case Code.Stloc_S: Translate_Stloc(stack, locals, (Local)instr.Operand); break; case Code.Stloc_0: Translate_Stloc(stack, locals, 0); break; case Code.Stloc_1: Translate_Stloc(stack, locals, 1); break; case Code.Stloc_2: Translate_Stloc(stack, locals, 2); break; case Code.Stloc_3: Translate_Stloc(stack, locals, 3); break; case Code.Ldarg: case Code.Ldarg_S: stack.Push(GetArg(stack, args, (Parameter)instr.Operand)); break; case Code.Ldarg_0: stack.Push(GetArg(stack, args, 0)); break; case Code.Ldarg_1: stack.Push(GetArg(stack, args, 1)); break; case Code.Ldarg_2: stack.Push(GetArg(stack, args, 2)); break; case Code.Ldarg_3: stack.Push(GetArg(stack, args, 3)); break; case Code.Ldloc: case Code.Ldloc_S: stack.Push(GetLocal(stack, locals, (Local)instr.Operand)); break; case Code.Ldloc_0: stack.Push(GetLocal(stack, locals, 0)); break; case Code.Ldloc_1: stack.Push(GetLocal(stack, locals, 1)); break; case Code.Ldloc_2: stack.Push(GetLocal(stack, locals, 2)); break; case Code.Ldloc_3: stack.Push(GetLocal(stack, locals, 3)); break; case Code.Ldloca: case Code.Ldloca_S: Translate_Ldloca(stack, locals, (Local)instr.Operand); break; case Code.Dup: stack.CopyTop(); break; case Code.Ldc_I4: stack.Push(ctx.MkBV((int)instr.Operand, 32)); break; case Code.Ldc_I4_S: stack.Push(ctx.MkBV((sbyte)instr.Operand, 32)); break; case Code.Ldc_I4_0: stack.Push(ctx.MkBV(0, 32)); break; case Code.Ldc_I4_1: stack.Push(ctx.MkBV(1, 32)); break; case Code.Ldc_I4_2: stack.Push(ctx.MkBV(2, 32)); break; case Code.Ldc_I4_3: stack.Push(ctx.MkBV(3, 32)); break; case Code.Ldc_I4_4: stack.Push(ctx.MkBV(4, 32)); break; case Code.Ldc_I4_5: stack.Push(ctx.MkBV(5, 32)); break; case Code.Ldc_I4_6: stack.Push(ctx.MkBV(6, 32)); break; case Code.Ldc_I4_7: stack.Push(ctx.MkBV(7, 32)); break; case Code.Ldc_I4_8: stack.Push(ctx.MkBV(8, 32)); break; case Code.Ldc_I4_M1: stack.Push(ctx.MkBV(-1, 32)); break; case Code.Ldnull: stack.Push(stack.Unknown()); break; case Code.Ldstr: stack.Push(stack.Unknown()); break; case Code.Add: Translate_Add(stack, instr); break; case Code.Sub: Translate_Sub(stack, instr); break; case Code.Mul: Translate_Mul(stack, instr); break; case Code.Div: Translate_Div(stack, instr); break; case Code.Div_Un: Translate_Div_Un(stack, instr); break; case Code.Rem: Translate_Rem(stack, instr); break; case Code.Rem_Un: Translate_Rem_Un(stack, instr); break; case Code.Neg: Translate_Neg(stack, instr); break; case Code.And: Translate_And(stack, instr); break; case Code.Or: Translate_Or(stack, instr); break; case Code.Xor: Translate_Xor(stack, instr); break; case Code.Not: Translate_Not(stack, instr); break; case Code.Shl: Translate_Shl(stack, instr); break; case Code.Shr: Translate_Shr(stack, instr); break; case Code.Shr_Un: Translate_Shr_Un(stack, instr); break; case Code.Ceq: Translate_Ceq(stack, instr); break; case Code.Cgt: Translate_Cgt(stack, instr); break; case Code.Cgt_Un: Translate_Cgt_Un(stack, instr); break; case Code.Clt: Translate_Clt(stack, instr); break; case Code.Clt_Un: Translate_Clt_Un(stack, instr); break; case Code.Box: stack.Push(stack.Pop()); break; case Code.Unbox_Any: stack.Push(stack.Pop()); break; case Code.Add_Ovf: Translate_Add_Ovf(stack, instr); break; case Code.Add_Ovf_Un: Translate_Add_Ovf_Un(stack, instr); break; case Code.Sub_Ovf: Translate_Sub_Ovf(stack, instr); break; case Code.Sub_Ovf_Un: Translate_Sub_Ovf_Un(stack, instr); break; case Code.Mul_Ovf: Translate_Mul_Ovf(stack, instr); break; case Code.Mul_Ovf_Un: Translate_Mul_Ovf_Un(stack, instr); break; case Code.Ldlen: Translate_Ldlen(stack, instr); break; case Code.Sizeof: Translate_Sizeof(stack, instr); break; case Code.Ldsfld: Translate_Ldsfld(stack, instr); break; case Code.Ldind_I4: Translate_Ldind_I4(stack, instr); break; default: UpdateStack(stack, instr); break; } }