public void BwInvertedCondition() { var ebx = m.Reg32("ebx", 3); var eax = m.Reg32("eax", 0); var CZ = m.Flags("CZ"); m.Assign(CZ, m.Cond(m.ISub(ebx, 0x30))); m.BranchIf(m.Test(ConditionCode.ULE, CZ), "do_switch"); m.Goto("default_case"); m.Label("do_switch"); m.Assign(eax, 0); var block = m.CurrentBlock; var xfer = new RtlGoto(m.Mem32(m.IAdd(Constant.Word32(0x00123400), m.IMul(ebx, 4))), InstrClass.Transfer); m.Label("default_case"); m.Return(); var bw = new Backwalker <Block, Instruction>(host, xfer, expSimp); Assert.IsTrue(bw.CanBackwalk()); var ops = bw.BackWalk(block); Assert.AreEqual(3, ops.Count); Assert.AreEqual("cmp 48", ops[0].ToString()); Assert.AreEqual("branch UGT", ops[1].ToString()); Assert.AreEqual("* 4", ops[2].ToString()); }
public void CfgcJmpToBranch() { var m = new ProcedureBuilder(); var c = m.Temp(PrimitiveType.Bool, "c"); var pfn = m.Temp(PrimitiveType.Pointer32, "pfn"); m.Label("m1"); m.BranchIf(c, "m3"); m.Label("m2"); m.Goto("m3"); m.Label("m3"); m.SideEffect(m.Fn(pfn)); m.Return(); var sExp = #region Expected @"// ProcedureBuilder // Return size: 0 void ProcedureBuilder() ProcedureBuilder_entry: pfn() return // succ: ProcedureBuilder_exit m1: m3: ProcedureBuilder_exit: "; #endregion var cfgc = new ControlFlowGraphCleaner(m.Procedure); cfgc.Transform(); var sw = new StringWriter(); m.Procedure.Write(false, sw); Assert.AreEqual(sExp, sw.ToString()); }
public void TrfPropagateStackValuesToSuccessor() { m.Label("Start"); Identifier ecx = m.Register(1); trf = CreateTrashedRegisterFinder(program); CreateBlockFlow(m.Block, m.Frame); trf.StartProcessingBlock(m.Block); trf.StackSymbolicValues[-4] = ecx; trf.StackSymbolicValues[-8] = ecx; trf.StackSymbolicValues[-12] = ecx; trf.StackSymbolicValues[-16] = m.Word32(0x1234); trf.StackSymbolicValues[-20] = m.Word32(0x5678); trf.StackSymbolicValues[-24] = m.Word32(0x9ABC); var succ = new Block(m.Procedure, "succ"); var sf = CreateBlockFlow(succ, m.Frame); flow[succ] = sf; sf.SymbolicIn.StackState[-8] = ecx; sf.SymbolicIn.StackState[-12] = Constant.Word32(1231); sf.SymbolicIn.StackState[-20] = Constant.Word32(0x5678); sf.SymbolicIn.StackState[-24] = Constant.Word32(0xCCCC); trf.PropagateToSuccessorBlock(succ); Assert.AreEqual("ecx", sf.SymbolicIn.StackState[-4].ToString(), "Didn't have a value before"); Assert.AreEqual("ecx", sf.SymbolicIn.StackState[-8].ToString(), "Same value as before"); Assert.AreEqual("<invalid>", sf.SymbolicIn.StackState[-12].ToString()); Assert.AreEqual("0x00001234", sf.SymbolicIn.StackState[-16].ToString()); Assert.AreEqual("0x00005678", sf.SymbolicIn.StackState[-20].ToString()); Assert.AreEqual("<invalid>", sf.SymbolicIn.StackState[-24].ToString()); }
/// <summary> /// Builds a strongly connected component corresponding to: /// a1 = 0 /// a2 = phi(a1, a3) /// while (a2 != 10) /// { /// a3 = a2 + 4 /// } /// </summary> private List <SsaIdentifier> BuildScc() { var m = new ProcedureBuilder("test"); Identifier a = new Identifier("a", PrimitiveType.Word32, null); m.Label("b1"); m.Assign(a, Constant.Word32(0)); m.Label("b2"); m.Assign(a, m.IAdd(a, 4)); m.BranchIf(m.Ne(a, 10), "b2"); m.Label("b3"); m.Return(); this.dom = m.Procedure.CreateBlockDominatorGraph(); var ssa = new SsaTransform( new ProgramDataFlow(), m.Procedure, null, dom, new HashSet <RegisterStorage>()); /* * * proc = new Procedure("test", new Frame(PrimitiveType.Word32)); * Block b1 = proc.AddBlock("b1"); * Block b2 = proc.AddBlock("b2"); * * Identifier a2 = new Identifier("a2", PrimitiveType.Word32, null); * Identifier a3 = new Identifier("a3", PrimitiveType.Word32, null); * PhiFunction phi = new PhiFunction(a1.DataType, new Expression [] { a1, a3 }); * * Statement stm_a1 = new Statement(0, new Assignment(a1, Constant.Word32(0)), null); * Statement stm_a2 = new Statement(0, new PhiAssignment(a2, new PhiFunction(a1.DataType, a1, a3 )), null); * Statement stm_ex = new Statement(0, new Branch(new BinaryExpression(Operator.Ne, PrimitiveType.Bool, a2, Constant.Word32(10)), b2), null); * Statement stm_a3 = new Statement(0, new Assignment(a3, new BinaryExpression(Operator.IAdd, a3.DataType, a2, Constant.Word32(4))), null); * b1.Statements.Add(stm_a1); * * b2.Statements.Add(stm_a2); * b2.Statements.Add(stm_a3); * * SsaIdentifier sid_a1 = new SsaIdentifier(a1, a1, stm_a1, ((Assignment)stm_a1.Instruction).Src, false); * SsaIdentifier sid_a2 = new SsaIdentifier(a2, a2, stm_a2, ((PhiAssignment) stm_a2.Instruction).Src, false); * SsaIdentifier sid_a3 = new SsaIdentifier(a3, a3, stm_a3, ((Assignment) stm_a3.Instruction).Src, false); * sid_a1.Uses.Add(stm_a2); * ssaIds = new SsaIdentifierCollection(); * ssaIds.Add(a1, sid_a1); * ssaIds.Add(a2, sid_a2); * ssaIds.Add(a3, sid_a3); */ ssaIds = ssa.SsaState.Identifiers; List <SsaIdentifier> list = new List <SsaIdentifier> { ssaIds.Where(i => i.Identifier.Name == "a_0").Single(), ssaIds.Where(i => i.Identifier.Name == "a_1").Single(), ssaIds.Where(i => i.Identifier.Name == "a_2").Single(), }; return(list); }
public void CceUnsignedRange() { var sExp = #region Expected @"r2:r2 def: def r2 uses: Mem4[0x00123400:word32] = r2 branch r2 >u 0x00000007 || r2 <u 0x00000002 mElse branch r2 >u 0x00000007 || r2 <u 0x00000002 mElse r1_1: orig: r1 SCZ_2: orig: SCZ CZ_3: orig: CZ Mem4: orig: Mem0 def: Mem4[0x00123400:word32] = r2 // ProcedureBuilder // Return size: 0 void ProcedureBuilder(word32 r2) ProcedureBuilder_entry: def r2 // succ: l1 l1: branch r2 >u 0x00000007 || r2 <u 0x00000002 mElse // succ: mDo mElse mDo: Mem4[0x00123400:word32] = r2 // succ: mElse mElse: return // succ: ProcedureBuilder_exit ProcedureBuilder_exit: "; #endregion RunStringTest(sExp, m => { var r1 = MockReg(m, 1); var r2 = MockReg(m, 2); var SCZ = m.Flags("SCZ"); var CZ = m.Flags("CZ"); m.Assign(r1, m.ISub(r2, 2)); m.Assign(SCZ, m.Cond(m.ISub(r1, 5))); m.BranchIf(m.Test(ConditionCode.UGT, CZ), "mElse"); m.Label("mDo"); m.MStore(m.Word32(0x00123400), r2); m.Label("mElse"); m.Return(); }); }
public void Pdg_PostDominateIfElse() { ProcedureBuilder m = new ProcedureBuilder(); m.BranchIf(m.Local32("a"), "then"); m.Assign(m.Local32("b"), m.Int32(0)); m.Jump("join"); m.Label("then"); m.Assign(m.Local32("c"), m.Int32(0)); m.Label("join"); m.Return(); FindPostDominators(m); }
public void OutpReplaceManyUses() { ProcedureBuilder m = new ProcedureBuilder(); Identifier foo = new Identifier("foo", PrimitiveType.Word32, null); Identifier bar = new Identifier("bar", PrimitiveType.Word32, null); Identifier pfoo = new Identifier("pfoo", PrimitiveType.Ptr32, null); Block block = m.Label("block"); m.Assign(foo, 1); Statement stmFoo = m.Block.Statements.Last; m.Assign(bar, foo); Statement stmBar = m.Block.Statements.Last; SsaIdentifier ssaFoo = new SsaIdentifier(foo, foo, stmFoo, ((Assignment)stmFoo.Instruction).Src, false); ssaFoo.Uses.Add(stmBar); SsaIdentifier ssaBar = new SsaIdentifier(bar, bar, stmBar, ((Assignment)stmBar.Instruction).Src, false); SsaIdentifierCollection ssaIds = new SsaIdentifierCollection(); ssaIds.Add(foo, ssaFoo); ssaIds.Add(bar, ssaBar); OutParameterTransformer opt = new OutParameterTransformer(m.Procedure, ssaIds); opt.ReplaceDefinitionsWithOutParameter(foo, pfoo); Assert.AreEqual(3, block.Statements.Count); Assert.AreEqual("foo = 0x00000001", block.Statements[0].Instruction.ToString()); Assert.AreEqual("*pfoo = foo", block.Statements[1].Instruction.ToString()); Assert.AreEqual("bar = foo", block.Statements[2].Instruction.ToString()); }
/// <summary> /// Mutually recursive functions that jump into each other's bodies. /// </summary> /// <returns></returns> public static Program BuildProgram() { var prog = new ProgramBuilder(); var m = new ProcedureBuilder("even"); var r1 = m.Register(1); m.BranchIf(m.Eq0(r1), "done"); m.Assign(r1, m.ISub(r1, 1)); m.Call("odd", 4); m.Assign(r1, m.Not(r1)); m.Return(); m.Label("done"); m.Assign(r1, true); m.Return(); prog.Add(m); m = new ProcedureBuilder("odd"); r1 = m.Register(1); m.BranchIf(m.Eq(r1, 1), "done"); m.Assign(r1, m.ISub(r1, 1)); m.Call("event", 4); m.Assign(r1, m.Not(r1)); m.Return(); m.Label("done"); m.Assign(r1, true); m.Return(); prog.Add(m); return(prog.BuildProgram()); }
public void WriteProcedure_Max() { var m = new ProcedureBuilder("proc"); var r1 = m.Register("r1"); var r2 = m.Register("r2"); var r3 = m.Register("r3"); m.BranchIf(m.Gt(r1, r2), "greaterthan"); m.Assign(r3,r2); m.Assign(r2, r1); m.Assign(r1, r3); m.Label("greaterthan"); m.Return(r1); hcf.Write(m.Procedure); var sExp = @"<span class=""kw"">define</span> proc<br /> {<br /> proc_entry:<br /> <span class=""kw"">goto</span> l1<br /> greaterthan:<br /> <span class=""kw"">return</span> r1<br /> l1:<br /> <span class=""kw"">branch</span> r1 > r2 greaterthan<br /> l2:<br /> r3 = r2<br /> r2 = r1<br /> r1 = r3<br /> <span class=""kw"">goto</span> greaterthan<br /> proc_exit:<br /> }<br /> "; Debug.Write(sb.ToString()); Assert.AreEqual(sExp, sb.ToString()); }
public void Larw_do_not_span_multiple_blocks() { var sExp = #region Expected @"l1: ax_2 = Mem0[0x0210<p16>:word16] dx_3 = Mem0[0x0212<p16>:word16] ax_4 = ax_2 + Mem0[0x0220<p16>:word16] SCZ_5 = cond(ax_4) C_6 = SLICE(SCZ_5, bool, 2) (alias) "; #endregion RunTest(sExp, m => { m.Assign(ax, m.Mem16(m.Ptr16(0x210))); block = m.Block; m.Assign(dx, m.Mem16(m.Ptr16(0x212))); m.Assign(ax, m.IAdd(ax, m.Mem16(m.Ptr16(0x0220)))); m.Assign(this.SCZ, m.Cond(ax)); m.Goto("m2"); m.Label("m2"); m.Assign(dx, m.IAdd(m.IAdd(dx, m.Mem16(m.Ptr16(0x0222))), this.CF)); }); }
private Procedure BuildSimpleLoop() { ProcedureBuilder m = new ProcedureBuilder(); Identifier p = m.Local32("p"); m.Assign(p, 0); m.Label("loop"); m.BranchIf(m.Eq(p, 0x4000), "done"); m.Store(m.IAdd(p, 0x3000), m.Int32(0)); m.Assign(p, m.IAdd(p, 4)); m.Jump("loop"); m.Label("done"); m.Return(); return(m.Procedure); }
public void SsaSwitchWithSharedBranches() { var m = new ProcedureBuilder("SsaSwitchWithSharedBranches"); var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister); var r1 = m.Reg32("r1", 1); var r2 = m.Reg32("r2", 2); var foo = new ExternalProcedure("foo", new FunctionType( new Identifier("", VoidType.Instance, null), new Identifier("arg1", PrimitiveType.Int32, new StackArgumentStorage(4, PrimitiveType.Int32)))); m.Assign(sp, m.Frame.FramePointer); m.Assign(r1, m.Mem32(m.IAdd(sp, 4))); m.BranchIf(m.Ugt(r1, m.Word32(0x5)), "m4_default"); m.Label("m1"); m.Switch(r1, "m2", "m2", "m3", "m3", "m2", "m3"); m.Label("m2"); m.Assign(sp, m.ISub(sp, 4)); m.MStore(sp, m.Word32(0x42)); m.Call(foo, 4); m.Assign(sp, m.IAdd(sp, 4)); // fall through m.Label("m3"); m.Assign(sp, m.ISub(sp, 4)); m.MStore(sp, m.Word32(42)); m.Call(foo, 4); m.Assign(sp, m.IAdd(sp, 4)); // fall through m.Label("m4_default"); m.Assign(sp, m.ISub(sp, 4)); m.MStore(sp, m.Word32(0)); m.Call(foo, 4); m.Assign(sp, m.IAdd(sp, 4)); m.Return(); RunUnitTest(m, "Analysis/SsaSwitchWithSharedBranches.txt"); }
public void Pdg_InfiniteLoop() { ProcedureBuilder m = new ProcedureBuilder(); m.Label("Infinity"); m.BranchIf(m.Eq(m.LoadW(m.Word16(0x1234)), 0), "hop"); m.SideEffect(m.Fn("foo")); m.Label("hop"); m.BranchIf(m.Eq(m.LoadW(m.Word16(0x5123)), 1), "Infinity"); m.SideEffect(m.Fn("bar")); m.Jump("Infinity"); m.Return(); FindPostDominators(m); string sExp = "hop (4): idom ProcedureBuilder_exit (6)" + nl + "Infinity (2): idom hop (4)" + nl + "l1 (3): idom hop (4)" + nl + "l2 (5): idom ProcedureBuilder_exit (6)" + nl + "ProcedureBuilder_entry (1): idom Infinity (2)" + nl + "ProcedureBuilder_exit (6): idom " + nl; Assert.AreEqual(sExp, sw.ToString()); }
public void OutpReplaceSimple() { var m = new ProcedureBuilder(); var block = m.Label("block"); var foo = new Identifier("foo", PrimitiveType.Word32, null); var pfoo = new Identifier("pfoo", PrimitiveType.Pointer32, null); m.Assign(foo, 3); var sid = new SsaIdentifier(foo, foo, m.Block.Statements.Last, null, false); var ssaIds = new SsaIdentifierCollection { { foo, sid } }; var opt = new OutParameterTransformer(null, ssaIds); opt.ReplaceDefinitionsWithOutParameter(foo, pfoo); Assert.AreEqual("*pfoo = 0x00000003", m.Block.Statements[0].ToString()); }
public void BwUnresolveableIndirect() { var eax = m.Reg32("eax", 0); var esi = m.Reg32("esi", 6); var Z = m.Frame.EnsureFlagGroup(Registers.eflags, 1, "Z", PrimitiveType.Bool); var xfer = new RtlCall(eax, 4, InstrClass.Transfer); m.Assign(eax, m.Mem32(esi)); m.Assign(Z, m.Cond(m.And(eax, eax))); m.BranchIf(m.Test(ConditionCode.EQ, Z), "null_ptr"); m.Label("do_call"); var bw = new Backwalker <Block, Instruction>(host, xfer, expSimp); Assert.IsTrue(bw.CanBackwalk()); Assert.AreEqual("eax", bw.Index.Name); bw.BackWalk(m.Block); Assert.AreEqual("None", bw.Index.ToString()); }
public void BwUnresolveableIndirect() { var eax = m.Frame.CreateTemporary("eax", PrimitiveType.Word32); var esi = m.Frame.CreateTemporary("esi", PrimitiveType.Word32); var Z = m.Frame.EnsureFlagGroup(1, "Z", PrimitiveType.Bool); var xfer = new RtlCall(eax, 4, RtlClass.Transfer); m.Assign(eax, m.LoadDw(esi)); m.Assign(Z, m.Cond(m.And(eax, eax))); m.BranchIf(m.Test(ConditionCode.EQ, Z), "null_ptr"); m.Label("do_call"); var bw = new Backwalker(host, xfer, expSimp); Assert.IsTrue(bw.CanBackwalk()); Assert.AreEqual("eax", bw.Index.Name); bw.BackWalk(m.Block); Assert.AreEqual("None", bw.Index.Name); }
public void StrAnls_Issue_529() { var m = new ProcedureBuilder(); var fp = m.Frame.FramePointer; var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister); var puts = new ExternalProcedure("puts", new FunctionType()); m.Label("m4E2"); m.Goto("m4F7"); m.Label("m4E4"); m.SideEffect(m.Fn(puts, Constant.String("Hello", StringType.NullTerminated(PrimitiveType.Byte)))); m.Return(); m.Label("m4F7"); m.BranchIf(m.Eq0(m.Mem32(m.Word32(0x0808A0A4))), "m502"); m.Label("m500"); m.Goto("m50D"); m.Label("m502"); m.BranchIf(m.Eq0(m.Mem32(m.Word32(0x0808A0A8))), "m4E4"); m.Goto("m50D"); m.Label("m50D"); m.SideEffect(m.Fn(puts, Constant.String("Goodbye", StringType.NullTerminated(PrimitiveType.Byte)))); m.Goto("m4E4"); var sExp = #region Expected @" if (Mem0[0x0808A0A4:word32] != 0x00 || Mem0[0x0808A0A8:word32] != 0x00) puts(""Goodbye""); puts(""Hello""); return; "; #endregion Given_CompoundConditionCoalescer(m.Procedure); RunTest(sExp, m.Procedure); }
public void CrwManyPredecessorsToExitBlock() { var m = new ProcedureBuilder("CrwManyPredecessorsToExitBlock"); var eax = m.Frame.EnsureRegister(Registers.eax); m.BranchIf(m.Ge0(eax), "m2Ge"); m.Label("m1Lt"); m.Assign(eax, -1); m.Return(); m.Label("m2Ge"); m.BranchIf(m.Ne0(eax), "m4Gt"); m.Label("m3Eq"); m.Return(); m.Label("m4Gt"); m.Assign(eax, 1); m.Return(); var flow = new ProgramDataFlow(program); var sst = new SsaTransform(program, m.Procedure, new HashSet <Procedure>(), null, new ProgramDataFlow()); sst.Transform(); sst.AddUsesToExitBlock(); sst.SsaState.Procedure.Signature = FunctionType.Func( new Identifier("", PrimitiveType.Word32, Registers.eax), new Identifier("eax", PrimitiveType.Word32, Registers.eax)); var crw = new CallRewriter(this.platform, flow, new FakeDecompilerEventListener()); crw.RewriteReturns(sst.SsaState); crw.RemoveStatementsFromExitBlock(sst.SsaState); var sExp = #region Expected @"eax:eax def: def eax uses: branch eax >= 0<32> m2Ge branch eax != 0<32> m4Gt return eax eax_2: orig: eax def: eax_2 = 1<32> uses: return eax_2 eax_3: orig: eax def: eax_3 = 0xFFFFFFFF<32> uses: return eax_3 eax_4: orig: eax // CrwManyPredecessorsToExitBlock // Return size: 0 word32 CrwManyPredecessorsToExitBlock(word32 eax) CrwManyPredecessorsToExitBlock_entry: def eax // succ: l1 l1: branch eax >= 0<32> m2Ge // succ: m1Lt m2Ge m1Lt: eax_3 = 0xFFFFFFFF<32> return eax_3 // succ: CrwManyPredecessorsToExitBlock_exit m2Ge: branch eax != 0<32> m4Gt // succ: m3Eq m4Gt m3Eq: return eax // succ: CrwManyPredecessorsToExitBlock_exit m4Gt: eax_2 = 1<32> return eax_2 // succ: CrwManyPredecessorsToExitBlock_exit CrwManyPredecessorsToExitBlock_exit: "; #endregion AssertExpected(sExp, sst.SsaState); }
public void ProcStr_IfThen() { var r1 = m.Reg32("r1"); m.Label("head"); m.BranchIf(m.Le(r1, 0), "tail"); m.Label("doit"); m.Assign(r1, 0); m.Label("tail"); m.Return(r1); var sExp = @" if (r1 > 0x00) r1 = 0x00; return r1; "; RunTest(sExp, m.Procedure); }
public void StrAnls_DoNoCleanProcedureCall() { m.Label("head"); m.BranchIf(m.Fn("someCheck"), "failed"); m.Goto("exit"); m.Label("failed"); m.Label("exit"); m.Return(); var sExp = @" someCheck(); return; "; RunTest(sExp, m.Procedure); }
public void CceUnsignedRange() { var sExp = #region Expected @"// ProcedureBuilder // Return size: 0 define ProcedureBuilder ProcedureBuilder_entry: def r2 // succ: l1 l1: branch r2 >u 7<32> || r2 <u 2<32> mElse // succ: mDo mElse mDo: Mem5[0x00123400<p32>:word32] = r2 // succ: mElse mElse: return // succ: ProcedureBuilder_exit ProcedureBuilder_exit: "; #endregion RunStringTest(sExp, m => { var r1 = MockReg(m, 1); var r2 = MockReg(m, 2); var SCZ = m.Flags("SCZ"); var CZ = m.Flags("CZ"); m.Assign(r1, m.ISub(r2, 2)); m.Assign(SCZ, m.Cond(m.ISub(r1, 5))); m.BranchIf(m.Test(ConditionCode.UGT, CZ), "mElse"); m.Label("mDo"); m.MStore(m.Ptr32(0x00123400), r2); m.Label("mElse"); m.Return(); }); }