/// <summary> /// Given block flow, computes its live branches given the cells to /// which values evaluate. /// </summary> /// <param name="flow"> /// The block flow to consider. /// </param> /// <param name="cells"> /// The lattice cells currently assigned to values in the graph. /// </param> /// <param name="graph"> /// The control-flow graph that defines <paramref name="flow"/>. /// </param> /// <returns>A sequence of live branches.</returns> public virtual IEnumerable <Branch> GetLiveBranches( BlockFlow flow, IReadOnlyDictionary <ValueTag, TCell> cells, FlowGraph graph) { return(flow.Branches); }
private void Given_Contexts() { frame = new Frame(PrimitiveType.Pointer32); ctx = new SymbolicEvaluationContext(arch, frame); blockflow = new BlockFlow(null, arch.CreateRegisterBitset(), ctx); trf.EnsureEvaluationContext(blockflow); }
private void Given_Contexts() { frame = new Frame(PrimitiveType.Ptr32); ctx = new SymbolicEvaluationContext(arch, frame); blockflow = new BlockFlow(null, new HashSet <RegisterStorage>(), ctx); trf.EnsureEvaluationContext(blockflow); }
private LNode Encode( BlockFlow flow, UniqueNameMap <UniqueTag> blockNameMap, UniqueNameMap <UniqueTag> valueNameMap) { if (flow is UnreachableFlow) { return(Factory.Id(unreachableFlowSymbol)); } else if (flow is JumpFlow) { return(Factory.Call( CodeSymbols.Goto, Encode(((JumpFlow)flow).Branch, blockNameMap, valueNameMap))); } else if (flow is ReturnFlow) { return(Factory.Call( CodeSymbols.Return, Encode(((ReturnFlow)flow).ReturnValue, valueNameMap))); } else if (flow is TryFlow) { var tryFlow = (TryFlow)flow; return(Factory.Call( CodeSymbols.Try, Encode(tryFlow.Instruction, valueNameMap), Encode(tryFlow.SuccessBranch, blockNameMap, valueNameMap), Encode(tryFlow.ExceptionBranch, blockNameMap, valueNameMap))); } else if (flow is SwitchFlow) { var switchFlow = (SwitchFlow)flow; var caseNodes = new List <LNode>(); foreach (var switchCase in switchFlow.Cases) { caseNodes.Add( Factory.Call( CodeSymbols.Case, Factory.Call(CodeSymbols.AltList, switchCase.Values.Select(Encode)), Encode(switchCase.Branch, blockNameMap, valueNameMap))); } return(Factory.Call( CodeSymbols.Switch, Encode(switchFlow.SwitchValue, valueNameMap), Encode(switchFlow.DefaultBranch, blockNameMap, valueNameMap), Factory.Call(CodeSymbols.Braces, caseNodes))); } else { throw new NotSupportedException( "Cannot encode unknown block flow '" + flow + "'."); } }
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); }
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); }
private void EmitProgram(Program program, DataFlowAnalysis dfa, TextWriter output) { if (output == null) { return; } foreach (Procedure proc in program.Procedures.Values) { if (program.NeedsSsaTransform && dfa != null) { ProcedureFlow flow = dfa.ProgramDataFlow[proc]; TextFormatter f = new TextFormatter(output); if (flow.Signature != null) { flow.Signature.Emit(proc.Name, FunctionType.EmitFlags.LowLevelInfo, f); } else if (proc.Signature != null) { proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.LowLevelInfo, f); } else { output.Write("Warning: no signature found for {0}", proc.Name); } output.WriteLine(); flow.Emit(program.Architecture, output); foreach (Block block in new DfsIterator <Block>(proc.ControlGraph).PostOrder().Reverse()) { if (block == null) { continue; } block.Write(output); BlockFlow bf = dfa.ProgramDataFlow[block]; if (bf != null) { bf.Emit(program.Architecture, output); output.WriteLine(); } } } else { proc.Write(false, output); } output.WriteLine(); output.WriteLine(); } output.Flush(); }
public override IEnumerable <Branch> GetLiveBranches( BlockFlow flow, IReadOnlyDictionary <ValueTag, LatticeCell> cells, FlowGraph graph) { if (flow is SwitchFlow) { var switchFlow = (SwitchFlow)flow; var condition = Evaluate(switchFlow.SwitchValue, cells, graph); if (condition.Kind == LatticeCellKind.Top) { // Do nothing for now. return(EmptyArray <Branch> .Value); } else if (condition.Kind == LatticeCellKind.Constant) { // If a switch flow has a constant condition (for now), // then pick a single branch. var valuesToBranches = switchFlow.ValueToBranchMap; return(new[] { valuesToBranches.ContainsKey(condition.Value) ? valuesToBranches[condition.Value] : switchFlow.DefaultBranch }); } else if (condition.Kind == LatticeCellKind.NonNull) { // If a switch flow has a non-null condition, then we // work on all branches except for the null branch, if // it exists. return(switchFlow.ValueToBranchMap .Where(pair => pair.Key != NullConstant.Instance) .Select(pair => pair.Value) .Concat(new[] { switchFlow.DefaultBranch }) .ToArray()); } else { // If a switch flow has a bottom condition, then everything // is possible. return(flow.Branches); } } else { return(flow.Branches); } }
public void Rl_ProcedureWithTrashedAndPreservedRegisters() { Procedure proc = new Procedure("test", prog.Architecture.CreateFrame()); ProcedureFlow pf = new ProcedureFlow(proc, prog.Architecture); mpprocflow[proc] = pf; pf.TrashedRegisters[Registers.eax.Number] = true; pf.TrashedRegisters[Registers.ebx.Number] = true; pf.PreservedRegisters[Registers.ebp.Number] = true; pf.PreservedRegisters[Registers.bp.Number] = true; RegisterLiveness.State st = new RegisterLiveness.ByPassState(); BlockFlow bf = CreateBlockFlow(proc.ExitBlock, proc.Frame); mpprocflow[proc.ExitBlock] = bf; st.InitializeBlockFlow(proc.ExitBlock, mpprocflow, true); Assert.IsFalse(bf.DataOut[Registers.ebp.Number], "preserved registers cannot be live out"); Assert.IsFalse(bf.DataOut[Registers.bp.Number], "preserved registers cannot be live out"); Assert.IsTrue(bf.DataOut[Registers.eax.Number], "trashed registers may be live out"); Assert.IsTrue(bf.DataOut[Registers.esi.Number], "Unmentioned registers may be live out"); }
/// <inheritdoc/> public override BlockFlow Emit(FlowGraphBuilder graph, ValueTag value) { int caseCounter = 0; BasicBlockBuilder currentBlock = null; var defaultJump = new JumpFlow(flow.DefaultBranch); BlockFlow result = defaultJump; foreach (var switchCase in flow.Cases) { foreach (var pattern in switchCase.Values) { caseCounter++; var nextBlock = graph.AddBasicBlock("case" + caseCounter); var blockFlow = new SwitchFlow( Instruction.CreateCopy(graph.GetValueType(value), value), new[] { new SwitchCase(ImmutableHashSet.Create(pattern), switchCase.Branch) }, new Branch(nextBlock)); if (currentBlock == null) { result = blockFlow; } else { currentBlock.Flow = blockFlow; } currentBlock = nextBlock; } } if (currentBlock != null) { currentBlock.Flow = defaultJump; } return(result); }
public void TrfPropagateToSuccessorBlocks() { Procedure proc = new Procedure("test", prog.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(prog.Architecture, frame)); flow[e] = new BlockFlow(e, null, new SymbolicEvaluationContext(prog.Architecture, frame)); trf = CreateTrashedRegisterFinder(prog); 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"); }
public void Rl_PredefinedSignature() { Procedure callee = new Procedure(program.Architecture, "callee", null); Identifier edx = new Identifier("edx", PrimitiveType.Word32, Registers.edx); callee.Signature = new FunctionType( new Identifier("eax", PrimitiveType.Word32, Registers.eax), new Identifier[] { new Identifier("ecx", PrimitiveType.Word32, Registers.ecx), new Identifier("arg04", PrimitiveType.Word16, new StackArgumentStorage(4, PrimitiveType.Word16)), new Identifier("edxOut", PrimitiveType.Word32, new OutArgumentStorage(edx)) }); RegisterLiveness.State st = new RegisterLiveness.ByPassState(program.Architecture); BlockFlow bf = CreateBlockFlow(callee.ExitBlock, null); mpprocflow[callee.ExitBlock] = bf; st.InitializeBlockFlow(callee.ExitBlock, mpprocflow, true); Assert.IsTrue(bf.DataOut.Contains(Registers.eax), "eax is a return register"); Assert.IsTrue(bf.DataOut.Contains(Registers.edx), "edx is an out register"); Assert.IsTrue(bf.DataOut.Contains(Registers.ax), "ax is aliased by eax"); Assert.IsFalse(bf.DataOut.Contains(Registers.ecx), "ecx is an in register"); Assert.IsFalse(bf.DataOut.Contains(Registers.esi), "esi is not present in signature"); }
/// <summary> /// Terminates the block with a particular flow. /// </summary> /// <param name="flow">The flow to terminate the block with.</param> public void Terminate(BlockFlow flow) { Block.Flow = flow; IsTerminated = true; }