public DataFlowAnalysis(Program program, IImportResolver importResolver, DecompilerEventListener eventListener) { this.program = program; this.importResolver = importResolver; this.eventListener = eventListener; this.flow = new ProgramDataFlow(program); }
/// <summary> /// Constructs an SsaTransform, and in the process generates the SsaState for the procedure <paramref>proc</paramref>. /// </summary> /// <param name="proc"></param> /// <param name="gr"></param> public SsaTransform(ProgramDataFlow programFlow, Procedure proc, DominatorGraph<Block> gr) { this.programFlow = programFlow; this.proc = proc; this.SsaState = new SsaState(proc, gr); this.AOrig = CreateA(); Transform(); }
public void Setup() { arch = new X86ArchitectureFlat32(); m = new ProcedureBuilder(arch); program = new Program(); program.Architecture = arch; exit = new Procedure("exit", new Frame(PrimitiveType.Word32)); flow = new ProgramDataFlow(); p = new ProgramBuilder(); }
public void Setup() { exit = new ExternalProcedure("exit", new ProcedureSignature(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(); }
public void Setup() { arch = new IntelArchitecture(ProcessorMode.Protected32); m = new ProcedureBuilder(arch); prog = new Program(); prog.Architecture = arch; exit = new Procedure("exit", new Frame(PrimitiveType.Word32)); flow = new ProgramDataFlow(); p = new ProgramBuilder(); }
public TrashedRegisterFinder( Program prog, IEnumerable <Procedure> procedures, ProgramDataFlow flow, DecompilerEventListener eventListener) { this.program = prog; this.procedures = procedures; this.flow = flow; this.eventListener = eventListener ?? NullDecompilerEventListener.Instance; this.worklist = new WorkList <Block>(); this.visited = new HashSet <Block>(); this.ecomp = new ExpressionValueComparer(); }
public TrashedRegisterFinder2( IProcessorArchitecture arch, ProgramDataFlow flow, Procedure proc, SsaIdentifierCollection ssa, DecompilerEventListener listener) { this.arch = arch; this.progFlow = flow; this.proc = proc; this.ssa = ssa; this.decompilerEventListener = listener; this.flow = new ProcedureFlow2(); }
public void Setup() { program = new Program(); program.Architecture = new IntelArchitecture(ProcessorMode.Protected32); 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>(); }
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(); } }
/// <summary> /// Computes intraprocedural liveness of the program <paramref name="p"/>, /// storing the results in <paramref name="procFlow"/>. /// </summary> /// <param name="p"></param> /// <param name="procFlow"></param> /// <returns></returns> public static RegisterLiveness Compute( Program p, ProgramDataFlow procFlow, DecompilerEventListener eventListener) { var live = new RegisterLiveness(p, procFlow, eventListener); Debug.WriteLineIf(trace.TraceError, "** Computing ByPass ****"); live.CurrentState = new ByPassState(p.Architecture); live.ProcessWorklist(); if (eventListener.IsCanceled()) { return(live); } Debug.WriteLineIf(trace.TraceError, "** Computing MayUse ****"); live.CurrentState = new MayUseState(); if (trace.TraceInfo) { live.Dump(); } live.ProcessWorklist(); if (eventListener.IsCanceled()) { return(live); } //$REVIEW: since we never use the liveinstate, can we get rid of the following // four statements? Debug.WriteLineIf(trace.TraceError, "** Computing LiveIn ****"); live.CurrentState = new LiveInState(); if (trace.TraceInfo) { live.Dump(); } live.ProcessWorklist(); if (eventListener.IsCanceled()) { return(live); } live.CompleteWork(); if (trace.TraceInfo) { live.Dump(); } return(live); }
/// <summary> /// Walks the dominator tree, renaming the different definitions of variables /// (including phi-functions). /// </summary> /// <param name="ssa">SSA identifiers</param> /// <param name="p">procedure to rename</param> public VariableRenamer(SsaTransform ssaXform) { this.programFlow = ssaXform.programFlow; this.ssa = ssaXform.SsaState; this.renameFrameAccess = ssaXform.RenameFrameAccesses; this.addUseInstructions = ssaXform.AddUseInstructions; this.proc = ssaXform.proc; this.rename = new Dictionary <Identifier, Identifier>(); this.stmCur = null; this.existingDefs = proc.EntryBlock.Statements .Select(s => s.Instruction as DefInstruction) .Where(d => d != null) .Select(d => d.Expression) .ToHashSet(); }
public TrashedRegisterFinder( Program program, ProgramDataFlow flow, IEnumerable <SsaTransform> sccGroup, DecompilerEventListener listener) { this.arch = program.Architecture; this.segmentMap = program.SegmentMap; this.flow = flow; this.sccGroup = sccGroup.ToHashSet(); this.callGraph = program.CallGraph; this.listener = listener; this.cmp = new ExpressionValueComparer(); this.worklist = new WorkStack <Block>(); this.ssas = sccGroup.ToDictionary(s => s.SsaState.Procedure, s => s.SsaState); }
public UnusedOutValuesRemover( Program program, IEnumerable <SsaState> ssaStates, ProgramDataFlow dataFlow, IDynamicLinker dynamicLinker, DecompilerEventListener eventListener) { this.dataFlow = dataFlow; this.program = program; this.ssaStates = ssaStates; this.dynamicLinker = dynamicLinker; this.eventListener = eventListener; this.wl = new WorkList <SsaState>(); this.procToSsa = ssaStates .ToDictionary(s => s.Procedure); }
private void ApplyStackPointers( Dictionary <Procedure, int?> savedSps, ProgramDataFlow flow) { foreach (var de in savedSps) { var p = flow[de.Key]; if (de.Value.HasValue && de.Value.Value == 0) { //$TODO: x86 RET-N instructions unbalance the stack // register. p.Trashed.Remove(arch.StackRegister); p.Preserved.Add(arch.StackRegister); } } }
public RegisterLiveness( Program program, ProgramDataFlow progFlow, DecompilerEventListener eventListener) { this.program = program; this.mpprocData = progFlow; this.eventListener = eventListener; this.worklist = new WorkList <BlockFlow>(); this.varLive = new IdentifierLiveness(program.Architecture); this.isLiveHelper = new IsLiveHelper(program.Architecture); AddAllBasicBlocksToWorklist(); if (trace.TraceInfo) { Dump(); } }
public static void Rewrite(Program program, ProgramDataFlow summaries) { GlobalCallRewriter crw = new GlobalCallRewriter(program, summaries); foreach (Procedure proc in program.Procedures.Values) { ProcedureFlow flow = (ProcedureFlow) crw.mpprocflow[proc]; flow.Dump(program.Architecture); crw.AdjustLiveOut(flow); crw.EnsureSignature(proc, flow); crw.AddUseInstructionsForOutArguments(proc); } foreach (Procedure proc in program.Procedures.Values) { crw.RewriteCalls(proc); crw.RewriteReturns(proc); } }
/// <summary> /// Walks the dominator tree, renaming the different definitions of variables /// (including phi-functions). /// </summary> /// <param name="ssa">SSA identifiers</param> /// <param name="newPhiStatements"> /// Phi statements added during current pass of SsaTransform. Used /// to avoid extra use of identifiers in existing phi assignments /// </param> public VariableRenamer(SsaTransform ssaXform, HashSet <Statement> newPhiStatements) { this.programFlow = ssaXform.programFlow; this.ssa = ssaXform.SsaState; this.implicitRegs = ssaXform.implicitRegs; this.renameFrameAccess = ssaXform.RenameFrameAccesses; this.addUseInstructions = ssaXform.AddUseInstructions; this.proc = ssaXform.proc; this.importResolver = ssaXform.importResolver; this.rename = new Dictionary <Identifier, Identifier>(); this.stmCur = null; this.existingDefs = proc.EntryBlock.Statements .Select(s => s.Instruction as DefInstruction) .Where(d => d != null) .Select(d => d.Identifier) .ToHashSet(); this.newPhiStatements = newPhiStatements; }
public override void InitializeBlockFlow(Block block, ProgramDataFlow flow, bool isExitBlock) { BlockFlow bf = flow[block]; if (isExitBlock && block.Procedure.Signature.ParametersValid) { Identifier ret = block.Procedure.Signature.ReturnValue; if (ret != null) { RegisterStorage rs = ret.Storage as RegisterStorage; if (rs != null) { bf.DataOut.UnionWith(arch.GetAliases(rs)); } } foreach (Identifier id in block.Procedure.Signature.Parameters) { OutArgumentStorage os = id.Storage as OutArgumentStorage; if (os == null) { continue; } RegisterStorage rs = os.OriginalIdentifier.Storage as RegisterStorage; if (rs != null) { bf.DataOut.UnionWith(arch.GetAliases(rs)); } } } else if (bf.TerminatesProcess) { bf.DataOut.Clear(); } else { bf.DataOut.Clear(); if (isExitBlock) { //Add all registers except preserved registers bf.DataOut.UnionWith(arch.GetRegisters()); bf.DataOut.ExceptWith(flow[block.Procedure].PreservedRegisters); } } }
public static void Rewrite(Program program, ProgramDataFlow summaries) { GlobalCallRewriter crw = new GlobalCallRewriter(program, summaries); foreach (Procedure proc in program.Procedures.Values) { ProcedureFlow flow = (ProcedureFlow)crw.mpprocflow[proc]; flow.Dump(program.Architecture); crw.AdjustLiveOut(flow); crw.EnsureSignature(proc, flow); crw.AddUseInstructionsForOutArguments(proc); } foreach (Procedure proc in program.Procedures.Values) { crw.RewriteCalls(proc); crw.RewriteReturns(proc); } }
private Dictionary <Procedure, int?> CollectStackPointers(ProgramDataFlow flow, Storage stackRegister) { if (stackRegister == null) { return(new Dictionary <Procedure, int?>()); } return(flow.ProcedureFlows.ToDictionary( de => de.Key, de => { if (de.Value.Trashed.Contains(stackRegister)) { return (int?)null; } if (de.Value.Preserved.Contains(stackRegister)) { return 0; } //$TODO: x86 RET N instructions. return 0; })); }
public override void InitializeBlockFlow(Block block, ProgramDataFlow flow, bool isExitBlock) { BlockFlow bf = flow[block]; if (isExitBlock && block.Procedure.Signature.ParametersValid) { Identifier ret = block.Procedure.Signature.ReturnValue; if (ret != null) { RegisterStorage rs = ret.Storage as RegisterStorage; if (rs != null) { rs.SetAliases(bf.DataOut, true); } } foreach (Identifier id in block.Procedure.Signature.Parameters) { OutArgumentStorage os = id.Storage as OutArgumentStorage; if (os == null) { continue; } RegisterStorage rs = os.OriginalIdentifier.Storage as RegisterStorage; if (rs != null) { rs.SetAliases(bf.DataOut, true); } } } else if (bf.TerminatesProcess) { bf.DataOut.SetAll(false); } else { bf.DataOut.SetAll(isExitBlock); bf.DataOut &= ~flow[block.Procedure].PreservedRegisters; } }
public GlobalCallRewriter(Program program, ProgramDataFlow mpprocflow, DecompilerEventListener eventListener) : base(program) { this.mpprocflow = mpprocflow; }
public DataFlowAnalysis(Program prog, DecompilerEventListener eventListener) { this.program = prog; this.eventListener = eventListener; this.flow = new ProgramDataFlow(prog); }
public override void InitializeBlockFlow(Block block, ProgramDataFlow flow, bool isExitBlock) { flow[block].DataOut.Clear(); }
public TerminationAnalysis(ProgramDataFlow flow, DecompilerEventListener eventListener) { this.flow = flow; this.eventListener = eventListener; }
protected override void RunTest(Program prog, TextWriter writer) { var flow = new ProgramDataFlow(prog); var eventListener = new FakeDecompilerEventListener(); var importResolver = MockRepository.GenerateStub<IImportResolver>(); importResolver.Replay(); var trf = new TrashedRegisterFinder(prog, prog.Procedures.Values, flow, eventListener); trf.Compute(); trf.RewriteBasicBlocks(); Dump(prog.CallGraph); RegisterLiveness.Compute(prog, flow, eventListener); GlobalCallRewriter.Rewrite(prog, flow, eventListener); foreach (Procedure proc in prog.Procedures.Values) { Aliases alias = new Aliases(proc, prog.Architecture); alias.Transform(); var gr = proc.CreateBlockDominatorGraph(); SsaTransform sst = new SsaTransform( flow, proc, importResolver, gr, new HashSet<RegisterStorage>()); ssa = sst.SsaState; ssa.Write(writer); proc.Write(false, true, writer); writer.WriteLine(); } }
protected override void RunTest(Program prog, TextWriter writer) { this.program = prog; flow = new ProgramDataFlow(prog); trf = CreateTrashedRegisterFinder(); trf.Compute(); DumpProcedureSummaries(writer); }
public override void InitializeBlockFlow(Block block, ProgramDataFlow flow, bool isExitBlock) { flow[block].DataOut.SetAll(false); }
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); a.Analyze(test); Assert.IsTrue(flow[test].TerminatesProcess); }
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); a.Analyze(prog); Assert.IsTrue(flow[sub].TerminatesProcess); Assert.IsTrue(flow[caller].TerminatesProcess); }
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); a.Analyze(proc); Assert.IsTrue(flow[proc].TerminatesProcess); }
public TerminationAnalysis(ProgramDataFlow flow) { this.flow = flow; }
public CallRewriter(IPlatform platform, ProgramDataFlow mpprocflow, DecompilerEventListener listener) { this.platform = platform; this.mpprocflow = mpprocflow; this.listener = listener; }
public LocateDefinedVariables(SsaTransform ssaXform, Dictionary<Expression, byte>[] defOrig) { this.programFlow = ssaXform.programFlow; this.proc = ssaXform.proc; this.ssa = ssaXform.SsaState; this.frameVariables = ssaXform.RenameFrameAccesses; this.defVars = defOrig; this.definitions = new List<Identifier>(); this.inDefinitions = new HashSet<Identifier>(); }
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, program.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(); } }
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 { Console.WriteLine(summary); throw; } }
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); a.Analyze(proc); Assert.IsTrue(flow[proc].TerminatesProcess); }
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; program.Procedures.Add(Address.Ptr32(0x10000), proc); program.CallGraph.AddProcedure(proc); flow = new ProgramDataFlow(program); trf = CreateTrashedRegisterFinder(program); trf.Compute(); ProcedureFlow pf = flow[proc]; Assert.AreEqual(" ebp esp", pf.EmitRegisters(program.Architecture, "", pf.PreservedRegisters), "ebp should have been preserved"); }
public void Setup() { this.pf = new ProgramDataFlow(); this.progBuilder = new ProgramBuilder(); }
public static void Rewrite( Program program, ProgramDataFlow summaries, DecompilerEventListener eventListener) { GlobalCallRewriter crw = new GlobalCallRewriter(program, summaries, eventListener); foreach (Procedure proc in program.Procedures.Values) { if (eventListener.IsCanceled()) return; ProcedureFlow flow = crw.mpprocflow[proc]; flow.Dump(program.Architecture); crw.AdjustLiveOut(flow); crw.EnsureSignature(proc, flow); crw.AddUseInstructionsForOutArguments(proc); } foreach (Procedure proc in program.Procedures.Values) { if (eventListener.IsCanceled()) return; crw.RewriteCalls(proc); crw.RewriteReturns(proc); } }
public GlobalCallRewriter(Program prog, ProgramDataFlow mpprocflow) : base(prog) { this.mpprocflow = mpprocflow; }
/// <summary> /// Walks the dominator tree, renaming the different definitions of variables /// (including phi-functions). /// </summary> /// <param name="ssa">SSA identifiers</param> /// <param name="p">procedure to rename</param> public VariableRenamer(SsaTransform ssaXform) { this.programFlow = ssaXform.programFlow; this.ssa = ssaXform.SsaState; this.renameFrameAccess = ssaXform.RenameFrameAccesses; this.addUseInstructions = ssaXform.AddUseInstructions; this.proc = ssaXform.proc; this.rename = new Dictionary<Identifier, Identifier>(); this.stmCur = null; this.existingDefs = proc.EntryBlock.Statements .Select(s => s.Instruction as DefInstruction) .Where(d => d != null) .Select(d => d.Expression) .ToHashSet(); }
public abstract void InitializeBlockFlow(Block blow, ProgramDataFlow flow, bool isExitBlock);
public GlobalCallRewriter(Program program, ProgramDataFlow mpprocflow) : base(program) { this.mpprocflow = mpprocflow; }
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); a.Analyze(proc); Assert.IsFalse(flow[proc].TerminatesProcess); }
public void Setup() { this.pb = new ProgramBuilder(); this.programFlow = new ProgramDataFlow(); this.importReferences = new Dictionary<Address, ImportReference>(); }