Esempio n. 1
0
        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);

            // Perform the initial transformation
            var ssa = new SsaTransform(programFlow, proc, dg);

            // 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(ssa.SsaState.Identifiers, proc);
            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);
        }
Esempio n. 2
0
 private void SetImmediatePostDominators(DominatorGraph <StructureNode> reverseDomGraph)
 {
     foreach (StructureNode node in curProc.Nodes)
     {
         node.ImmPDom = reverseDomGraph.ImmediateDominator(node);
     }
 }
Esempio n. 3
0
        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 importResolver = new ImportResolver(
                project,
                this.pb.Program,
                new FakeDecompilerEventListener());
            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);
            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);
        }
Esempio n. 4
0
        /// <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();
        }
Esempio n. 5
0
        /// <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();
        }
Esempio n. 6
0
        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 importResolver = new ImportResolver(
                project,
                this.pb.Program,
                new FakeDecompilerEventListener());

            this.pb.Program.Platform = new FakePlatform(null, new FakeArchitecture());
            this.pb.Program.ImageMap = new ImageMap(
                Address.Ptr32(0x0000),
                new ImageSegment(
                    ".text",
                    Address.Ptr32(0),
                    0x40000,
                    AccessMode.ReadWriteExecute));

            // Perform the initial transformation
            var ssa = new SsaTransform(programFlow, proc, importResolver, dg);

            // 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.Identifiers, proc);

            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);
        }
Esempio n. 7
0
        /// <summary>
        /// Executes the core of the analysis
        /// </summary>
        /// <remarks>
        /// The algorithm visits nodes in post-order in each iteration. This
        /// means that all descendants of a node will be visited (and
        /// hence had the chance to be reduced) before the node itself.
        /// The algorithm’s behavior when visiting node _n_
        /// depends on hether the region at _n_
        /// is acyclic (has no loop) or not. For an acyclic region, the 
        /// algorithm tries to match the subgraph
        /// at _n_to an acyclic schemas (3.2). If there is no match,
        /// and the region is a switch candidate, then it attempts to
        /// refine the region at _n_ into a switch region.
        ///             
        /// If _n_ is cyclic, the algorithm 
        /// compares the region at _n_ to the cyclic schemata.
        /// If this fails, it refines _n_ into a loop (3.6).
        /// 
        /// If both matching and refinement do not make progress, the
        /// current node _n_ is then skipped for the current iteration of
        /// the algorithm.  If there is an iteration in which all
        /// nodes are skipped, i.e., the algorithm makes no progress, then
        /// the algorithm employs a last resort refinement (3.7) to
        /// ensure that progress can be made in the next iteration.
        /// </remarks>
        public Region Execute()
        {
            var result = BuildRegionGraph(proc);
            this.regionGraph = result.Item1;
            this.entry = result.Item2;
            int iterations = 0;
            int oldCount;
            int newCount;
            do
            {
                if (eventListener.IsCanceled())
                    break;
                ++iterations;
                if (iterations > 1000)
                {
                    eventListener.Warn(
                        eventListener.CreateProcedureNavigator(program, proc),
                        "Structure analysis stopped making progress, quitting. Please report this issue at https://github.com/uxmal/reko");
                    DumpGraph();
                    break;
                }

                oldCount = regionGraph.Nodes.Count;
                this.doms = new DominatorGraph<Region>(this.regionGraph, result.Item2);
                this.unresolvedCycles = new Queue<Tuple<Region, ISet<Region>>>();
                this.unresolvedNoncycles = new Queue<Tuple<Region, ISet<Region>>>();
                var postOrder = new DfsIterator<Region>(regionGraph).PostOrder(entry).ToList();

                bool didReduce = false;
                foreach (var n in postOrder)
                {
                    Probe();
                    didReduce = false;
                    do
                    {
                        if (eventListener.IsCanceled())
                            break;
                        didReduce = ReduceAcyclic(n);
                        if (!didReduce && IsCyclic(n))
                        {
                            didReduce = ReduceCyclic(n);
                        }
                    } while (didReduce);
                }
                newCount = regionGraph.Nodes.Count;
                if (newCount == oldCount && newCount > 1)
                {
                    // Didn't make any progress this round,
                    // try refining unstructured regions
                    ProcessUnresolvedRegions();
                }
            } while (regionGraph.Nodes.Count > 1);
            return entry;
        }
Esempio n. 8
0
 // Use for debugging, but don't leave in the unit tests to avoid
 // useless "spew".
 private void DumpDominatorFrontier(DominatorGraph <string> pdg)
 {
     foreach (var n in graph.Nodes)
     {
         Console.Write("{0}:", n);
         foreach (var df in pdg.DominatorFrontier(n))
         {
             Console.Write(" {0}", df);
         }
         Console.WriteLine();
     }
 }
Esempio n. 9
0
        public Region Execute(Procedure proc)
        {
#if NILZ
        We focus on the novel aspects of our algorithm in this
paper and refer readers interested in any structural analysis
details elided to standard sources 
         
Like vanilla structural analysis, our algorithm visits
nodes in post-order in each iteration.   Intuitively,  this
means that all descendants of a node will be visited (and
hence had the chance to be reduced) before the node itself.
The algorithm’s behavior when visiting node _n_
depends on hether the region at _n_
is acyclic (has no loop) or not. For an acyclic region, the 
algorithm tries to match the subgraph
at _n_to an acyclic schemas (3.2). If there is no match,
and the region is a switch candidate, then it attempts to
refine the region at _n_ into a switch region (3.4).
            
If _n_ is cyclic, the algorithm 
compares the region at _n_ to the cyclic schemas (3.5)
If this fails, it refines _n_ into a loop (3.6).
If both matching and refinement do not make progress, the
current node _n_ is then skipped for the current iteration of
the algorithm.  If there is an iteration in which all
nodes are skipped, i.e., the algorithm makes no progress, then
the algorithm employs a last resort refinement (3.7) to
ensure that progress can be made in the next iteration.
#endif
            var result = BuildRegionGraph(proc);
            this.regionGraph = result.Item1;
            var entry = result.Item2;
            DumpGraph();
            newGraph = new DiGraph<Region>();
            do
            {
                this.Changed = false;
                this.doms = new DominatorGraph<Region>(this.regionGraph, result.Item2);
                this.unresolvedCycles = new List<Tuple<Region, ISet<Region>>>(); 
                var postOrder = new DfsIterator<Region>(regionGraph).PostOrder(entry).ToList();
                Debug.Print("Iterating....");
                DumpGraph();
                foreach (var n in postOrder) 
                {
                    entry = Dfs(n);
                }
            } while (Changed);
            return entry;
        }
Esempio n. 10
0
        public DominatorGraph <StructureNode> AnalyzeGraph()
        {
            var graph         = new StructureGraphAdapter(curProc.Nodes);
            var reverseGraph  = new ReverseGraph(curProc.Nodes);
            var infiniteLoops = FindInfiniteLoops(graph, curProc.EntryNode);

            AddPseudoEdgeFromInfiniteLoopsToExitNode(graph, infiniteLoops, curProc.ExitNode, reverseGraph);

            var pdg = new DominatorGraph <StructureNode>(reverseGraph, curProc.ExitNode);

            SetImmediatePostDominators(pdg);

            RemovePseudoEdgeFromInfiniteLoopsToExitNode(graph, infiniteLoops, curProc.ExitNode);
            return(pdg);
        }
Esempio n. 11
0
        protected override void RunTest(Program prog, FileUnitTester fut)
        {
            foreach (Procedure proc in prog.Procedures.Values)
            {
                DominatorGraph gr    = new DominatorGraph(proc);
                Aliases        alias = new Aliases(proc, prog.Architecture);
                alias.Transform();
                SsaTransform sst = new SsaTransform(proc, gr, true);
                SsaState     ssa = sst.SsaState;

                DeadCode.Eliminate(proc, ssa);

                ValueNumbering vn = new ValueNumbering(ssa.Identifiers);
                ssa.Write(fut.TextWriter);
                proc.Write(false, fut.TextWriter);
                vn.Write(fut.TextWriter);
            }
        }
Esempio n. 12
0
        private SsaTransform BuildSsaTransform(Procedure proc)
        {
            if (program.NeedsSsaTransform)
            {
                var larw = new LongAddRewriter(proc);
                larw.Transform();

                var alias = new Aliases(proc, flow);
                alias.Transform();

                var doms = new DominatorGraph <Block>(proc.ControlGraph, proc.EntryBlock);
                var sst  = new SsaTransform(flow, proc, importResolver, doms, new HashSet <RegisterStorage>());
                return(sst);
            }
            else
            {
                // We are assuming phi functions are already generated.
                var sst = new SsaTransform(proc);
                return(sst);
            }
        }
Esempio n. 13
0
        public LoopFinder(DirectedGraph <T> graph, T entry, DominatorGraph <T> doms)
        {
            this.graph     = graph;
            this.entry     = entry;
            this.loopNodes = new HashSet <T>();
            this.nodeColor = new Dictionary <T, NodeColor>();

            Debug.Assert(entry != null);

            // Find all nodes that can be reached from the back-edge
            // predecessors by reversed edges and paint them gray.
            foreach (var p in graph.Predecessors(entry))
            {
                if (doms.DominatesStrictly(entry, p))
                {
                    // Back edge!
                    if (!nodeColor.ContainsKey(p))
                    {
                        // Unvisited back edge!
                        BackwardVisit(p);
                    }
                }
                else if (p == entry)
                {
                    // Self-loop.
                    loopNodes.Add(p);
                }
            }

            // Find all gray nodes that can be visited from the suspected
            // loop entry and color them black. Black nodes belong
            // to the loop.
            NodeColor color;

            if (nodeColor.TryGetValue(entry, out color) &&
                color == NodeColor.Gray)
            {
                ForwardVisit(entry);
            }
        }
Esempio n. 14
0
        /// <summary>
        /// Executes the core of the analysis
        /// </summary>
        /// <remarks>
        /// The algorithm visits nodes in post-order in each iteration. This
        /// means that all descendants of a node will be visited (and
        /// hence had the chance to be reduced) before the node itself.
        /// The algorithm’s behavior when visiting node _n_
        /// depends on hether the region at _n_
        /// is acyclic (has no loop) or not. For an acyclic region, the 
        /// algorithm tries to match the subgraph
        /// at _n_to an acyclic schemas (3.2). If there is no match,
        /// and the region is a switch candidate, then it attempts to
        /// refine the region at _n_ into a switch region.
        ///             
        /// If _n_ is cyclic, the algorithm 
        /// compares the region at _n_ to the cyclic schemata.
        /// If this fails, it refines _n_ into a loop (3.6).
        /// 
        /// If both matching and refinement do not make progress, the
        /// current node _n_ is then skipped for the current iteration of
        /// the algorithm.  If there is an iteration in which all
        /// nodes are skipped, i.e., the algorithm makes no progress, then
        /// the algorithm employs a last resort refinement (3.7) to
        /// ensure that progress can be made in the next iteration.
        /// </remarks>
        public Region Execute()
        {
            if (proc.Name.EndsWith("2150")) //$DEBUG
                proc.Name.ToString();
            var result = BuildRegionGraph(proc);
            this.regionGraph = result.Item1;
            this.entry = result.Item2;
            int oldCount;
            int newCount;
            do
            {
                //if (proc.Name.EndsWith())
                oldCount = regionGraph.Nodes.Count;
                this.doms = new DominatorGraph<Region>(this.regionGraph, result.Item2);
                this.unresolvedCycles = new Queue<Tuple<Region, ISet<Region>>>();
                this.unresolvedNoncycles = new Queue<Tuple<Region, ISet<Region>>>();
                var postOrder = new DfsIterator<Region>(regionGraph).PostOrder(entry).ToList();

                bool didReduce = false;
                foreach (var n in postOrder)
                {
                    didReduce = false;
                    do {
                        didReduce = ReduceAcyclic(n, false);
                        if (!didReduce && IsCyclic(n))
                        {
                            didReduce = ReduceCyclic(n);
                        }
                    } while (didReduce);
                }
                newCount = regionGraph.Nodes.Count;
                if (newCount == oldCount && newCount > 1)
                {
                    // Didn't make any progress this round,
                    // try refining unstructured regions
                    ProcessUnresolvedRegions();
                }
            } while (regionGraph.Nodes.Count > 1);
            return entry;
        }
Esempio n. 15
0
        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);

            // Perform the initial transformation
            var ssa = new SsaTransform(programFlow, proc, dg);

            // 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(ssa.SsaState.Identifiers, proc);

            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);
        }
Esempio n. 16
0
        /// <summary>
        /// Processes procedures individually, building complex expression trees out
        /// of the simple, close-to-the-machine code generated by the disassembly.
        /// </summary>
        /// <param name="rl"></param>
        public void BuildExpressionTrees()
        {
            int i = 0;

            foreach (Procedure proc in program.Procedures.Values)
            {
                eventListener.ShowProgress("Building complex expressions.", i, program.Procedures.Values.Count);
                ++i;

                try
                {
                    var larw = new LongAddRewriter(proc, program.Architecture);
                    larw.Transform();

                    Aliases alias = new Aliases(proc, program.Architecture, flow);
                    alias.Transform();

                    var doms = new DominatorGraph <Block>(proc.ControlGraph, proc.EntryBlock);
                    var sst  = new SsaTransform(flow, proc, importResolver, doms);
                    var ssa  = sst.SsaState;

                    var cce = new ConditionCodeEliminator(ssa.Identifiers, program.Platform);
                    cce.Transform();
                    //var cd = new ConstDivisionImplementedByMultiplication(ssa);
                    //cd.Transform();

                    DeadCode.Eliminate(proc, ssa);

                    var vp = new ValuePropagator(program.Architecture, ssa.Identifiers, proc);
                    vp.Transform();
                    DeadCode.Eliminate(proc, ssa);


                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.

                    var coa = new Coalescer(proc, ssa);
                    coa.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    var liv = new LinearInductionVariableFinder(
                        proc,
                        ssa.Identifiers,
                        new BlockDominatorGraph(proc.ControlGraph, proc.EntryBlock));
                    liv.Find();

                    foreach (KeyValuePair <LinearInductionVariable, LinearInductionVariableContext> de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    var opt = new OutParameterTransformer(proc, ssa.Identifiers);
                    opt.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(proc, ssa.Identifiers, program.InductionVariables);
                    web.Transform();
                    ssa.ConvertBack(false);
                }
                catch (StatementCorrelatedException stex)
                {
                    eventListener.Error(
                        eventListener.CreateBlockNavigator(program, stex.Statement.Block),
                        stex,
                        "An error occurred during data flow analysis.");
                }
                catch (Exception ex)
                {
                    eventListener.Error(
                        new NullCodeLocation(proc.Name),
                        ex,
                        "An error occurred during data flow analysis.");
                }
            }
        }
Esempio n. 17
0
 private void CompileTest(DirectedGraphImpl<string> e, string entry)
 {
     pdg = new DominatorGraph<string>(e, entry);
 }
Esempio n. 18
0
 public SsaState(Procedure proc, DominatorGraph <Block> domGraph)
 {
     this.Procedure = proc;
     this.DomGraph  = domGraph;
     this.ids       = new SsaIdentifierCollection();
 }
Esempio n. 19
0
 private void DumpDominatorFrontier(DominatorGraph<string> pdg)
 {
     foreach (var n in graph.Nodes)
     {
         Console.Write("{0}:", n);
         foreach (var df in pdg.DominatorFrontier(n))
         {
             Console.Write(" {0}", df);
         }
         Console.WriteLine();
     }
 }
Esempio n. 20
0
        /// <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, IImportResolver importResolver, DominatorGraph <Block> gr, HashSet <RegisterStorage> implicitRegs)
        {
            this.programFlow    = programFlow;
            this.proc           = proc;
            this.importResolver = importResolver;
            this.implicitRegs   = implicitRegs;
            this.SsaState       = new SsaState(proc, gr);
            this.AOrig          = CreateA();

            Transform();
        }
Esempio n. 21
0
		public SsaState(Procedure proc, DominatorGraph<Block> domGraph)
		{
			this.Procedure = proc;
            this.DomGraph = domGraph;
			this.ids = new SsaIdentifierCollection();
		}
Esempio n. 22
0
        /// <summary>
        /// Processes procedures individually, building complex expression trees out
        /// of the simple, close-to-the-machine code generated by the disassembly.
        /// </summary>
        /// <param name="rl"></param>
        public void BuildExpressionTrees()
        {
            int i = 0;
            foreach (Procedure proc in program.Procedures.Values)
            {
                eventListener.ShowProgress("Building complex expressions.", i, program.Procedures.Values.Count);
                ++i;

                try
                {
                    var larw = new LongAddRewriter(proc, program.Architecture);
                    larw.Transform();

                    Aliases alias = new Aliases(proc, program.Architecture, flow);
                    alias.Transform();

                    var doms = new DominatorGraph<Block>(proc.ControlGraph, proc.EntryBlock);
                    var sst = new SsaTransform(flow, proc, doms);
                    var ssa = sst.SsaState;

                    var cce = new ConditionCodeEliminator(ssa.Identifiers, program.Platform);
                    cce.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    var vp = new ValuePropagator(program.Architecture, ssa.Identifiers, proc);
                    vp.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.

                    var coa = new Coalescer(proc, ssa);
                    coa.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    var liv = new LinearInductionVariableFinder(
                        proc,
                        ssa.Identifiers,
                        new BlockDominatorGraph(proc.ControlGraph, proc.EntryBlock));
                    liv.Find();

                    foreach (KeyValuePair<LinearInductionVariable, LinearInductionVariableContext> de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    var opt = new OutParameterTransformer(proc, ssa.Identifiers);
                    opt.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(proc, ssa.Identifiers, program.InductionVariables);
                    web.Transform();
                    ssa.ConvertBack(false);
                }
                catch (Exception ex)
                {
                    eventListener.Error(new NullCodeLocation(proc.Name), ex, "An error occurred during data flow analysis.");
                }
            }
        }
Esempio n. 23
0
 private void CompileTest(DirectedGraphImpl <string> e, string entry)
 {
     pdg = new DominatorGraph <string>(e, entry);
 }
Esempio n. 24
0
        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));
        }
Esempio n. 25
0
        /// <summary>
        /// </summary>
        /// <remarks>
        /// The algorithm visits nodes in post-order in each iteration. This
        /// means that all descendants of a node will be visited (and
        /// hence had the chance to be reduced) before the node itself.
        /// The algorithm’s behavior when visiting node _n_
        /// depends on hether the region at _n_
        /// is acyclic (has no loop) or not. For an acyclic region, the 
        /// algorithm tries to match the subgraph
        /// at _n_to an acyclic schemas (3.2). If there is no match,
        /// and the region is a switch candidate, then it attempts to
        /// refine the region at _n_ into a switch region.
        ///             
        /// If _n_ is cyclic, the algorithm 
        /// compares the region at _n_ to the cyclic schemata.
        /// If this fails, it refines _n_ into a loop (3.6).
        /// 
        /// If both matching and refinement do not make progress, the
        /// current node _n_ is then skipped for the current iteration of
        /// the algorithm.  If there is an iteration in which all
        /// nodes are skipped, i.e., the algorithm makes no progress, then
        /// the algorithm employs a last resort refinement (3.7) to
        /// ensure that progress can be made in the next iteration.
        /// </remarks>
        public Region Execute()
        {
            var result = BuildRegionGraph(proc);
            this.regionGraph = result.Item1;
            var entry = result.Item2;
            int oldCount;
            int newCount;
            DumpGraph();
            do
            {
                oldCount = regionGraph.Nodes.Count;
                this.doms = new DominatorGraph<Region>(this.regionGraph, result.Item2);
                this.postDoms = BuildPostDoms();
                this.unresolvedCycles = new Queue<Tuple<Region, ISet<Region>>>();
                this.unresolvedNoncycles = new Queue<Tuple<Region, ISet<Region>>>();
                this.tailRegions = new Queue<Region>();
                var postOrder = new DfsIterator<Region>(regionGraph).PostOrder(entry).ToList();
                Debug.Print("== Graph contains {0} nodes ===================================", regionGraph.Nodes.Count);
                DumpGraph();

                bool didReduce = false;
                foreach (var n in postOrder)
                {
                    didReduce = false;
                    do {
                        didReduce = ReduceAcyclic(n, false);
                        if (!didReduce && IsCyclic(n))
                        {
                            didReduce = ReduceCyclic(n);
                        }
                    } while (didReduce);
                }

                newCount = regionGraph.Nodes.Count;
                if (newCount == oldCount)
                {
#if NYI
                    didReduce = false;
                    // Didn't make any progress, try removing tail blocks.
                    foreach (var n in postOrder.Where(n => regionGraph.Nodes.Contains(n)))
                    {
                        didreduce = !IsCyclic(n) && ReduceAcyclic(n, true);
                        if (didreduce)
                            break;
                    } 
#endif
                    // Didn't make any progress, try to trim away stray gotos.
           //         if (!didReduce)
                        ProcessUnresolvedRegions();
                }
            } while (regionGraph.Nodes.Count > 1);
            return entry;
        }