public void SrtSimpleLoop() { Procedure proc = BuildSimpleLoop(); var dom = proc.CreateBlockDominatorGraph(); SsaTransform ssa = new SsaTransform(new ProgramDataFlow(), proc, dom); proc.Write(false, Console.Out); LinearInductionVariableFinder lif = new LinearInductionVariableFinder(proc, ssa.SsaState.Identifiers, dom); lif.Find(); Assert.AreEqual(1, lif.InductionVariables.Count, "Should have found one induction variable"); Assert.AreEqual(1, lif.Contexts.Count); LinearInductionVariableContext ctx = lif.Contexts[lif.InductionVariables[0]]; StrengthReduction str = new StrengthReduction(ssa.SsaState,lif.InductionVariables[0], ctx); str.ClassifyUses(); Assert.AreEqual(1, str.IncrementedUses.Count); str.ModifyUses(); Assert.AreEqual("(0x00003000 0x00000004 0x00007000)", lif.InductionVariables[0].ToString()); using (FileUnitTester fut = new FileUnitTester("Analysis/SrtSimpleLoop.txt")) { proc.Write(false, fut.TextWriter); fut.AssertFilesEqual(); } }
/// <summary> /// Processes procedures individually, building complex expression trees out /// of the simple, close-to-the-machine code generated by the disassembly. /// </summary> /// <param name="rl"></param> public void BuildExpressionTrees() { int i = 0; foreach (Procedure proc in program.Procedures.Values) { eventListener.ShowProgress("Building complex expressions.", i, program.Procedures.Values.Count); ++i; try { var larw = new LongAddRewriter(proc, program.Architecture); larw.Transform(); Aliases alias = new Aliases(proc, program.Architecture, flow); alias.Transform(); var doms = new DominatorGraph<Block>(proc.ControlGraph, proc.EntryBlock); var sst = new SsaTransform(flow, proc, doms); var ssa = sst.SsaState; var cce = new ConditionCodeEliminator(ssa.Identifiers, program.Platform); cce.Transform(); DeadCode.Eliminate(proc, ssa); var vp = new ValuePropagator(ssa.Identifiers, proc); vp.Transform(); DeadCode.Eliminate(proc, ssa); // Build expressions. A definition with a single use can be subsumed // into the using expression. var coa = new Coalescer(proc, ssa); coa.Transform(); DeadCode.Eliminate(proc, ssa); var liv = new LinearInductionVariableFinder( proc, ssa.Identifiers, new BlockDominatorGraph(proc.ControlGraph, proc.EntryBlock)); liv.Find(); foreach (KeyValuePair<LinearInductionVariable, LinearInductionVariableContext> de in liv.Contexts) { var str = new StrengthReduction(ssa, de.Key, de.Value); str.ClassifyUses(); str.ModifyUses(); } var opt = new OutParameterTransformer(proc, ssa.Identifiers); opt.Transform(); DeadCode.Eliminate(proc, ssa); // Definitions with multiple uses and variables joined by PHI functions become webs. var web = new WebBuilder(proc, ssa.Identifiers, program.InductionVariables); web.Transform(); ssa.ConvertBack(false); } catch (Exception ex) { eventListener.Error(new NullCodeLocation(proc.Name), ex, "An error occurred during data flow analysis."); } } }
private void UntangleProcedureScc(IList<Procedure> procs) { if (procs.Count == 1) { var proc = procs[0]; 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, doms); var ssa = sst.SsaState; // Propagate condition codes and registers. At the end, the hope is that // all statements like (x86) mem[esp_42+4] will have been converted to // mem[fp - 30]. We also hope that procedure constants kept in registers // are propagated to the corresponding call sites. var cce = new ConditionCodeEliminator(ssa.Identifiers, program.Platform); cce.Transform(); var vp = new ValuePropagator(ssa.Identifiers, proc); vp.Transform(); // Now compute SSA for the stack-based variables as well. That is: // mem[fp - 30] becomes wLoc30, while // mem[fp + 30] becomes wArg30. // This allows us to compute the dataflow of this procedure. sst.RenameFrameAccesses = true; sst.AddUseInstructions = true; sst.Transform(); // Propagate those newly discovered identifiers. vp.Transform(); // At this point, the computation of _actual_ ProcedureFlow should be possible. var tid = new TrashedRegisterFinder2(program.Architecture, flow, proc, ssa.Identifiers, this.eventListener); tid.Compute(); DeadCode.Eliminate(proc, ssa); // Build expressions. A definition with a single use can be subsumed // into the using expression. var coa = new Coalescer(proc, ssa); coa.Transform(); DeadCode.Eliminate(proc, ssa); var liv = new LinearInductionVariableFinder( proc, ssa.Identifiers, new BlockDominatorGraph(proc.ControlGraph, proc.EntryBlock)); liv.Find(); foreach (var de in liv.Contexts) { var str = new StrengthReduction(ssa, de.Key, de.Value); str.ClassifyUses(); str.ModifyUses(); } proc.Dump(true, false); //var opt = new OutParameterTransformer(proc, ssa.Identifiers); //opt.Transform(); DeadCode.Eliminate(proc, ssa); // Definitions with multiple uses and variables joined by PHI functions become webs. var web = new WebBuilder(proc, ssa.Identifiers, program.InductionVariables); web.Transform(); ssa.ConvertBack(false); } else { } }