public void TrfCtx_MergeState_Stack() { var state = new Dictionary <Identifier, Tuple <Expression, BitRange> >(); var stateOther = new Dictionary <Identifier, Tuple <Expression, BitRange> >(); var procFlow = new ProcedureFlow(null); var ctx = new TrashedRegisterFinder.Context( null, null, state, procFlow); var ctxOther = new TrashedRegisterFinder.Context( null, null, state, procFlow); var ebp = new Identifier("ebp", PrimitiveType.Word32, new RegisterStorage("ebp", 5, 0, PrimitiveType.Word32)); var esi = new Identifier("esi", PrimitiveType.Word32, new RegisterStorage("esi", 6, 0, PrimitiveType.Word32)); var edi = new Identifier("edi", PrimitiveType.Word32, new RegisterStorage("edi", 7, 0, PrimitiveType.Word32)); ctx.StackState[-4] = ebp; ctx.StackState[-8] = esi; ctx.StackState[-16] = Constant.Word32(0x42); ctx.StackState[-20] = Constant.Word32(0x42); ctxOther.StackState[-4] = ebp; ctxOther.StackState[-12] = edi; ctxOther.StackState[-16] = Constant.Word32(0x42); ctxOther.StackState[-20] = Constant.Word32(0x4711); ctx.MergeWith(ctxOther); Assert.AreEqual(ebp, ctx.StackState[-4]); Assert.AreEqual(esi, ctx.StackState[-8]); Assert.AreEqual(edi, ctx.StackState[-12]); Assert.AreEqual("0x00000042", ctx.StackState[-16].ToString()); Assert.AreSame(Constant.Invalid, ctx.StackState[-20]); }
public void TrfPropagateToProcedureSummary() { Procedure proc = new Procedure("proc", prog.Architecture.CreateFrame()); prog.CallGraph.AddProcedure(proc); Identifier eax = proc.Frame.EnsureRegister(Registers.eax); Identifier ebx = proc.Frame.EnsureRegister(Registers.ebx); Identifier ecx = proc.Frame.EnsureRegister(Registers.ecx); Identifier esi = proc.Frame.EnsureRegister(Registers.esi); flow[proc] = new ProcedureFlow(proc, prog.Architecture); trf = CreateTrashedRegisterFinder(); CreateBlockFlow(proc.ExitBlock, proc.Frame); trf.StartProcessingBlock(proc.ExitBlock); trf.RegisterSymbolicValues[(RegisterStorage)eax.Storage] = eax; // preserved trf.RegisterSymbolicValues[(RegisterStorage)ebx.Storage] = ecx; // trashed trf.RegisterSymbolicValues[(RegisterStorage)esi.Storage] = Constant.Invalid; // trashed trf.PropagateToProcedureSummary(proc); ProcedureFlow pf = flow[proc]; Assert.AreEqual(" ebx esi", pf.EmitRegisters(prog.Architecture, "", pf.TrashedRegisters)); Assert.AreEqual(" eax", pf.EmitRegisters(prog.Architecture, "", pf.PreservedRegisters)); }
public void Rl_MarkLiveStackParameters() { var callee = new Procedure(program.Architecture, "callee", program.Architecture.CreateFrame()); callee.Frame.ReturnAddressSize = 4; callee.Frame.ReturnAddressKnown = true; callee.Frame.EnsureStackArgument(0, PrimitiveType.Word32); callee.Frame.EnsureStackArgument(4, PrimitiveType.Word32); Assert.AreEqual(8, callee.Frame.GetStackArgumentSpace()); ProcedureFlow pf = new ProcedureFlow(callee, program.Architecture); mpprocflow[callee] = pf; m.Frame.EnsureStackLocal(-8, PrimitiveType.Word32); m.Frame.EnsureStackLocal(-12, PrimitiveType.Word32); m.Frame.EnsureStackLocal(-16, PrimitiveType.Word32); rl.CurrentState = new RegisterLiveness.ByPassState(program.Architecture); var ci = new CallInstruction( new ProcedureConstant(PrimitiveType.Ptr32, callee), new CallSite(4, 0) { StackDepthOnEntry = 16 }); rl.Procedure = m.Procedure; rl.MarkLiveStackParameters(ci); Assert.AreEqual(" Local -000C Local -0010", Dump(rl.IdentifierLiveness)); }
public void UrfXXX() { var sExp = "Used: [0..31]"; var regDx = new RegisterStorage("dx", 2, 0, PrimitiveType.Word16); var regAx = new RegisterStorage("ax", 0, 0, PrimitiveType.Word16); var seqDxAx = new SequenceStorage(regDx, regAx); RunClassifyTest( sExp, "dx_ax", m => { var ax = m.Reg("dx", regAx); var dx = m.Reg("ax", regDx); var dx_ax = m.SeqId("dx_ax", PrimitiveType.Word32, regDx, regAx); m.Assign(dx_ax, m.Mem32(m.Word32(0x00123400))); m.Alias(ax, m.Slice(ax.DataType, dx_ax, 0)); m.Alias(dx, m.Slice(ax.DataType, dx_ax, 16)); m.AddUseToExitBlock(ax); m.AddUseToExitBlock(dx); }, p => { var flow = new ProcedureFlow(p); flow.BitsLiveOut.Add(seqDxAx, new BitRange(0, 32)); return(flow); }); }
public void TrfCtx_MergeState_Stack() { var state = new Dictionary <Identifier, (Expression, BitRange)>(); var stateOther = new Dictionary <Identifier, (Expression, BitRange)>(); var procFlow = new ProcedureFlow(null); var proc = Procedure.Create(arch, Address.Ptr32(0x00123400), arch.CreateFrame()); var ssa = new SsaState(proc); var ctx = new TrashedRegisterFinder.Context( ssa, null, state, procFlow); var ctxOther = new TrashedRegisterFinder.Context( ssa, null, state, procFlow); var ebp = new Identifier("ebp", PrimitiveType.Word32, new RegisterStorage("ebp", 5, 0, PrimitiveType.Word32)); var esi = new Identifier("esi", PrimitiveType.Word32, new RegisterStorage("esi", 6, 0, PrimitiveType.Word32)); var edi = new Identifier("edi", PrimitiveType.Word32, new RegisterStorage("edi", 7, 0, PrimitiveType.Word32)); ctx.StackState[-4] = ebp; ctx.StackState[-8] = esi; ctx.StackState[-16] = Constant.Word32(0x42); ctx.StackState[-20] = Constant.Word32(0x42); ctxOther.StackState[-4] = ebp; ctxOther.StackState[-12] = edi; ctxOther.StackState[-16] = Constant.Word32(0x42); ctxOther.StackState[-20] = Constant.Word32(0x4711); ctx.MergeWith(ctxOther); Assert.AreEqual(ebp, ctx.StackState[-4]); Assert.AreEqual(esi, ctx.StackState[-8]); Assert.AreEqual(edi, ctx.StackState[-12]); Assert.AreEqual("0x42<32>", ctx.StackState[-16].ToString()); Assert.IsTrue(ctx.StackState[-20] is InvalidConstant); }
public void Setup() { arch = new FakeArchitecture(); proc = new Procedure("Test", new Frame(arch.FramePointerType)); flow = new ProcedureFlow(proc, arch); ctx = new SymbolicEvaluationContext(arch, proc.Frame); trs = new TrashedRegisterSummarizer(arch, proc, flow, ctx); }
public void Setup() { program = new Program(); program.Architecture = new X86ArchitectureFlat32("x86-protected-32"); program.Platform = new DefaultPlatform(null, program.Architecture); gcr = new GlobalCallRewriter(program, null, new FakeDecompilerEventListener()); proc = new Procedure("foo", program.Architecture.CreateFrame()); flow = new ProcedureFlow(proc, program.Architecture); }
public void Setup() { program = new Program(); program.Architecture = new X86ArchitectureFlat32(); program.Platform = new DefaultPlatform(null, program.Architecture); gcr = new GlobalCallRewriter(program, null); proc = new Procedure("foo", program.Architecture.CreateFrame()); flow = new ProcedureFlow(proc, program.Architecture); }
private Procedure Given_Procedure_With_Flow(ProcedureBuilder m, string name, Storage[] uses, Storage[] defs) { var sig = new FunctionType(); var proc = new Procedure(m.Architecture, name, Address.Ptr32(0x00123400), m.Architecture.CreateFrame()); var flow = new ProcedureFlow(proc); flow.BitsUsed = uses.ToDictionary(u => u, u => new BitRange(0, (int)u.BitSize / 8)); flow.Trashed = defs.ToSet(); this.programDataFlow[proc] = flow; return(proc); }
/// <summary> /// Update the symbolic context with all the registers /// modified by calling the function. /// </summary> /// <param name="pf"></param> public void UpdateRegistersTrashedByProcedure(ProcedureFlow pf) { foreach (var reg in pf.TrashedRegisters) { Constant c; if (!pf.ConstantRegisters.TryGetValue(reg, out c)) { c = Constant.Invalid; } RegisterState[reg] = c; } TrashedFlags |= pf.grfTrashed; }
public void Setup() { program = new Program(); program.Architecture = new X86ArchitectureFlat32("x86-protected-32"); program.Platform = new DefaultPlatform(null, program.Architecture); crw = new CallRewriter(program.Platform, new ProgramDataFlow(), new FakeDecompilerEventListener()); proc = new Procedure(program.Architecture, "foo", Address.Ptr32(0x00123400), program.Architecture.CreateFrame()); flow = new ProcedureFlow(proc); ssa = new SsaState(proc); pb = new ProgramBuilder(); ssaStates = new List <SsaState>(); eventListener = new FakeDecompilerEventListener(); }
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(); }
protected override void RunTest(Program prog, TextWriter writer) { dfa = new DataFlowAnalysis(prog, new FakeDecompilerEventListener()); dfa.AnalyzeProgram(); foreach (Procedure proc in prog.Procedures.Values) { ProcedureFlow flow = dfa.ProgramDataFlow[proc]; writer.Write("// "); flow.Signature.Emit(proc.Name, ProcedureSignature.EmitFlags.ArgumentKind | ProcedureSignature.EmitFlags.LowLevelInfo, writer); flow.Emit(prog.Architecture, writer); proc.Write(false, writer); writer.WriteLine(); } }
public void TrfTerminatingProcedure() { var eax = m.Procedure.Frame.EnsureRegister(Registers.eax); m.Assign(eax, m.Word32(0x40)); m.Call(exit, 4); flow[m.Block] = CreateBlockFlow(m.Block, m.Frame); flow[exit] = new ProcedureFlow(exit, prog.Architecture); flow[exit].TerminatesProcess = true; trf = CreateTrashedRegisterFinder(prog); trf.ProcessBlock(m.Block); Assert.AreEqual("", DumpValues()); }
protected override void RunTest(Program prog, TextWriter writer) { dfa = new DataFlowAnalysis(prog, null, new FakeDecompilerEventListener()); dfa.UntangleProcedures(); foreach (Procedure proc in prog.Procedures.Values) { ProcedureFlow flow = dfa.ProgramDataFlow[proc]; proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.ArgumentKind, new TextFormatter(writer)); writer.WriteLine(); flow.Emit(prog.Architecture, writer); proc.Write(true, writer); writer.Flush(); } }
public Context( SsaState ssa, Identifier fp, Dictionary <Identifier, Tuple <Expression, BitRange> > idState, ProcedureFlow procFlow) : this( ssa, fp, idState, procFlow, new Dictionary <int, Expression>(), new ExpressionValueComparer()) { }
public void Setup() { program = new Program(); sc = new ServiceContainer(); program.Architecture = new X86ArchitectureFlat32(sc, "x86-protected-32", new Dictionary <string, object>()); program.Platform = new DefaultPlatform(sc, program.Architecture); crw = new CallRewriter(program.Platform, new ProgramDataFlow(), new FakeDecompilerEventListener()); proc = new Procedure(program.Architecture, "foo", Address.Ptr32(0x00123400), program.Architecture.CreateFrame()); flow = new ProcedureFlow(proc); ssa = new SsaState(proc); pb = new ProgramBuilder(); ssaStates = new List <SsaState>(); eventListener = new FakeDecompilerEventListener(); sc.AddService <DecompilerEventListener>(eventListener); }
private Context( SsaState ssa, Identifier fp, Dictionary <Identifier, Tuple <Expression, BitRange> > idState, ProcedureFlow procFlow, Dictionary <int, Expression> stack, ExpressionValueComparer cmp) { this.ssa = ssa; this.FramePointer = fp; this.IdState = idState; this.ProcFlow = procFlow; this.StackState = stack; this.cmp = cmp; }
public void TrfCallInstruction() { var callee = new Procedure("Callee", prog.Architecture.CreateFrame()); var stm = m.Call(callee, 4); var pf = new ProcedureFlow(callee, prog.Architecture); pf.TrashedRegisters[Registers.ebx.Number] = true; flow[callee] = pf; trf = CreateTrashedRegisterFinder(); CreateBlockFlow(m.Block, m.Frame); trf.StartProcessingBlock(m.Block); stm.Instruction.Accept(trf); Assert.AreEqual("(ebx:<invalid>)", DumpValues()); }
public void TrfPropagateFlagsToProcedureSummary() { var proc = new Procedure("proc", prog.Architecture.CreateFrame()); prog.CallGraph.AddProcedure(proc); var flags = prog.Architecture.GetFlagGroup("SZ"); var sz = m.Frame.EnsureFlagGroup(flags.FlagGroupBits, flags.Name, flags.DataType); var stm = m.Assign(sz, m.Int32(3)); flow[proc] = new ProcedureFlow(proc, prog.Architecture); trf = CreateTrashedRegisterFinder(prog); CreateBlockFlow(m.Block, m.Frame); trf.StartProcessingBlock(m.Block); stm.Accept(trf); trf.PropagateToProcedureSummary(proc); Assert.AreEqual(" SZ", flow[proc].EmitFlagGroup(prog.Architecture, "", flow[proc].grfTrashed)); }
protected override void RunTest(Program program, TextWriter writer) { SetCSignatures(program); IImportResolver importResolver = new Mock <IImportResolver>().Object; dfa = new DataFlowAnalysis(program, importResolver, new FakeDecompilerEventListener()); dfa.AnalyzeProgram(); foreach (Procedure proc in program.Procedures.Values) { ProcedureFlow flow = dfa.ProgramDataFlow[proc]; writer.Write("// "); var sig = flow.Signature ?? proc.Signature; sig.Emit(proc.Name, FunctionType.EmitFlags.ArgumentKind | FunctionType.EmitFlags.LowLevelInfo, writer); flow.Emit(program.Architecture, writer); proc.Write(false, writer); writer.WriteLine(); } }
private void EmitProgram(Program program, IEnumerable <object> objects, DataFlowAnalysis?dfa, string filename, TextWriter output) { if (output == null) { return; } foreach (object o in objects) { if (o is Procedure proc) { 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 { proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.LowLevelInfo, f); } output.WriteLine(); WriteProcedureCallers(program, proc, output); flow.Emit(proc.Architecture, output); foreach (Block block in new DfsIterator <Block>(proc.ControlGraph).PostOrder().Reverse()) { if (block == null) { continue; } block.Write(output); } } else { proc.Write(false, output); } } output.WriteLine(); output.WriteLine(); } output.Flush(); }
public void Pflow_IntersectBinding_StackArgument_ExactMatch() { var stCallee = new StackArgumentStorage(4, PrimitiveType.Word32); var stCaller = new StackArgumentStorage(4, PrimitiveType.Word32); var idCaller = new Identifier("local", stCaller.DataType, stCaller); var cbs = new[] { new CallBinding(stCaller, idCaller) }; var uses = new Dictionary <Storage, BitRange> { { stCallee, new BitRange(0, 32) } }; var bindings = ProcedureFlow.IntersectCallBindingsWithUses(cbs, uses) .ToArray(); Assert.AreEqual(1, bindings.Length); Assert.AreEqual("Stack +0004:local", bindings[0].ToString()); }
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"); }
public void Pflow_IntersectBinding() { var reg = new RegisterStorage("r1", 1, 0, PrimitiveType.Word32); var id = new Identifier("r1", reg.DataType, reg); var cbs = new[] { new CallBinding(reg, id) }; var uses = new Dictionary <Storage, BitRange> { { reg, new BitRange(0, 31) } }; var bindings = ProcedureFlow.IntersectCallBindingsWithUses(cbs, uses) .ToArray(); Assert.AreEqual(1, bindings.Length); Assert.AreEqual("r1:r1", bindings[0].ToString()); }
public void Rl_ProcedureWithTrashedAndPreservedRegisters() { var proc = new Procedure(program.Architecture, "test", program.Architecture.CreateFrame()); var pf = new ProcedureFlow(proc, program.Architecture); mpprocflow[proc] = pf; pf.TrashedRegisters.Add(Registers.eax); pf.TrashedRegisters.Add(Registers.ebx); pf.PreservedRegisters.Add(Registers.ebp); pf.PreservedRegisters.Add(Registers.bp); RegisterLiveness.State st = new RegisterLiveness.ByPassState(program.Architecture); var bf = CreateBlockFlow(proc.ExitBlock, proc.Frame); mpprocflow[proc.ExitBlock] = bf; st.InitializeBlockFlow(proc.ExitBlock, mpprocflow, true); Assert.IsFalse(bf.DataOut.Contains(Registers.ebp), "preserved registers cannot be live out"); Assert.IsFalse(bf.DataOut.Contains(Registers.bp), "preserved registers cannot be live out"); Assert.IsTrue(bf.DataOut.Contains(Registers.eax), "trashed registers may be live out"); Assert.IsTrue(bf.DataOut.Contains(Registers.esi), "Unmentioned registers may be live out"); }
public void Pflow_IntersectBinding_WiderRegisterInCallBinding() { var regCaller = new RegisterStorage("ebx", 1, 0, PrimitiveType.Word32); var regCallee = new RegisterStorage("bx", 1, 0, PrimitiveType.Word16); var idCaller = new Identifier("ebx", regCaller.DataType, regCaller); var cbs = new[] { new CallBinding(regCaller, idCaller) }; var uses = new Dictionary <Storage, BitRange> { { regCallee, new BitRange(0, 16) } }; var bindings = ProcedureFlow.IntersectCallBindingsWithUses(cbs, uses) .ToArray(); Assert.AreEqual(1, bindings.Length); Assert.AreEqual("bx:SLICE(ebx, word16, 0)", bindings[0].ToString()); }
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"); }
public void Pflow_IntersectBinding_NotFoundUses() { var reg = new RegisterStorage("r1", 1, 0, PrimitiveType.Word32); var stCallee = new StackArgumentStorage(4, PrimitiveType.Word32); var id = new Identifier("r1", reg.DataType, reg); var cbs = new CallBinding[] { }; var uses = new Dictionary <Storage, BitRange> { { reg, new BitRange(0, 31) }, { stCallee, new BitRange(0, 31) }, }; var bindings = ProcedureFlow.IntersectCallBindingsWithUses(cbs, uses) .ToArray(); Assert.AreEqual(0, bindings.Length); }
protected void DumpProcedureFlows(Program program, DataFlowAnalysis dfa, RegisterLiveness live, TextWriter w) { foreach (Procedure proc in program.Procedures.Values) { w.WriteLine("// {0} /////////////////////", proc.Name); ProcedureFlow flow = dfa.ProgramDataFlow[proc]; DataFlow.EmitRegisters(program.Architecture, "\tLiveOut: ", flow.grfLiveOut, flow.LiveOut, w); w.WriteLine(); DataFlow.EmitRegisters(program.Architecture, "\tMayUseIn: ", flow.grfMayUse, flow.MayUse, w); w.WriteLine(); DataFlow.EmitRegisters(program.Architecture, "\tBypassIn: ", flow.grfMayUse, flow.ByPass, w); w.WriteLine(); DataFlow.EmitRegisters(program.Architecture, "\tTrashed: ", flow.grfTrashed, flow.TrashedRegisters, w); w.WriteLine(); DataFlow.EmitRegisters(program.Architecture, "\tPreserved:", flow.grfPreserved, flow.PreservedRegisters, w); w.WriteLine(); w.WriteLine("// {0}", proc.Name); proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, new TextFormatter(w)); w.WriteLine(); foreach (Block block in proc.SortBlocksByName()) { if (live != null) { var bFlow = dfa.ProgramDataFlow[block]; bFlow.WriteBefore(program.Architecture, w); block.Write(w); bFlow.WriteAfter(program.Architecture, w); w.WriteLine(); } else { block.Write(w); } } } }