public void CrwManyPredecessorsToExitBlock() { var m = new ProcedureBuilder("CrwManyPredecessorsToExitBlock"); var eax = m.Frame.EnsureRegister(Registers.eax); m.BranchIf(m.Ge0(eax), "m2Ge"); m.Label("m1Lt"); m.Assign(eax, -1); m.Return(); m.Label("m2Ge"); m.BranchIf(m.Ne0(eax), "m4Gt"); m.Label("m3Eq"); m.Return(); m.Label("m4Gt"); m.Assign(eax, 1); m.Return(); var flow = new ProgramDataFlow(program); var sst = new SsaTransform(program, m.Procedure, new HashSet <Procedure>(), null, new ProgramDataFlow()); sst.Transform(); sst.AddUsesToExitBlock(); sst.SsaState.Procedure.Signature = FunctionType.Func( new Identifier("", PrimitiveType.Word32, Registers.eax), new Identifier("eax", PrimitiveType.Word32, Registers.eax)); var crw = new CallRewriter(this.platform, flow, new FakeDecompilerEventListener()); crw.RewriteReturns(sst.SsaState); crw.RemoveStatementsFromExitBlock(sst.SsaState); var sExp = #region Expected @"eax:eax def: def eax uses: branch eax >= 0x00000000 m2Ge branch eax != 0x00000000 m4Gt return eax eax_2: orig: eax def: eax_2 = 0x00000001 uses: return eax_2 eax_3: orig: eax def: eax_3 = 0xFFFFFFFF uses: return eax_3 eax_4: orig: eax // CrwManyPredecessorsToExitBlock // Return size: 0 word32 CrwManyPredecessorsToExitBlock(word32 eax) CrwManyPredecessorsToExitBlock_entry: def eax // succ: l1 l1: branch eax >= 0x00000000 m2Ge // succ: m1Lt m2Ge m1Lt: eax_3 = 0xFFFFFFFF return eax_3 // succ: CrwManyPredecessorsToExitBlock_exit m2Ge: branch eax != 0x00000000 m4Gt // succ: m3Eq m4Gt m3Eq: return eax // succ: CrwManyPredecessorsToExitBlock_exit m4Gt: eax_2 = 0x00000001 return eax_2 // succ: CrwManyPredecessorsToExitBlock_exit CrwManyPredecessorsToExitBlock_exit: "; #endregion AssertExpected(sExp, sst.SsaState); }
private void RunTest(string sExp, Action <ProcedureBuilder> builder) { var pb = new ProcedureBuilder(this.pb.Program.Architecture); builder(pb); var proc = pb.Procedure; var dg = new DominatorGraph <Block>(proc.ControlGraph, proc.EntryBlock); var project = new Project { Programs = { this.pb.Program } }; var listener = new FakeDecompilerEventListener(); var importResolver = new ImportResolver( project, this.pb.Program, listener); var arch = new FakeArchitecture(); var platform = new FakePlatform(null, arch); // Register r1 is assumed to always be implicit when calling // another procedure. var implicitRegs = new HashSet <RegisterStorage> { arch.GetRegister(1) }; Debug.Print("GetRegister(1) {0}", arch.GetRegister(1)); this.pb.Program.Platform = platform; this.pb.Program.Platform = new FakePlatform(null, new FakeArchitecture()); this.pb.Program.SegmentMap = new SegmentMap( Address.Ptr32(0x0000), new ImageSegment( ".text", Address.Ptr32(0), 0x40000, AccessMode.ReadWriteExecute)); // Perform the initial transformation var ssa = new SsaTransform(programFlow, proc, importResolver, dg, implicitRegs); // Propagate values and simplify the results. // We hope the the sequence // esp = fp - 4 // mov [esp-4],eax // will become // esp_2 = fp - 4 // mov [fp - 8],eax var vp = new ValuePropagator(this.pb.Program.Architecture, ssa.SsaState, listener); vp.Transform(); ssa.RenameFrameAccesses = true; ssa.AddUseInstructions = true; ssa.Transform(); var writer = new StringWriter(); proc.Write(false, writer); var sActual = writer.ToString(); if (sActual != sExp) { Debug.Print(sActual); } Assert.AreEqual(sExp, sActual); ssa.SsaState.CheckUses(s => Assert.Fail(s)); }
/// <summary> /// Builds a strongly connected component corresponding to: /// a1 = 0 /// a2 = phi(a1, a3) /// while (a2 != 10) /// { /// a3 = a2 + 4 /// } /// </summary> private List <SsaIdentifier> BuildScc() { var m = new ProcedureBuilder("test"); Identifier a = new Identifier("a", PrimitiveType.Word32, new RegisterStorage("a", 1, 0, PrimitiveType.Word32)); m.Label("b1"); m.Assign(a, Constant.Word32(0)); m.Label("b2"); m.Assign(a, m.IAdd(a, 4)); m.BranchIf(m.Ne(a, 10), "b2"); m.Label("b3"); m.Return(); this.dom = m.Procedure.CreateBlockDominatorGraph(); var program = new Program() { Architecture = m.Architecture, }; var sst = new SsaTransform( program, m.Procedure, new HashSet <Procedure>(), null, new ProgramDataFlow()); sst.Transform(); /* * * proc = new Procedure("test", new Frame(PrimitiveType.Word32)); * Block b1 = proc.AddBlock("b1"); * Block b2 = proc.AddBlock("b2"); * * Identifier a2 = new Identifier("a2", PrimitiveType.Word32, null); * Identifier a3 = new Identifier("a3", PrimitiveType.Word32, null); * PhiFunction phi = new PhiFunction(a1.DataType, new Expression [] { a1, a3 }); * * Statement stm_a1 = new Statement(0, new Assignment(a1, Constant.Word32(0)), null); * Statement stm_a2 = new Statement(0, new PhiAssignment(a2, new PhiFunction(a1.DataType, a1, a3 )), null); * Statement stm_ex = new Statement(0, new Branch(new BinaryExpression(Operator.Ne, PrimitiveType.Bool, a2, Constant.Word32(10)), b2), null); * Statement stm_a3 = new Statement(0, new Assignment(a3, new BinaryExpression(Operator.IAdd, a3.DataType, a2, Constant.Word32(4))), null); * b1.Statements.Add(stm_a1); * * b2.Statements.Add(stm_a2); * b2.Statements.Add(stm_a3); * * SsaIdentifier sid_a1 = new SsaIdentifier(a1, a1, stm_a1, ((Assignment)stm_a1.Instruction).Src, false); * SsaIdentifier sid_a2 = new SsaIdentifier(a2, a2, stm_a2, ((PhiAssignment) stm_a2.Instruction).Src, false); * SsaIdentifier sid_a3 = new SsaIdentifier(a3, a3, stm_a3, ((Assignment) stm_a3.Instruction).Src, false); * sid_a1.Uses.Add(stm_a2); * ssaIds = new SsaIdentifierCollection(); * ssaIds.Add(a1, sid_a1); * ssaIds.Add(a2, sid_a2); * ssaIds.Add(a3, sid_a3); */ ssa = sst.SsaState; List <SsaIdentifier> list = new List <SsaIdentifier> { ssa.Identifiers.Where(i => i.Identifier.Name == "a_1").Single(), ssa.Identifiers.Where(i => i.Identifier.Name == "a_2").Single(), ssa.Identifiers.Where(i => i.Identifier.Name == "a_3").Single(), }; return(list); }