예제 #1
0
 /// <summary>
 /// Extracts structured program constructs out of snarled goto nests, if possible.
 /// Since procedures are now independent of each other, this analysis
 /// is done one procedure at a time.
 /// </summary>
 public void StructureProgram()
 {
     foreach (var program in project.Programs)
     {
         int i = 0;
         foreach (Procedure proc in program.Procedures.Values)
         {
             try
             {
                 eventListener.ShowProgress("Rewriting procedures to high-level language.", i, program.Procedures.Values.Count);
                 ++i;
                 Console.WriteLine("rewriting: {0}", proc);
                 IStructureAnalysis sa = new StructureAnalysis(proc);
                 sa.Structure();
             }
             catch (Exception e)
             {
                 eventListener.Error(
                     eventListener.CreateProcedureNavigator(program, proc),
                     e,
                     "An error occurred while rewriting procedure to high-level language.");
             }
         }
         WriteDecompilerProducts();
     }
     eventListener.ShowStatus("Rewriting complete.");
 }
예제 #2
0
파일: Decompiler.cs 프로젝트: nemerle/reko
 /// <summary>
 /// Extracts structured program constructs out of snarled goto nests, if possible.
 /// Since procedures are now independent of each other, this analysis
 /// is done one procedure at a time.
 /// </summary>
 public void StructureProgram()
 {
     if (project is null)
     {
         return;
     }
     foreach (var program in project.Programs)
     {
         int i = 0;
         foreach (Procedure proc in program.Procedures.Values)
         {
             if (eventListener.IsCanceled())
             {
                 return;
             }
             try
             {
                 eventListener.ShowProgress("Rewriting procedures to high-level language.", i, program.Procedures.Values.Count);
                 ++i;
                 IStructureAnalysis sa = new StructureAnalysis(eventListener, program, proc);
                 sa.Structure();
             }
             catch (Exception e)
             {
                 eventListener.Error(
                     eventListener.CreateProcedureNavigator(program, proc),
                     e,
                     "An error occurred while rewriting procedure to high-level language.");
             }
         }
     }
     project.FireScriptEvent(ScriptEvent.OnProgramDecompiled);
     WriteDecompilerProducts();
     eventListener.ShowStatus("Rewriting complete.");
 }
예제 #3
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()
        {
            eventListener.ShowProgress("Building expressions.", 0, program.Procedures.Count);
            foreach (var sst in this.ssts)
            {
                var ssa = sst.SsaState;
                try
                {
                    DumpWatchedProcedure("Before expression coalescing", ssa.Procedure);

                    // Procedures should be untangled from each other. Now process
                    // each one separately.
                    DeadCode.Eliminate(ssa);

                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.
                    var coa = new Coalescer(ssa);
                    coa.Transform();
                    DeadCode.Eliminate(ssa);

                    var vp = new ValuePropagator(program.SegmentMap, ssa, program.CallGraph, dynamicLinker, eventListener);
                    vp.Transform();

                    DumpWatchedProcedure("After expression coalescing", ssa.Procedure);

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

                    foreach (var de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    DeadCode.Eliminate(ssa);
                    DumpWatchedProcedure("After strength reduction", ssa.Procedure);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(program, ssa, program.InductionVariables, eventListener);
                    web.Transform();
                    ssa.ConvertBack(false);

                    DumpWatchedProcedure("After data flow analysis", ssa.Procedure);
                }
                catch (Exception ex)
                {
                    eventListener.Error(
                        eventListener.CreateProcedureNavigator(program, ssa.Procedure),
                        ex,
                        "An internal error occurred while building the expressions of {0}",
                        ssa.Procedure.Name);
                }
                eventListener.Advance(1);
            }
        }
예제 #4
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;
        }
예제 #5
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()
        {
            eventListener.ShowProgress("Building expressions.", 0, program.Procedures.Count);
            foreach (var sst in this.ssts !)
            {
                var ssa = sst.SsaState;
                try
                {
                    if (program.User.AggressiveBranchRemoval)
                    {
                        // This ends up being very aggressive and doesn't replicate the original
                        // binary code. See discussion on https://github.com/uxmal/reko/issues/932
                        DumpWatchedProcedure("urb", "Before unreachable block removal", ssa.Procedure);
                        var urb = new UnreachableBlockRemover(ssa, eventListener);
                        urb.Transform();
                    }

                    DumpWatchedProcedure("precoa", "Before expression coalescing", ssa.Procedure);

                    // Procedures should be untangled from each other. Now process
                    // each one separately.
                    DeadCode.Eliminate(ssa);

                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.
                    var coa = new Coalescer(ssa);
                    coa.Transform();
                    DeadCode.Eliminate(ssa);

                    var vp = new ValuePropagator(program.SegmentMap, ssa, program.CallGraph, dynamicLinker, eventListener);
                    vp.Transform();

                    DumpWatchedProcedure("postcoa", "After expression coalescing", ssa.Procedure);

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

                    foreach (var de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    DeadCode.Eliminate(ssa);
                    DumpWatchedProcedure("sr", "After strength reduction", ssa.Procedure);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(program, ssa, program.InductionVariables, eventListener);
                    web.Transform();
                    ssa.ConvertBack(false);

                    DumpWatchedProcedure("dfa", "After data flow analysis", ssa.Procedure);
                }
                catch (Exception ex)
                {
                    eventListener.Error(
                        eventListener.CreateProcedureNavigator(program, ssa.Procedure),
                        ex,
                        "An internal error occurred while building the expressions of {0}",
                        ssa.Procedure.Name);
                }
                eventListener.Advance(1);
            }
        }