public void Setup() { exit = new ExternalProcedure("exit", new FunctionType( null, null, new Identifier("retCode", PrimitiveType.Int32, new StackArgumentStorage(0, PrimitiveType.Int32)))); exit.Characteristics = new ProcedureCharacteristics(); exit.Characteristics.Terminates = true; progMock = new ProgramBuilder(); flow = new ProgramDataFlow(); eventListener = new FakeDecompilerEventListener(); }
private void RunTest(Program prog, TextWriter writer) { flow = new ProgramDataFlow(prog); trf = new TrashedRegisterFinder(prog, prog.Procedures.Values, this.flow, new FakeDecompilerEventListener()); trf.Compute(); trf.RewriteBasicBlocks(); foreach (var proc in prog.Procedures.Values) { flow[proc].EmitRegisters(arch, "// Trashed", flow[proc].TrashedRegisters); proc.Write(false, writer); writer.WriteLine(); } }
public void Setup() { program = new Program(); program.Architecture = new X86ArchitectureFlat32(); program.Platform = new DefaultPlatform(null, program.Architecture); m = new ProcedureBuilder(); proc = m.Procedure; f = proc.Frame; mpprocflow = new ProgramDataFlow(); terminates = new HashSet <Procedure>(); rl = new RegisterLiveness(program, mpprocflow, null); rl.Procedure = proc; rl.IdentifierLiveness.Identifiers = new HashSet <RegisterStorage>(); }
public void CrwSinglePredecessorToExitBlock() { var m = new ProcedureBuilder("CrwSinglePredecessorToExitBlock"); var eax = m.Frame.EnsureRegister(Registers.eax); m.Assign(eax, m.Mem32(eax)); 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: eax_3 = Mem0[eax:word32] Mem0:Mem def: def Mem0 uses: eax_3 = Mem0[eax:word32] eax_3: orig: eax def: eax_3 = Mem0[eax:word32] uses: return eax_3 // CrwSinglePredecessorToExitBlock // Return size: 0 word32 CrwSinglePredecessorToExitBlock(word32 eax) CrwSinglePredecessorToExitBlock_entry: def eax def Mem0 // succ: l1 l1: eax_3 = Mem0[eax:word32] return eax_3 // succ: CrwSinglePredecessorToExitBlock_exit CrwSinglePredecessorToExitBlock_exit: "; #endregion AssertExpected(sExp, sst.SsaState); }
public void ProcedureTerminatesIfBlockTerminates() { var proc = CompileProcedure("proc", delegate(ProcedureBuilder m) { m.Call(exit, 4); m.Return(); }); var prog = progMock.BuildProgram(); flow = new ProgramDataFlow(prog); var a = new TerminationAnalysis(flow, eventListener); a.Analyze(proc); Assert.IsTrue(flow[proc].TerminatesProcess); }
public void TerminatingApplication() { var test = CompileProcedure("test", m => { m.SideEffect(m.Fn(new ProcedureConstant(PrimitiveType.Pointer32, exit))); m.FinishProcedure(); }); var prog = progMock.BuildProgram(); flow = new ProgramDataFlow(prog); var a = new TerminationAnalysis(flow, eventListener); a.Analyze(test); Assert.IsTrue(flow[test].TerminatesProcess); }
private void RunTest() { this.program = builder.BuildProgram(); this.dataFlow = new ProgramDataFlow(program); var sscf = new SccFinder <Procedure>(new ProcedureGraph(program), ProcessScc); foreach (var procedure in program.Procedures.Values) { sscf.Find(procedure); } var sbActual = new StringBuilder(); var sw = new StringWriter(); foreach (var procedure in program.Procedures.Values) { var flow = dataFlow[procedure]; sw.WriteLine("== {0} ====", procedure.Name); sw.Write("Preserved: "); sw.WriteLine(string.Join(",", flow.Preserved.OrderBy(p => p.ToString()))); sw.Write("Trashed: "); sw.WriteLine(string.Join(",", flow.Trashed.OrderBy(p => p.ToString()))); if (flow.Constants.Count > 0) { sw.Write("Constants: "); sw.Write(string.Join( ",", flow.Constants .OrderBy(kv => kv.Key.ToString()) .Select(kv => string.Format( "{0}:{1}", kv.Key, kv.Value)))); } sw.WriteLine(); } var sExp = sbExpected.ToString(); var sActual = sw.ToString(); if (sActual != sExp) { foreach (var proc in program.Procedures.Values) { Debug.Print("------"); proc.Dump(true); } Debug.WriteLine(sActual); Assert.AreEqual(sExp, sActual); } }
protected override void RunTest(Program prog, TextWriter writer) { var progFlow = new ProgramDataFlow(); foreach (Procedure proc in prog.Procedures.Values) { var gr = proc.CreateBlockDominatorGraph(); Aliases alias = new Aliases(proc, prog.Architecture); alias.Transform(); SsaTransform sst = new SsaTransform(progFlow, proc, gr); SsaState ssa = sst.SsaState; DumpProc(proc, ssa, writer); ValueNumbering vn = new ValueNumbering(ssa.Identifiers); vn.Write(writer); writer.WriteLine(); } }
public void ProcedureDoesntTerminatesIfOneBranchDoesnt() { var proc = CompileProcedure("proc", delegate(ProcedureBuilder m) { m.BranchIf(m.Eq(m.Local32("foo"), m.Word32(0)), "bye"); m.Call(exit, 4); m.Label("bye"); m.Return(); }); var prog = progMock.BuildProgram(); flow = new ProgramDataFlow(prog); var a = new TerminationAnalysis(flow, eventListener); a.Analyze(proc); Assert.IsFalse(flow[proc].TerminatesProcess); }
private void RunTest(ProgramBuilder p, string sExp) { prog = p.BuildProgram(arch); flow = new ProgramDataFlow(prog); trf = CreateTrashedRegisterFinder(); trf.Compute(); var summary = DumpProcedureSummaries().Trim(); if (sExp == summary) { return; } Console.WriteLine(summary); Assert.AreEqual(sExp, summary); }
protected override void RunTest(Program program, TextWriter writer) { var progFlow = new ProgramDataFlow(); foreach (Procedure proc in program.Procedures.Values) { var gr = proc.CreateBlockDominatorGraph(); Aliases alias = new Aliases(proc); alias.Transform(); SsaTransform sst = new SsaTransform(progFlow, proc, null, gr, new HashSet <RegisterStorage>()); SsaState ssa = sst.SsaState; DumpProc(proc, ssa, writer); ValueNumbering vn = new ValueNumbering(ssa.Identifiers, segmentMap, null); vn.Write(writer); writer.WriteLine(); } }
private void BuildTest(Action <ProcedureBuilder> builder) { var pb = new ProcedureBuilder(); builder(pb); var dflow = new ProgramDataFlow(); var program = new Program() { Architecture = pb.Architecture, }; var sst = new SsaTransform( program, pb.Procedure, new HashSet <Procedure>(), null, dflow); this.ssa = sst.Transform(); }
private void AssertSmallConst(string sExp, int shift, uint mult) { var m = new ProcedureBuilder(); var c = Constant.Int32((int)mult); var r1 = m.Reg32("r1", 1); var r2 = m.Reg32("r2", 2); var r2_r1 = m.Frame.EnsureSequence(PrimitiveType.Word64, r2.Storage, r1.Storage); var ass = m.Assign(r2_r1, m.SMul(r1, c)); m.Alias(r2, m.Slice(PrimitiveType.Word32, r2_r1, 32)); if (shift != 0) { m.Assign(r2, m.Sar(r2, shift)); } m.MStore(m.Word32(0x0402000), r2); // Force use of r2 m.Return(); var proc = m.Procedure; var flow = new ProgramDataFlow(); var program = new Program() { Architecture = m.Architecture, }; var sst = new SsaTransform( program, proc, new HashSet <Procedure>(), null, flow); sst.Transform(); proc.Dump(true); var ctx = new SsaEvaluationContext(m.Architecture, sst.SsaState.Identifiers, null); var rule = new ConstDivisionImplementedByMultiplication(sst.SsaState); ctx.Statement = proc.EntryBlock.Succ[0].Statements[0]; Assert.IsTrue(rule.Match(ctx.Statement.Instruction)); var instr = rule.TransformInstruction(); Assert.AreEqual(sExp, instr.Src.ToString()); }
public void ProcedureTerminatesIfAllBranchesDo() { var proc = CompileProcedure("proc", m => { m.BranchIf(m.Eq(m.Local32("foo"), m.Word32(0)), "whee"); m.Call(exit, 4); m.FinishProcedure(); m.Label("whee"); m.Call(exit, 4); m.FinishProcedure(); }); var prog = progMock.BuildProgram(); flow = new ProgramDataFlow(prog); var a = new TerminationAnalysis(flow, eventListener); a.Analyze(proc); Assert.IsTrue(flow[proc].TerminatesProcess); }
private void BuildTest(Action <ProcedureBuilder> bld) { var m = new ProcedureBuilder(); bld(m); var proc = m.Procedure; var flow = new ProgramDataFlow(); var program = new Program() { Architecture = m.Architecture, }; var sst = new SsaTransform( program, proc, new HashSet <Procedure>(), null, flow); this.ssa = sst.Transform(); this.ctx = new SsaEvaluationContext(m.Architecture, ssa.Identifiers, null); }
public void TrfPreserveEbp() { Identifier esp = m.Frame.EnsureRegister(Registers.esp); Identifier ebp = m.Frame.EnsureRegister(Registers.ebp); m.Store(esp, ebp); m.Assign(ebp, m.LoadDw(m.Int32(0x12345678))); m.Assign(ebp, m.LoadDw(esp)); m.Return(); Procedure proc = m.Procedure; prog.Procedures.Add(Address.Ptr32(0x10000), proc); prog.CallGraph.AddProcedure(proc); flow = new ProgramDataFlow(prog); trf = CreateTrashedRegisterFinder(prog); trf.Compute(); ProcedureFlow pf = flow[proc]; Assert.AreEqual(" esp ebp", pf.EmitRegisters(prog.Architecture, "", pf.PreservedRegisters), "ebp should have been preserved"); }
private void AssertProgramFlow(string sExp, Program program, ProgramDataFlow flow) { var sw = new StringWriter(); var sep = ""; foreach (var proc in program.Procedures.Values) { sw.Write(sep); var pflow = flow.ProcedureFlows[proc]; sw.WriteLine("// Trashed {0}", string.Join(", ", pflow.Trashed.OrderBy(s => s.ToString()))); sw.WriteLine("// Preserved {0}", string.Join(", ", pflow.Preserved.OrderBy(s => s.ToString()))); sw.WriteLine("// Used {0}", string.Join(", ", pflow.BitsUsed.Select(s => string.Format("({0}:{1})", s.Key, s.Value)).OrderBy(s => s))); proc.Write(false, sw); sep = "===" + Environment.NewLine; } var sActual = sw.ToString(); if (sExp != sActual) { Debug.WriteLine(sActual); } Assert.AreEqual(sExp, sw.ToString()); }
public void TerminatingSubProcedure() { var sub = CompileProcedure("sub", m => { m.Call(exit, 4); m.FinishProcedure(); }); Procedure caller = CompileProcedure("caller", m => { m.Call(sub, 4); m.Return(); }); var prog = progMock.BuildProgram(); flow = new ProgramDataFlow(prog); var a = new TerminationAnalysis(flow, eventListener); a.Analyze(prog); Assert.IsTrue(flow[sub].TerminatesProcess); Assert.IsTrue(flow[caller].TerminatesProcess); }
private void RunUnitTest(ProcedureBuilder m, string outfile) { var flow = new ProgramDataFlow(); var dynamicLinker = new Mock <IDynamicLinker>(); var proc = m.Procedure; var platform = new FakePlatform(null, m.Architecture) { Test_CreateTrashedRegisters = () => new HashSet <RegisterStorage>() { (RegisterStorage)r1.Storage, (RegisterStorage)r2.Storage, } }; var program = new Program() { Architecture = m.Architecture, Platform = platform, }; var sst = new SsaTransform( program, proc, new HashSet <Procedure>(), dynamicLinker.Object, flow); sst.Transform(); ssa = sst.SsaState; using (var fut = new FileUnitTester(outfile)) { ssa.Write(fut.TextWriter); proc.Write(false, fut.TextWriter); fut.AssertFilesEqual(); ssa.Validate(s => Assert.Fail(s)); } }
protected override void RunTest(Program program, TextWriter writer) { var flow = new ProgramDataFlow(); var dynamicLinker = new Mock <IDynamicLinker>(); foreach (Procedure proc in program.Procedures.Values) { var sst = new SsaTransform( program, proc, new HashSet <Procedure>(), dynamicLinker.Object, flow); sst.Transform(); sst.AddUsesToExitBlock(); sst.RemoveDeadSsaIdentifiers(); Debug.Print("SsaTest: {0}", new StackFrame(3).GetMethod().Name); ssa = sst.SsaState; ssa.Write(writer); proc.Write(false, true, writer); writer.WriteLine(); ssa.Validate(s => Assert.Fail(s)); } }
private void RunTest(ProgramBuilder p, string sExp) { program = p.BuildProgram(arch); flow = new ProgramDataFlow(program); trf = CreateTrashedRegisterFinder(); trf.Compute(); var summary = DumpProcedureSummaries().Trim(); if (sExp == summary) { return; } try { Assert.AreEqual(sExp, summary); } catch { Debug.Print("{0}", summary); throw; } }
public void RunTest(IEnumerable <Procedure> procs) { importResolver = MockRepository.GenerateStub <IImportResolver>(); importResolver.Replay(); var flow = new ProgramDataFlow(program); var scc = new Dictionary <Procedure, SsaState>(); foreach (var proc in procs) { Aliases alias = new Aliases(proc, program.Architecture, flow); alias.Transform(); // Transform the procedure to SSA state. When encountering 'call' instructions, // they can be to functions already visited. If so, they have a "ProcedureFlow" // associated with them. If they have not been visited, or are computed destinations // (e.g. vtables) they will have no "ProcedureFlow" associated with them yet, in // which case the the SSA treats the call as a "hell node". var doms = proc.CreateBlockDominatorGraph(); var sst = new SsaTransform( flow, proc, importResolver, doms, program.Platform.CreateImplicitArgumentRegisters()); sst.AddUseInstructions = true; sst.Transform(); var ssa = sst.SsaState; scc.Add(proc, ssa); } this.dataFlow = new DataFlow2(); var regp = new RegisterPreservation(scc, dataFlow); regp.Compute(); }
private TrashedRegisterFinder CreateTrashedRegisterFinder(bool createFlow = false) { this.flow = createFlow ? new ProgramDataFlow(program) : this.flow; return(new TrashedRegisterFinder(program, program.Procedures.Values, this.flow, new FakeDecompilerEventListener())); }
public void Setup() { this.pf = new ProgramDataFlow(); this.progBuilder = new ProgramBuilder(); this.segmentMap = new SegmentMap(Address.Ptr32(0)); }
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 Setup() { this.pf = new ProgramDataFlow(); this.progBuilder = new ProgramBuilder(); }
public void Setup() { m = new SsaProcedureBuilder(); this.programDataFlow = new ProgramDataFlow(); this.dynamicLinker = new Mock <IDynamicLinker>(); }
public void Setup() { this.pb = new ProgramBuilder(); this.programFlow = new ProgramDataFlow(); this.importReferences = new Dictionary <Address, ImportReference>(); }
public void Setup() { m = new SsaProcedureBuilder(); this.programDataFlow = new ProgramDataFlow(); this.importResolver = new Mock <IImportResolver>(); }