/// <summary> /// Processes the data flow of a block by beginning with /// the dataOut after the last instruction, simluates all instructions /// until the beginning of the block is reached, and percolates any /// *changes* to predecessor blocks to the worklist for futher processing. /// </summary> /// <param name="item">The block dataflow item we are about to process</param> public void ProcessBlock(BlockFlow item) { bool t = trace.TraceInfo; if (t) { Debug.Write(item.Block.Procedure.Name + ", "); DumpBlock(item.Block); } varLive.Identifiers = new HashSet <RegisterStorage>(item.DataOut); varLive.Grf = item.grfOut; varLive.LiveStorages = new Dictionary <Storage, int>(item.StackVarsOut); Debug.WriteLineIf(t, string.Format(" out: {0}", DumpRegisters(varLive.Identifiers))); Procedure = item.Block.Procedure; // Used by statements because we need to look up registers using identifiers and the procedure frame. StatementList stms = item.Block.Statements; for (int i = stms.Count - 1; i >= 0; --i) { stmCur = stms[i]; Debug.WriteLineIf(t, stms[i].Instruction); stmCur.Instruction.Accept(this); Debug.WriteLineIf(t, string.Format("\tin: {0}", DumpRegisters(varLive.Identifiers))); } if (item.Block == item.Block.Procedure.EntryBlock) { PropagateToProcedureSummary(varLive, item.Block.Procedure); } else { PropagateToPredecessorBlocks(item); } }
/// <summary> /// Propagates liveness information to predecessor blocks, but only /// if there are changes to their dataOut fields. /// </summary> /// <param name="item"></param> private void PropagateToPredecessorBlocks(BlockFlow item) { foreach (Block p in item.Block.Pred) { MergeBlockInfo(p); } }
public void EnsureEvaluationContext(BlockFlow bf) { this.ctx = bf.SymbolicIn.Clone(); var tes = new TrashedExpressionSimplifier(this, ctx); this.se = new SymbolicEvaluator(tes, ctx); }
/// <summary> /// Merges the liveness information accumulated in <paramref name="varLive"/> into <paramref name="blockFlow"/> /// </summary> /// <param name="varLive">Current liveness state</param> /// <param name="blockFlow">liveness information associated with a block</param> /// <returns>Return true if merging the livness information changed the information in the block flow.</returns> public virtual bool MergeBlockInfo(IdentifierLiveness varLive, BlockFlow blockFlow) { bool ret = false; int oldCount = blockFlow.DataOut.Count; blockFlow.DataOut.UnionWith(varLive.Identifiers); if (blockFlow.DataOut.Count != oldCount) { ret = true; } if ((varLive.Grf & (~blockFlow.grfOut)) != 0) { blockFlow.grfOut |= varLive.Grf; ret = true; } IDictionary <Storage, int> dict = blockFlow.StackVarsOut; foreach (KeyValuePair <Storage, int> de in varLive.LiveStorages) { if (!dict.ContainsKey(de.Key)) { dict.Add(de.Key, de.Value); ret = true; } } return(ret); }
public void DumpProgram() { foreach (Procedure proc in program.Procedures.Values) { StringWriter output = new StringWriter(); ProcedureFlow pf = this.flow[proc]; TextFormatter f = new TextFormatter(output); if (pf.Signature != null) { pf.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, f); } else { proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, f); } output.WriteLine(); pf.Emit(proc.Architecture, output); output.WriteLine("// {0}", proc.Name); proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, f); output.WriteLine(); foreach (Block block in proc.ControlGraph.Blocks) { if (block != null) { BlockFlow bf = this.flow[block]; bf.Emit(proc.Architecture, output); output.WriteLine(); block.Write(output); } } Debug.WriteLine(output.ToString()); } }
public void MergeBlockInfo(Block block) { BlockFlow blockFlow = mpprocData[block]; if (state.MergeBlockInfo(varLive, blockFlow)) { worklist.Add(blockFlow); } }
public void PropagateToSuccessorBlock(Block s) { BlockFlow succFlow = flow[s]; bool changed = MergeDataFlow(succFlow); if (changed) { worklist.Add(s); } }
private BlockFlow CreateBlockFlow(Block block, Frame frame) { var bflow = new BlockFlow( block, prog.Architecture.CreateRegisterBitset(), new SymbolicEvaluationContext( prog.Architecture, frame)); flow[block] = bflow; return bflow; }
public void StartProcessingBlock(Block block) { bf = flow[block]; EnsureEvaluationContext(bf); if (block.Procedure.EntryBlock == block) { var sp = block.Procedure.Frame.EnsureRegister(program.Architecture.StackRegister); bf.SymbolicIn.RegisterState[sp.Storage] = block.Procedure.Frame.FramePointer; } ctx.TrashedFlags = bf.grfTrashedIn; }
private BlockFlow CreateBlockFlow(Block block, Frame frame) { var bflow = new BlockFlow( block, new HashSet<RegisterStorage>(), new SymbolicEvaluationContext( program.Architecture, frame)); flow[block] = bflow; return bflow; }
/// <summary> /// Make summary information available in LiveIn and LiveOut for each procedure. /// </summary> private void CompleteWork() { foreach (Procedure proc in program.Procedures.Values) { ProcedureFlow pi = mpprocData[proc]; BlockFlow bi = mpprocData[proc.ExitBlock]; pi.LiveOut = bi.DataOut; pi.grfLiveOut = bi.grfOut; // Remove unneeded data. Done for performance (and to give GC something to do). pi.ByPass.Clear(); } }
public void StartBlock(Block block) { this.block = block; if (this.pdf != null) { BlockFlow bf = pdf[block]; var marker = new AliasDeadVariableMarker(bf.DataOut, bf.grfOut); deadIn = marker.Compute(arch, proc.Frame); } else { // If no global analysis available, be pessimistic and assume // all variables are live-out of every block. deadIn = new HashSet <Identifier>(); } }
public override bool MergeBlockInfo(IdentifierLiveness varLive, BlockFlow blockFlow) { bool ret = false; if (!(~varLive.BitSet & blockFlow.DataOut).IsEmpty) { blockFlow.DataOut |= varLive.BitSet; ret = true; } if ((~varLive.Grf & blockFlow.grfOut) != 0) { blockFlow.grfOut |= varLive.Grf; ret = true; } return(ret); }
public ProgramDataFlow(Program program) : this() { foreach (Procedure proc in program.Procedures.Values) { procFlow[proc] = new ProcedureFlow(proc, program.Architecture); foreach (Block block in proc.ControlGraph.Blocks) { blockFlow[block] = new BlockFlow( block, new HashSet<RegisterStorage>(), new SymbolicEvaluationContext( program.Architecture, proc.Frame)); } } }
public ProgramDataFlow(Program prog) : this() { foreach (Procedure proc in prog.Procedures.Values) { procFlow[proc] = new ProcedureFlow(proc, prog.Architecture); foreach (Block block in proc.ControlGraph.Blocks) { blockFlow[block] = new BlockFlow( block, prog.Architecture.CreateRegisterBitset(), new SymbolicEvaluationContext( prog.Architecture, proc.Frame)); } } }
public ProgramDataFlow(Program program) : this() { foreach (Procedure proc in program.Procedures.Values) { procFlow[proc] = new ProcedureFlow(proc, proc.Architecture); foreach (Block block in proc.ControlGraph.Blocks) { blockFlow[block] = new BlockFlow( block, new HashSet <RegisterStorage>(), new SymbolicEvaluationContext( proc.Architecture, proc.Frame)); } } }
public override bool MergeBlockInfo(IdentifierLiveness varLive, BlockFlow blockFlow) { bool changed = false; int oldCount = blockFlow.DataOut.Count; blockFlow.DataOut.UnionWith(varLive.Identifiers); if (blockFlow.DataOut.Count != oldCount) { changed = true; } if ((~varLive.Grf & blockFlow.grfOut) != 0) { blockFlow.grfOut |= varLive.Grf; changed = true; } return(changed); }
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 bool MergeDataFlow(BlockFlow succFlow) { var ctxSucc = succFlow.SymbolicIn; bool changed = false; foreach (var de in ctx.RegisterState) { Expression oldValue; if (!ctxSucc.RegisterState.TryGetValue(de.Key, out oldValue)) { ctxSucc.RegisterState[de.Key] = de.Value; changed = true; } else if (oldValue != Constant.Invalid && !ecomp.Equals(oldValue, de.Value)) { ctxSucc.RegisterState[de.Key] = Constant.Invalid; changed = true; } } foreach (var de in ctx.StackState) { Expression oldValue; if (!ctxSucc.StackState.TryGetValue(de.Key, out oldValue)) { ctxSucc.StackState[de.Key] = de.Value; changed = true; } else if (!ecomp.Equals(oldValue, de.Value) && oldValue != Constant.Invalid) { ctxSucc.StackState[de.Key] = Constant.Invalid; changed = true; } } uint grfNew = succFlow.grfTrashedIn | ctx.TrashedFlags; if (grfNew != succFlow.grfTrashedIn) { succFlow.grfTrashedIn = grfNew; changed = true; } return(changed); }
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; } }
private void Given_Contexts() { frame = new Frame(PrimitiveType.Pointer32); ctx = new SymbolicEvaluationContext(arch, frame); blockflow = new BlockFlow(null, new HashSet<RegisterStorage>(), ctx); trf.EnsureEvaluationContext(blockflow); }
private void Given_Contexts() { frame = new Frame(PrimitiveType.Pointer32); ctx = new SymbolicEvaluationContext(arch, frame); blockflow = new BlockFlow(null, arch.CreateRegisterBitset(), ctx); trf.EnsureEvaluationContext(blockflow); }
public void TrfPropagateToSuccessorBlocks() { Procedure proc = new Procedure("test", program.Architecture.CreateFrame()); var frame = proc.Frame; Identifier ecx = m.Register(1); Identifier edx = m.Register(2); Identifier ebx = m.Register(3); Block b = proc.AddBlock("b"); Block t = proc.AddBlock("t"); Block e = proc.AddBlock("e"); proc.ControlGraph.AddEdge(b, e); proc.ControlGraph.AddEdge(b, t); flow[t] = new BlockFlow(t, null, new SymbolicEvaluationContext(program.Architecture, frame)); flow[e] = new BlockFlow(e, null, new SymbolicEvaluationContext(program.Architecture, frame)); trf = CreateTrashedRegisterFinder(program); CreateBlockFlow(b, frame); trf.StartProcessingBlock(b); trf.RegisterSymbolicValues[(RegisterStorage) ecx.Storage] = Constant.Invalid; trf.RegisterSymbolicValues[(RegisterStorage) edx.Storage] = ebx; flow[e].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage] = edx; flow[e].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage] = ebx; flow[t].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage] = Constant.Invalid; flow[t].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage] = edx; trf.PropagateToSuccessorBlock(e); trf.PropagateToSuccessorBlock(t); Assert.AreEqual(2, proc.ControlGraph.Successors(b).Count); Assert.AreEqual("<invalid>", flow[e].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage].ToString(), "trash & r2 => trash"); Assert.AreEqual("ebx", flow[e].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage].ToString(), "ebx & ebx => ebx"); Assert.AreEqual("<invalid>", flow[e].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage].ToString(), "trash & r2 => trash"); Assert.AreEqual("ebx", flow[e].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage].ToString(), "ebx & ebx => ebx"); Assert.AreEqual("<invalid>", flow[t].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage].ToString(), "trash & trash => trash"); Assert.AreEqual("<invalid>", flow[t].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage].ToString(), "r3 & r2 => trash"); }