public void Avoid() { m.Assign(SCZ, m.Cond(m.ISub(cx, 0x0030))); m.Assign(ax, m.IAdd(m.Word16(0x0000), CF)); m.Assign(SCZ, m.Cond(ax)); m.Assign(SCZ, m.Cond(m.ISub(cx, 0x003A))); m.Assign(CF, m.Not(CF)); m.Assign(ax, m.IAdd(m.IAdd(ax, ax), CF)); m.Assign(SCZ, m.Cond(ax)); var block = m.Block; m.Return(); rw.Transform(); var sExp = @"l1: SCZ = cond(cx - 0x0030) ax = 0x0000 + C SCZ = cond(ax) SCZ = cond(cx - 0x003A) C = !C ax = ax + ax + C SCZ = cond(ax) return "; var sb = new StringWriter(); block.Write(sb); Assert.AreEqual(sExp, sb.ToString()); }
public void Exs_UnsignedRangeComparison() { Given_ExpressionSimplifier(); var expr = m.Ugt(m.ISub(foo, 2), m.Word32(5)); Assert.AreEqual("foo_0 >u 0x00000007 || foo_0 <u 0x00000002", expr.Accept(simplifier).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 VpEquality2() { // Makes sure that // y = x - 2 // if (y == 0) ... // doesn't get munged into // y = x - 2 // if (x == 2) Identifier x = Reg32("x"); Identifier y = Reg32("y"); ProcedureBuilder m = new ProcedureBuilder(); var stmX = m.Assign(x, m.LoadDw(Constant.Word32(0x1000300))); ssaIds[x].DefStatement = m.Block.Statements.Last; var stmY = m.Assign(y, m.ISub(x, 2)); ssaIds[y].DefStatement = m.Block.Statements.Last; var stm = m.BranchIf(m.Eq(y, 0), "test"); Assert.AreEqual("x = Mem0[0x01000300:word32]", stmX.ToString()); Assert.AreEqual("y = x - 0x00000002", stmY.ToString()); Assert.AreEqual("branch y == 0x00000000 test", stm.ToString()); var vp = new ValuePropagator(arch, ssaIds, null); vp.Transform(stm); Assert.AreEqual("branch x == 0x00000002 test", stm.Instruction.ToString()); }
public void CceSetnz() { Identifier r = Reg32("r"); Identifier Z = FlagGroup("Z"); Identifier f = Reg32("f"); Statement stmZ = new Statement(0, m.Assign(Z, m.Cond(m.ISub(r, 0))), null); ssaIds[Z].DefStatement = stmZ; Statement stmF = new Statement(0, m.Assign(f, m.Test(ConditionCode.NE, Z)), null); ssaIds[f].DefStatement = stmF; ssaIds[Z].Uses.Add(stmF); Given_ConditionCodeEliminator(); cce.Transform(); Assert.AreEqual("f = r != 0x00000000", stmF.Instruction.ToString()); }
public void AtrcoIdMinusConst() { Identifier r = m.Local32("r"); MemoryAccess mem = m.Load(PrimitiveType.Word32, m.ISub(r, 4)); mem.Accept(eqb); atrco.Collect(null, 0, mem, mem.EffectiveAddress); Verify(null, "Typing/AtrcoIdMinusConst.txt"); }
public void VpShiftSum() { ProcedureBuilder m = new ProcedureBuilder(); Expression e = m.Shl(1, m.ISub(Constant.Byte(32), 1)); var vp = new ExpressionSimplifier(segmentMap, new SsaEvaluationContext(arch.Object, null, dynamicLinker.Object), listener); e = e.Accept(vp); Assert.AreEqual("0x80000000<32>", e.ToString()); }
public void VpShiftSum() { ProcedureBuilder m = new ProcedureBuilder(); Expression e = m.Shl(1, m.ISub(Constant.Byte(32), 1)); var vp = new ExpressionSimplifier(new SsaEvaluationContext(arch, null), listener); e = e.Accept(vp); Assert.AreEqual("0x80000000", e.ToString()); }
public void VpShiftSum() { Constant c = Constant.Word32(1); ProcedureBuilder m = new ProcedureBuilder(); Expression e = m.Shl(1, m.ISub(Constant.Byte(32), 1)); var vp = new ExpressionSimplifier(new SsaEvaluationContext(ssaIds)); e = e.Accept(vp); Assert.AreEqual("0x80000000", e.ToString()); }
public void VpPhiLoops() { var m = new ProcedureBuilder(); var ssa = new SsaState(m.Procedure, null); ssaIds = ssa.Identifiers; var fp = Reg16("fp"); var a = Reg16("a"); var b = Reg16("b"); var c = Reg16("c"); var d = Reg16("d"); var x = Reg16("x"); var y = Reg16("y"); var z = Reg16("z"); m.Emit(m.Assign(y, m.IAdd(x, 4))); m.Emit(m.Assign(z, m.ISub(x, 8))); m.Emit(m.Assign(a, m.ISub(fp, 12))); m.Emit(m.Assign(b, m.ISub(fp, 12))); m.Emit(m.Assign(c, m.ISub(y, 4))); m.Emit(m.Assign(d, m.IAdd(z, 8))); var phiStm = m.Phi(x, a, b, c, d); var stms = m.Procedure.EntryBlock.Succ[0].Statements; stms.ForEach(stm => { var ass = stm.Instruction as Assignment; if (ass != null) { ssaIds[ass.Dst].DefStatement = stm; } var phiAss = stm.Instruction as PhiAssignment; if (phiAss != null) { ssaIds[phiAss.Dst].DefStatement = stm; } }); var vp = new ValuePropagator(arch, ssa, listener); vp.Transform(); Assert.AreEqual("x = fp - 0x000C", phiStm.Instruction.ToString()); }
private void indirect_call_two_arguments(ProcedureBuilder m) { var esp = m.Frame.EnsureIdentifier(m.Architecture.StackRegister); var eax = m.Frame.EnsureIdentifier(this.eax.Storage); var ecx = m.Frame.EnsureIdentifier(this.ecx.Storage); m.Assign(esp, m.Frame.FramePointer); m.Assign(eax, m.Mem32(m.IAdd(esp, 4))); // get argument to this fn. m.Assign(ecx, m.Mem32(eax)); m.Assign(esp, m.ISub(esp, 4)); // push arg2 m.MStore(esp, m.Word32(0x000B)); m.Assign(esp, m.ISub(esp, 4)); // push arg1 m.MStore(esp, m.Word32(0x000A)); // We expect the following call to be resolved as // (Mem0[ecx + 8:ptr32])(arg1, arg2) var c = m.Call(m.Mem32(m.IAdd(ecx, 8)), 4); c.CallSite.StackDepthOnEntry = 12; m.Return(); }
public void VpLoop() { var b = new ProgramBuilder(); b.Add("main", m => { var r = m.Reg32("r0", 0); var zf = m.Flags("Z"); m.Label("l0000"); m.Store(r, 0); m.Assign(r, m.ISub(r, 4)); m.Assign(zf, m.Cond(r)); m.BranchCc(ConditionCode.NE, "l0000"); m.Label("l0001"); m.Assign(r, 42); m.Label("l0002"); m.Store(r, 12); m.Assign(r, m.ISub(r, 4)); m.BranchIf(m.Eq0(r), "l0002"); m.Return(); }); RunFileTest(b.BuildProgram(), "Analysis/VpLoop.txt"); }
public void VpPhiLoopsSimplifyArgs() { var m = new ProcedureBuilder(); var sp = Reg16("sp"); var sp_1 = Reg16("sp_1"); var sp_2 = Reg16("sp_2"); var a = Reg16("a"); var b = Reg16("b"); var c = Reg16("c"); var d = Reg16("d"); var v = Reg16("v"); var w = Reg16("w"); var x = Reg16("x"); var y = Reg16("y"); var z = Reg16("z"); m.Phi(sp, sp_1, sp_2); m.Assign(v, m.ISub(sp, 4)); m.Assign(w, m.ISub(sp, 8)); m.Assign(y, m.IAdd(x, 4)); m.Assign(z, m.ISub(x, 8)); m.Assign(a, m.ISub(v, 8)); m.Assign(b, m.ISub(w, 4)); m.Assign(c, m.ISub(y, 4)); m.Assign(d, m.IAdd(z, 8)); var phiStm = m.Phi(x, a, b, c, d); RunValuePropagator(m); Assert.AreEqual("x = sp - 0x000C", phiStm.Instruction.ToString()); }
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 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.Cast(PrimitiveType.Word16, d0), 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.Cast(PrimitiveType.Byte, d0), 2)); m.Assign(d0, m.Dpb(d0, v39, 0)); m.Assign(CVZNX, m.Cond(v39)); m.Assign(v40, m.ISub(m.Cast(PrimitiveType.Word16, d0), 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, RtlClass.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 BwComparison() { var eax = m.Frame.EnsureRegister(Registers.eax); var SCZO = m.Frame.EnsureFlagGroup((uint)(FlagM.SF | FlagM.ZF | FlagM.CF | FlagM.OF), "SCZO", PrimitiveType.Byte); var bw = new Backwalker(host, new RtlGoto(m.LoadDw(m.IAdd(eax, 0x1000)), RtlClass.Transfer), expSimp); bw.UsedFlagIdentifier = m.Frame.EnsureFlagGroup((uint)FlagM.CF, "C", PrimitiveType.Byte); Assert.IsFalse(bw.BackwalkInstruction( m.Assign(SCZO, new ConditionOf(m.ISub(eax, 3)))), "Encountering this comparison should terminate the backwalk"); Assert.AreSame(Registers.eax, bw.Index); Assert.AreEqual("cmp 3", bw.Operations[0].ToString()); }
public void Larw_Avoid() { RunTest(m => { m.Assign(SCZ, m.Cond(m.ISub(cx, 0x0030))); m.Assign(ax, m.IAdd(m.Word16(0x0000), CF)); m.Assign(SCZ, m.Cond(ax)); m.Assign(SCZ, m.Cond(m.ISub(cx, 0x003A))); m.Assign(CF, m.Not(CF)); m.Assign(ax, m.IAdd(m.IAdd(ax, ax), CF)); m.Assign(SCZ, m.Cond(ax)); block = m.Block; m.Return(); }); rw.Transform(); var sExp = @"l1: SCZ_2 = cond(cx - 0x30<16>) C_3 = SLICE(SCZ_2, bool, 2) (alias) ax_4 = 0<16> + C_3 SCZ_5 = cond(ax_4) SCZ_6 = cond(cx - 0x3A<16>) C_7 = SLICE(SCZ_6, bool, 2) (alias) C_8 = !C_7 ax_9 = ax_4 + ax_4 + C_8 SCZ_10 = cond(ax_9) C_11 = SLICE(SCZ_10, bool, 2) (alias) S_12 = SLICE(SCZ_10, bool, 0) (alias) Z_13 = SLICE(SCZ_10, bool, 1) (alias) return "; var sb = new StringWriter(); block.Write(sb); Assert.AreEqual(sExp, sb.ToString()); }
/// <summary> /// Models a call to an indirect function pointed to by /// ecx, with one stack argument. /// </summary> private void indirect_call_one_argument(ProcedureBuilder m) { var esp = m.Frame.EnsureIdentifier(m.Architecture.StackRegister); var eax = m.Frame.EnsureIdentifier(this.eax.Storage); var ecx = m.Frame.EnsureIdentifier(this.ecx.Storage); m.Assign(esp, m.Frame.FramePointer); m.Assign(eax, m.Mem32(m.IAdd(esp, 4))); m.Assign(ecx, m.Mem32(eax)); m.Assign(esp, m.ISub(esp, 4)); m.MStore(esp, m.Word32(0x000A)); var c = m.Call(m.Mem32(m.IAdd(ecx, 4)), 4); c.CallSite.StackDepthOnEntry = 8; m.Return(); }
public void SsaPushAndPop() { // Mirrors the pattern of stack accesses used by x86 compilers. var m = new ProcedureBuilder("SsaPushAndPop"); var esp = EnsureRegister32(m, "esp"); var ebp = EnsureRegister32(m, "ebp"); var eax = EnsureRegister32(m, "eax"); m.Assign(esp, m.ISub(esp, 4)); m.MStore(esp, ebp); m.Assign(ebp, esp); m.Assign(eax, m.Mem32(m.IAdd(ebp, 8))); // dwArg04 m.Assign(ebp, m.Mem32(esp)); m.Assign(esp, m.IAdd(esp, 4)); m.Return(); RunUnitTest(m, "Analysis/SsaPushAndPop.txt"); }
public void TrfCopyBack() { var esp = m.Frame.EnsureRegister(Registers.esp); var r2 = m.Register(2); var stm1 = m.MStore(m.ISub(esp, 0x10), r2); var stm2 = m.Assign(r2, m.Int32(0)); var stm3 = m.Assign(r2, m.Mem32(m.ISub(esp, 0x10))); trf = CreateTrashedRegisterFinder(); var flow = CreateBlockFlow(m.Block, m.Frame); flow.SymbolicIn.SetValue((Identifier)esp, (Expression)this.m.Frame.FramePointer); trf.StartProcessingBlock(m.Block); stm1.Instruction.Accept(trf); stm2.Accept(trf); stm3.Accept(trf); Assert.AreEqual(r2, trf.RegisterSymbolicValues[(RegisterStorage)r2.Storage]); }
public void Exs_UnsignedRangeComparison() { Given_ExpressionSimplifier(); var(expr, _) = m.Ugt(m.ISub(foo, 2), m.Word32(5)).Accept(simplifier); Assert.AreEqual("foo_1 >u 7<32> || foo_1 <u 2<32>", expr.ToString()); }
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 StrAnls_r00237() { //byte fn0800_0541(byte al, selector ds) var ds = m.Temp(PrimitiveType.SegmentSelector, "ds"); var cx_10 = m.Temp(PrimitiveType.Word16, "cx_10"); var si_12 = m.Temp(PrimitiveType.Word16, "si_12"); var ah_13 = m.Temp(PrimitiveType.Byte, "al_13"); var al_43 = m.Temp(PrimitiveType.Byte, "al_43"); var Z_26 = m.Temp(PrimitiveType.Byte, "Z_26"); m.Assign(cx_10, 20000); m.Label("l0800_0544"); m.Assign(si_12, 0x8E8A); m.Assign(ah_13, 0x00); m.Label("l0800_054A"); m.Assign(si_12, m.IAdd(si_12, 0x01)); m.BranchIf(m.Eq0(m.SegMem8(ds, si_12)), "l0800_0557"); m.Label("l0800_054F"); m.Assign(ah_13, 0x01); m.Assign(Z_26, m.Cond(m.ISub(si_12, m.SegMem16(ds, m.Word16(0x8F0B))))); m.BranchIf(m.Ne(si_12, m.SegMem16(ds, m.Word16(0x8F0B))), "l0800_055F"); m.Label("l0800_0557"); m.Assign(Z_26, m.Cond(m.ISub(si_12, 0x8F0A))); m.BranchIf(m.Eq(si_12, 0x8F0A), "l0800_055F"); m.Label("l0800_055D"); m.Goto("l0800_054A"); m.Label("l0800_055F"); m.BranchIf(Z_26, "l0800_0578"); m.Label("l0800_0561"); m.SegStore(ds, m.Word16(0x8F0B), si_12); m.Assign(al_43, m.SegMem8(ds, m.ISub(si_12, 0x8E31))); m.BranchIf(m.Eq0(al_43), "l0800_0576"); m.Label("l0800_0571"); m.BranchIf(m.Ge(al_43, 0x00), "l0800_0575"); m.Label("l0800_0573"); m.Assign(al_43, 0x00); m.Label("l0800_0575"); m.Return(al_43); m.Label("l0800_0576"); m.Goto("l0800_0583"); m.Label("l0800_0578"); m.BranchIf(m.Ne0(ah_13), "l0800_0583"); m.Label("l0800_057D"); m.SegStore(ds, m.Word16(0x8F0B), m.Byte(0)); m.Label("l0800_0583"); m.Assign(cx_10, m.ISub(cx_10, 0x01)); m.BranchIf(m.Ne0(cx_10), "l0800_0544"); m.Label("l0800_0585"); m.Return(m.Byte(0x00)); var sExp = #region Expected @" cx_10 = 20000; do { si_12 = 0x8E8A; al_13 = 0x00; do { si_12 = si_12 + 0x01; if (Mem0[ds:si_12:byte] != 0x00) { al_13 = 0x01; Z_26 = cond(si_12 - Mem0[ds:0x8F0B:word16]); if (si_12 != Mem0[ds:0x8F0B:word16]) break; } Z_26 = cond(si_12 - 0x8F0A); } while (si_12 != 0x8F0A); if (!Z_26) { Mem0[ds:0x8F0B:word16] = si_12; al_43 = Mem0[ds:si_12 - 0x8E31:byte]; if (al_43 != 0x00) { if (al_43 < 0x00) al_43 = 0x00; return al_43; } } else if (al_13 == 0x00) Mem0[ds:0x8F0B:byte] = 0x00; cx_10 = cx_10 - 0x01; } while (cx_10 != 0x00); return 0x00; "; #endregion RunTest(sExp, m.Procedure); }
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.Stub(a => a.CreateStackAccess(null, 0, null)) .IgnoreArguments() .Do(new Func <IStorageBinder, int, DataType, Expression>((f, off, dt) => m.Mem(dt, m.IAdd(sp, off)))); mr.ReplayAll(); 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); }