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 Rl_SliceRegister() { Identifier eax = f.EnsureRegister(Registers.eax); Identifier ax = f.EnsureRegister(Registers.ax); Identifier ecx = f.EnsureRegister(Registers.ecx); m.MStore(m.Int32(0x01F3004), ax).Instruction.Accept(rl); Assert.AreEqual(" ax", Dump(rl.IdentifierLiveness)); m.Assign(eax, ecx).Accept(rl); Assert.AreEqual(16, rl.IdentifierLiveness.DefBitSize); Assert.AreEqual(" cx", Dump(rl.IdentifierLiveness)); }
public void BwReg_00121() { var d0 = m.Reg32("d0", 0); var d3 = m.Reg32("d3", 3); var a5 = m.Reg32("a5", 5); var v38 = m.Temp(PrimitiveType.Word16, "v38"); var v39 = m.Temp(PrimitiveType.Byte, "v39"); var v40 = m.Temp(PrimitiveType.Word16, "v40"); var VZN = m.Flags("VZN"); var ZN = m.Flags("ZN"); var C = m.Flags("C"); var V = m.Flags("V"); var CVZN = m.Flags("CVZN"); var CVZNX = m.Flags("CVZNX"); m.Assign(d0, d3); m.Assign(CVZN, m.Cond(d0)); m.Assign(v38, m.And(m.Slice(PrimitiveType.Word16, d0, 0), 0xF0)); m.Assign(d0, m.Dpb(d0, v38, 0)); m.Assign(ZN, m.Cond(v38)); m.Assign(C, false); m.Assign(V, false); m.Assign(v39, m.Shl(m.Slice(PrimitiveType.Byte, d0, 0), 2)); m.Assign(d0, m.Dpb(d0, v39, 0)); m.Assign(CVZNX, m.Cond(v39)); m.Assign(v40, m.ISub(m.Slice(PrimitiveType.Word16, d0, 0), 44)); m.Assign(CVZN, m.Cond(v40)); m.BranchIf(m.Test(ConditionCode.GT, VZN), "lDefault"); m.Assign(a5, m.Mem32(m.IAdd(Address.Ptr32(0x0000C046), d0))); var xfer = new RtlCall(a5, 4, InstrClass.Transfer); var bw = new Backwalker <Block, Instruction>(host, xfer, expSimp); Assert.IsTrue(bw.CanBackwalk()); Assert.AreEqual("a5", bw.Index.Name); bw.BackWalk(m.Block); Assert.AreEqual("v40", bw.IndexExpression.ToString()); }
public void CceEqId() { Identifier r = Reg32("r"); Identifier z = FlagGroup("z"); // is a condition code. Identifier y = FlagGroup("y"); // is a condition code. m.Assign(z, new ConditionOf(r)); ssaIds[z].DefStatement = m.Block.Statements.Last; m.Assign(y, z); ssaIds[y].DefStatement = m.Block.Statements.Last; ssaIds[z].Uses.Add(m.Block.Statements.Last); var stmBr = m.BranchIf(m.Test(ConditionCode.EQ, y), "foo"); ssaIds[y].Uses.Add(stmBr); Given_ConditionCodeEliminator(); cce.Transform(); Assert.AreEqual("branch r == 0x00000000 foo", stmBr.Instruction.ToString()); }
public void BwAdd() { var eax = m.Frame.EnsureRegister(Registers.eax); var bw = new Backwalker( host, new RtlGoto(m.LoadDw(m.IAdd(eax, 0x10000)), RtlClass.Transfer), expSimp); Assert.IsTrue(bw.BackwalkInstruction(m.Assign(eax, m.IAdd(eax, eax)))); Assert.AreSame(Registers.eax, bw.Index); Assert.AreEqual("* 2", bw.Operations[0].ToString()); Assert.AreEqual(2, bw.Stride); }
public void ProcStr_IfThen() { var r1 = m.Reg32("r1", 1); 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 VpIndirectCall() { var callee = CreateExternalProcedure( "foo", 12, RegArg(1, "r1"), StackArg(4), StackArg(8)); var pc = new ProcedureConstant(PrimitiveType.Ptr32, callee); var m = new ProcedureBuilder(); var r1 = m.Reg32("r1", 1); var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister); m.Assign(sp, m.Frame.FramePointer); m.Assign(r1, pc); m.Assign(sp, m.ISub(sp, 4)); m.MStore(sp, m.Word32(3)); m.Assign(sp, m.ISub(sp, 4)); m.MStore(sp, m.Mem16(m.Word32(0x1231230))); m.Call(r1, 4); m.Return(); arch.Setup(a => a.CreateStackAccess( It.IsAny <IStorageBinder>(), It.IsAny <int>(), It.IsAny <DataType>())) .Returns((IStorageBinder f, int off, DataType dt) => m.Mem(dt, m.IAdd(f.EnsureRegister((RegisterStorage)sp.Storage), off))); arch.Setup(s => s.CreateFrameApplicationBuilder( It.IsAny <IStorageBinder>(), It.IsAny <CallSite>(), It.IsAny <Expression>())) .Returns((IStorageBinder binder, CallSite site, Expression c) => new FrameApplicationBuilder(arch.Object, binder, site, c, false)); var ssa = RunTest(m); var sExp = #region Expected @"fp:fp def: def fp uses: r63_2 = fp r63_4 = fp - 4<32> Mem5[fp - 4<32>:word32] = 3<32> r63_6 = fp - 8<32> Mem7[fp - 8<32>:word16] = Mem5[0x1231230<32>:word16] r1_8 = foo(Mem7[fp - 8<32>:word32], Mem7[fp - 4<32>:word32]) r1_8 = foo(Mem7[fp - 8<32>:word32], Mem7[fp - 4<32>:word32]) r63_2: orig: r63 def: r63_2 = fp r1_3: orig: r1 def: r1_3 = foo r63_4: orig: r63 def: r63_4 = fp - 4<32> Mem5: orig: Mem0 def: Mem5[fp - 4<32>:word32] = 3<32> uses: Mem7[fp - 8<32>:word16] = Mem5[0x1231230<32>:word16] r63_6: orig: r63 def: r63_6 = fp - 8<32> Mem7: orig: Mem0 def: Mem7[fp - 8<32>:word16] = Mem5[0x1231230<32>:word16] uses: r1_8 = foo(Mem7[fp - 8<32>:word32], Mem7[fp - 4<32>:word32]) r1_8 = foo(Mem7[fp - 8<32>:word32], Mem7[fp - 4<32>:word32]) r1_8: orig: r1 def: r1_8 = foo(Mem7[fp - 8<32>:word32], Mem7[fp - 4<32>:word32]) // ProcedureBuilder // Return size: 0 define ProcedureBuilder ProcedureBuilder_entry: def fp // succ: l1 l1: r63_2 = fp r1_3 = foo r63_4 = fp - 4<32> Mem5[fp - 4<32>:word32] = 3<32> r63_6 = fp - 8<32> Mem7[fp - 8<32>:word16] = Mem5[0x1231230<32>:word16] r1_8 = foo(Mem7[fp - 8<32>:word32], Mem7[fp - 4<32>:word32]) return // succ: ProcedureBuilder_exit ProcedureBuilder_exit: "; #endregion AssertStringsEqual(sExp, ssa); }
public void Larw_FindCond() { Block block = null; RunTest(m => { m.Assign(ax, m.IAdd(ax, cx)); m.Assign(SCZ, m.Cond(ax)); block = m.CurrentBlock; m.Return(); }); var ax_3 = GetId("ax_3"); var cm = rw.FindConditionOf(block.Statements, 0, ax_3); Assert.AreEqual("SCZ_4", cm.FlagGroup.ToString()); Assert.AreEqual("SCZ_4 = cond(ax_3)", cm.Statement.ToString()); }
public void VpUndoUnnecessarySlicingOfSegmentPointer() { var m = new ProcedureBuilder(); var es = m.Reg16("es", 1); var bx = m.Reg16("bx", 3); var es_bx = m.Frame.EnsureSequence(PrimitiveType.Word32, es.Storage, bx.Storage); m.Assign(es_bx, m.SegMem(PrimitiveType.Word32, es, bx)); m.Assign(es, m.Slice(PrimitiveType.Word16, es_bx, 16)); m.Assign(bx, m.Slice(PrimitiveType.Word16, es_bx, 0)); m.SStore(es, m.IAdd(bx, 4), m.Byte(3)); var ssa = RunTest(m); var sExp = #region Expected @"es:es def: def es uses: es_bx_4 = Mem0[es:bx:word32] bx:bx def: def bx uses: es_bx_4 = Mem0[es:bx:word32] Mem0:Mem def: def Mem0 uses: es_bx_4 = Mem0[es:bx:word32] es_bx_4: orig: es_bx def: es_bx_4 = Mem0[es:bx:word32] uses: es_5 = SLICE(es_bx_4, word16, 16) (alias) bx_6 = SLICE(es_bx_4, word16, 0) (alias) es_7 = SLICE(es_bx_4, word16, 16) bx_8 = SLICE(es_bx_4, word16, 0) Mem9[es_bx_4 + 4<16>:byte] = 3<8> es_5: orig: es def: es_5 = SLICE(es_bx_4, word16, 16) (alias) bx_6: orig: bx def: bx_6 = SLICE(es_bx_4, word16, 0) (alias) es_7: orig: es def: es_7 = SLICE(es_bx_4, word16, 16) bx_8: orig: bx def: bx_8 = SLICE(es_bx_4, word16, 0) Mem9: orig: Mem0 def: Mem9[es_bx_4 + 4<16>:byte] = 3<8> // ProcedureBuilder // Return size: 0 define ProcedureBuilder ProcedureBuilder_entry: def es def bx def Mem0 // succ: l1 l1: es_bx_4 = Mem0[es:bx:word32] es_5 = SLICE(es_bx_4, word16, 16) (alias) bx_6 = SLICE(es_bx_4, word16, 0) (alias) es_7 = SLICE(es_bx_4, word16, 16) bx_8 = SLICE(es_bx_4, word16, 0) Mem9[es_bx_4 + 4<16>:byte] = 3<8> ProcedureBuilder_exit: "; #endregion AssertStringsEqual(sExp, ssa); }
public void FindCond() { m.Assign(ax, m.IAdd(ax, cx)); m.Assign(SCZ, m.Cond(ax)); var block = m.CurrentBlock; m.Return(); var cm = rw.FindConditionOf(block.Statements, 0, ax); Assert.AreEqual("SCZ", cm.FlagGroup.ToString()); Assert.AreEqual(1, cm.StatementIndex); }
public void VpIndirectCall() { var callee = CreateExternalProcedure("foo", RegArg(1, "r1"), StackArg(4), StackArg(8)); var pc = new ProcedureConstant(PrimitiveType.Ptr32, callee); var m = new ProcedureBuilder(); var r1 = m.Reg32("r1", 1); var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister); m.Assign(r1, pc); m.Assign(sp, m.ISub(sp, 4)); m.MStore(sp, m.Word32(3)); m.Assign(sp, m.ISub(sp, 4)); m.MStore(sp, m.Mem16(m.Word32(0x1231230))); m.Call(r1, 4); m.Return(); arch.Setup(a => a.CreateStackAccess( It.IsAny <IStorageBinder>(), It.IsAny <int>(), It.IsAny <DataType>())) .Returns((IStorageBinder f, int off, DataType dt) => m.Mem(dt, m.IAdd(sp, off))); var ssa = RunTest(m); var sExp = #region Expected @"r1_0: orig: r1 def: r1_0 = foo r63:r63 def: def r63 uses: r63_2 = r63 - 0x00000004 Mem3[r63 - 0x00000004:word32] = 0x00000003 r63_4 = r63 - 0x00000008 Mem5[r63 - 0x00000008:word16] = Mem3[0x01231230:word16] r1_6 = foo(Mem8[r63 - 0x00000008:word32], Mem9[r63 - 0x00000004:word32]) r1_6 = foo(Mem8[r63 - 0x00000008:word32], Mem9[r63 - 0x00000004:word32]) r63_2: orig: r63 def: r63_2 = r63 - 0x00000004 Mem3: orig: Mem0 def: Mem3[r63 - 0x00000004:word32] = 0x00000003 uses: Mem5[r63 - 0x00000008:word16] = Mem3[0x01231230:word16] r63_4: orig: r63 def: r63_4 = r63 - 0x00000008 Mem5: orig: Mem0 def: Mem5[r63 - 0x00000008:word16] = Mem3[0x01231230:word16] r1_6: orig: r1 def: r1_6 = foo(Mem8[r63 - 0x00000008:word32], Mem9[r63 - 0x00000004:word32]) r63_7: orig: r63 Mem8: orig: Mem0 uses: r1_6 = foo(Mem8[r63 - 0x00000008:word32], Mem9[r63 - 0x00000004:word32]) Mem9: orig: Mem0 uses: r1_6 = foo(Mem8[r63 - 0x00000008:word32], Mem9[r63 - 0x00000004:word32]) // ProcedureBuilder // Return size: 0 void ProcedureBuilder() ProcedureBuilder_entry: def r63 // succ: l1 l1: r1_0 = foo r63_2 = r63 - 0x00000004 Mem3[r63 - 0x00000004:word32] = 0x00000003 r63_4 = r63 - 0x00000008 Mem5[r63 - 0x00000008:word16] = Mem3[0x01231230:word16] r1_6 = foo(Mem8[r63 - 0x00000008:word32], Mem9[r63 - 0x00000004:word32]) return // succ: ProcedureBuilder_exit ProcedureBuilder_exit: "; #endregion AssertStringsEqual(sExp, ssa); }
/// <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, new RegisterStorage("a", 1, 0, PrimitiveType.Word32)); 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 program = new Program() { Architecture = m.Architecture, }; var sst = new SsaTransform( program, m.Procedure, new HashSet <Procedure>(), null, new ProgramDataFlow()); sst.Transform(); /* * * 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); */ ssa = sst.SsaState; List <SsaIdentifier> list = new List <SsaIdentifier> { ssa.Identifiers.Where(i => i.Identifier.Name == "a_1").Single(), ssa.Identifiers.Where(i => i.Identifier.Name == "a_2").Single(), ssa.Identifiers.Where(i => i.Identifier.Name == "a_3").Single(), }; return(list); }
public void TrashRegister() { var r1 = m.Register(1); var stm = m.Assign(r1, m.Int32(0)); trf = CreateTrashedRegisterFinder(); CreateBlockFlow(m.Block, m.Frame); trf.StartProcessingBlock(m.Block); stm.Accept(trf); Debug.WriteLine(trf.RegisterSymbolicValues[(RegisterStorage)r1.Storage].ToString()); Assert.IsTrue(trf.IsTrashed(r1.Storage), "r1 should have been marked as trashed."); }