/// <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 TrfCallInstruction() { var callee = new Procedure("Callee", prog.Architecture.CreateFrame()); var stm = m.Call(callee, 4); var pf = new ProcedureFlow(callee, prog.Architecture); pf.TrashedRegisters[Registers.ebx.Number] = true; flow[callee] = pf; trf = CreateTrashedRegisterFinder(); CreateBlockFlow(m.Block, m.Frame); trf.StartProcessingBlock(m.Block); stm.Instruction.Accept(trf); Assert.AreEqual("(ebx:<invalid>)", DumpValues()); }
/// <summary> /// Models a call to an indirect function pointed to by /// ecx, with no arguments. /// </summary> private void indirect_call_no_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))); m.Assign(ecx, m.Mem32(eax)); m.Call(m.Mem32(ecx), 4); m.Return(); }
public void SsaCallIndirect() { var m = new ProcedureBuilder("SsaCallIndirect"); var r1 = m.Reg32("r1", 1); var r2 = m.Reg32("r2", 2); m.Assign(r1, m.Mem32(r2)); m.Call(r1, 4); m.Return(); RunUnitTest(m, "Analysis/SsaCallIndirect.txt"); }
public void CoaCallCallee() { var m = new ProcedureBuilder("foo"); var r2 = m.Register(2); var r3 = m.Register(3); m.Assign(r3, m.Fn(r2)); m.Assign(r3, m.IAdd(r3, 4)); m.Call(r3, 4); m.Return(); RunFileTest(m, "Analysis/CoaCallCallee.txt"); }
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 BlockTerminates() { var m = new ProcedureBuilder(); m.Call(exit, 4); var b = m.CurrentBlock; m.Return(); var a = new TerminationAnalysis(flow, eventListener); flow[b] = CreateBlockFlow(b, m.Frame); a.Analyze(b); Assert.IsTrue(flow[b].TerminatesProcess); }
/// <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(); }
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 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 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); }