/// <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 = @"void 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()); }
private void Given_Procedure(uint address) { var m = new ProcedureBuilder("fnTest"); m.Return(); this.proc = m.Procedure; this.program.Procedures[Address.Ptr32(address)] = this.proc; }
public void DeadFnReturn() { ProcedureBuilder m = new ProcedureBuilder("foo"); Identifier unused = m.Local32("unused"); m.Assign(unused, m.Fn("foo", Constant.Word32(1))); m.Return(); RunTest(m, "Analysis/DeadFnReturn.txt"); }
/// <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 SsaCallIndirect() { var m = new ProcedureBuilder("SsaCallIndirect"); var r1 = m.Reg32("r1"); var r2 = m.Reg32("r2"); m.Assign(r1, m.LoadDw(r2)); m.Call(r1, 4); m.Return(); RunUnitTest(m, "Analysis/SsaCallIndirect.txt"); }
public void BlockTerminates() { var m = new ProcedureBuilder(); m.Call(exit, 4); var b = m.CurrentBlock; m.Return(); var a = new TerminationAnalysis(flow); flow[b] = CreateBlockFlow(b, m.Frame); a.Analyze(b); Assert.IsTrue(flow[b].TerminatesProcess); }
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 FindNoLoopInInterval() { ProcedureBuilder m = new ProcedureBuilder(); m.Return(); StructureNode node = new StructureNode(m.Procedure.ControlGraph.Blocks[1], 3); node.Order = 0; Interval interval = new Interval(1, node); var nodesInInterval = interval.FindIntervalNodes(0); SccLoopFinder finder = new SccLoopFinder(interval, nodesInInterval); var loopNodes = finder.FindLoop(); Assert.AreEqual(0, loopNodes.Count); }
public void BlockDoesntTerminate() { var m = new ProcedureBuilder(); m.Store(m.Word32(0x1231), m.Byte(0)); var b = m.Block; m.Return(); var a = new TerminationAnalysis(flow); program = new Program { Architecture = new FakeArchitecture() }; flow[b] = CreateBlockFlow(b, m.Frame); a.Analyze(b); Assert.IsFalse(flow[b].TerminatesProcess); }
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.Goto("loop"); m.Label("done"); m.Return(); return m.Procedure; }
public void BlockCloner_CloneBlock() { var m = new ProcedureBuilder(arch, "fn1000"); var r1 = m.Register("r1"); var r2 = m.Register("r2"); var ass = m.Assign(r1, r2); m.Return(); var block = m.Procedure.ControlGraph.Blocks[2]; m = new ProcedureBuilder(arch, "procCalling"); var blockCloner = new BlockCloner(block, m.Procedure, callgraph); var blockNew = blockCloner.Execute(); var assNew = (Assignment) blockNew.Statements[0].Instruction; Assert.AreNotSame(ass.Dst, assNew.Dst); Assert.AreNotSame(ass.Src, assNew.Src); }
public void Cvp_SetProcedure() { codeViewer.CreateControl(); var m = new ProcedureBuilder(); m.Return(); using (mr.Record()) { var project = new Project { Programs = { new Program() } }; decompiler.Stub(d => d.Project).Return(project); } codeViewer.DisplayProcedure(m.Procedure); string sExp = "void ProcedureBuilder()" + nl + "{" + nl + "ProcedureBuilder_entry:" + nl + "l1:" + nl + " 'return'" + nl + "ProcedureBuilder_exit:" + nl + "}" + nl; Assert.AreEqual(sExp, Flatten(codeViewer.TextView.Model)); }
public void VpCastCast() { var m = new ProcedureBuilder(); m.Store( m.Word32(0x1234000), m.Cast( PrimitiveType.Real32, m.Cast( PrimitiveType.Real64, m.Load(PrimitiveType.Real32, m.Word32(0x123400))))); m.Return(); mr.ReplayAll(); RunFileTest(m, "Analysis/VpCastCast.txt"); }
public void VpIndirectCall() { var callee = CreateExternalProcedure("foo", RegArg(1, "r1"), StackArg(4), StackArg(8)); var pc = new ProcedureConstant(PrimitiveType.Pointer32, 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.Store(sp, 3); m.Assign(sp, m.ISub(sp, 4)); m.Store(sp, m.LoadW(m.Word32(0x1231230))); m.Call(r1, 4); m.Return(); arch.Stub(a => a.CreateStackAccess(null, 0, null)) .IgnoreArguments() .Do(new Func<Frame, int, DataType, Expression>((f, off, dt) => m.Load(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); }
public static void MemStore(ProcedureBuilder m) { m.Store(m.Word32(0x3120), 0); m.Store(m.Word32(0x3120), m.IAdd(m.LoadDw(m.Word32(0x3120)), 1)); m.Return(); }
public void Pdg_LoopWithIfElse() { var m = new ProcedureBuilder(); var c = m.Declare(PrimitiveType.Word32, "c"); var f = m.Declare(PrimitiveType.Bool, "f"); m.Label("loopHead"); m.BranchIf(m.Eq(c, 0), "done"); m.BranchIf(f, "then"); m.Label("else"); m.SideEffect(m.Fn("CallElse")); m.Jump("loopHead"); m.Label("then"); m.SideEffect(m.Fn("CallThen")); m.Jump("loopHead"); m.Label("done"); m.Return(); FindPostDominators(m); string sExp = "done (6): idom ProcedureBuilder_exit (7)" + nl + "else (4): idom loopHead (2)" + nl + "l1 (3): idom loopHead (2)" + nl + "loopHead (2): idom done (6)" + nl + "ProcedureBuilder_entry (1): idom loopHead (2)" + nl + "ProcedureBuilder_exit (7): idom " + nl + "then (5): idom loopHead (2)" + nl; Assert.AreEqual(sExp, sw.ToString()); }
public void Usb_ParseFunctionDeclaration_WithRegisterArgs() { var arch = new FakeArchitecture(); var m = new ProcedureBuilder(arch, "test"); var r1 = m.Reg32("r1", 1); var r2 = m.Reg32("r2", 2); m.Store(m.Word32(0x123400), m.Cast(PrimitiveType.Byte, r1)); m.Store(m.Word32(0x123404), m.Cast(PrimitiveType.Real32, r2)); m.Return(); var usb = new UserSignatureBuilder(program); usb.ApplySignatureToProcedure( Address.Create(PrimitiveType.Pointer32, 0x1000), new ProcedureSignature( null, new Identifier("r2", PrimitiveType.Char, r1.Storage), // perverse but legal. new Identifier("r1", PrimitiveType.Real32, r2.Storage)), m.Procedure); var sExp = @"// test // Return size: 0 void test(char r2, real32 r1) test_entry: // succ: l1 l1: r1 = r2 r2 = r1 Mem0[0x00123400:byte] = (byte) r1 Mem0[0x00123404:real32] = (real32) r2 return // succ: test_exit test_exit: "; var sb = new StringWriter(); m.Procedure.Write(false, sb); Assert.AreEqual(sExp, sb.ToString()); }
private void Given_StubProcedure(uint addr, uint size) { var address = Address32.Ptr32(addr); var m = new ProcedureBuilder("fnTest"); m.Return(); this.proc = m.Procedure; this.program.Procedures[address] = proc; var item = new ImageMapBlock { Address = address, Size = size, Block = new Block(proc, "fakeBlock") }; program.ImageMap.AddItemWithSize(address, item); }
public void Scanner_IsLinearReturn_EndsWithReturn() { var scanner = CreateScanner(0x1000, 0x1000); var m = new ProcedureBuilder(arch, "fn1000"); m.Return(); var block = m.Procedure.ControlGraph.Blocks[2]; Assert.IsTrue(scanner.IsLinearReturning(block)); }
public void SsaOutParamters() { ProcedureBuilder m = new ProcedureBuilder("foo"); Identifier r4 = m.Register(4); m.Store(m.Int32(0x400), m.Fn("foo", m.Out(PrimitiveType.Pointer32, r4))); m.Return(); RunFileTest(m, "Analysis/SsaOutParameters.txt"); }
public void Pdg_PostdominateLoop() { ProcedureBuilder m = new ProcedureBuilder(); m.Jump("test"); m.Label("test"); m.BranchIf(m.LocalBool("f"), "done"); m.Label("body"); m.Store(m.Int32(30), m.Int32(0)); m.Jump("test"); m.Label("done"); m.Return(); FindPostDominators(m); string sExp = "body (4): idom test (3)" + nl + "done (5): idom ProcedureBuilder_exit (6)" + nl + "l1 (2): idom test (3)" + nl + "ProcedureBuilder_entry (1): idom l1 (2)" + nl + "ProcedureBuilder_exit (6): idom " + nl + "test (3): idom done (5)" + nl; Console.WriteLine(sw.ToString()); Assert.AreEqual(sExp, sw.ToString()); }
public void VpAddress32Const() { var m = new ProcedureBuilder("VpAddress32Const"); var r1 = m.Reg32("r1", 1); m.Assign(r1, Address.Ptr32(0x00123400)); m.Assign(r1, m.Load(r1.DataType, m.IAdd(r1, 0x56))); m.Return(); mr.ReplayAll(); RunFileTest(m, "Analysis/VpAddress32Const.txt"); }
public void DfaUnsignedDiv() { var m = new ProcedureBuilder(); var r1 = m.Register(1); var r2 = m.Register(2); var r2_r1 = m.Frame.EnsureSequence(r2.Storage, r1.Storage, PrimitiveType.Word64); var tmp = m.Frame.CreateTemporary(r2_r1.DataType); m.Assign(r1, m.LoadDw(m.Word32(0x123400))); m.Assign(r2_r1, m.Seq(m.Word32(0), r1)); m.Assign(tmp, r2_r1); m.Assign(r1, m.UDiv(tmp, m.Word32(42))); m.Store(m.Word32(0x123404), r1); m.Return(); RunFileTest(m, "Analysis/DfaUnsignedDiv.txt"); }
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.Store(esp, ebp); m.Assign(ebp, esp); m.Assign(eax, m.LoadDw(m.IAdd(ebp, 8))); // dwArg04 m.Assign(ebp, m.LoadDw(esp)); m.Assign(esp, m.IAdd(esp,4)); m.Return(); RunUnitTest(m, "Analysis/SsaPushAndPop.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()); }
private void Given_StubProcedure() { var m = new ProcedureBuilder("fnTest"); m.Return(); this.proc = m.Procedure; this.program.Procedures[Address.Ptr32(0x1234)] = proc; }
public void SsaStackReference_Load() { var m = new ProcedureBuilder("SsaStackReference"); var wRef = m.Frame.EnsureStackArgument(4, PrimitiveType.Word16); var ax = EnsureRegister16(m, "ax"); m.Assign(ax, wRef); m.Return(); RunUnitTest(m, "Analysis/SsaStackReference.txt"); }