Exemple #1
0
        /// <summary>
        /// Converts all registers and stack accesses to SSA variables.
        /// </summary>
        /// <param name="proc"></param>
        /// <returns>The SsaTransform for the procedure.</returns>
        public SsaTransform ConvertToSsa(Procedure proc)
        {
            if (program.NeedsSsaTransform)
            {
                // Transform the procedure to SSA state. When encountering 'call'
                // instructions, they can be to functions already visited. If so,
                // they have a "ProcedureFlow" associated with them. If they have
                // not been visited, or are computed destinations  (e.g. vtables)
                // they will have no "ProcedureFlow" associated with them yet, in
                // which case the the SSA treats the call as a "hell node".
                var sst = new SsaTransform(program, proc, sccProcs, dynamicLinker, this.ProgramDataFlow);
                var ssa = sst.Transform();
                DumpWatchedProcedure("After SSA", ssa.Procedure);

                // Merge unaligned memory accesses.
                var fuser = new UnalignedMemoryAccessFuser(ssa);
                fuser.Transform();

                // After value propagation expressions like (x86)
                // mem[esp_42+4] will have been converted to mem[fp - 30].
                // We also hope that procedure constants
                // kept in registers are propagated to the corresponding call
                // sites.
                var vp = new ValuePropagator(program.SegmentMap, ssa, program.CallGraph, dynamicLinker, eventListener);
                vp.Transform();
                DumpWatchedProcedure("After first VP", ssa.Procedure);

                // Fuse additions and subtractions that are linked by the carry flag.
                var larw = new LongAddRewriter(ssa);
                larw.Transform();

                // Propagate condition codes and registers.
                var cce = new ConditionCodeEliminator(ssa, program.Platform);
                cce.Transform();

                vp.Transform();
                DumpWatchedProcedure("After CCE", ssa.Procedure);

                // Now compute SSA for the stack-based variables as well. That is:
                // mem[fp - 30] becomes wLoc30, while
                // mem[fp + 30] becomes wArg30.
                // This allows us to compute the dataflow of this procedure.
                sst.RenameFrameAccesses = true;
                sst.Transform();
                DumpWatchedProcedure("After SSA frame accesses", ssa.Procedure);

                var icrw = new IndirectCallRewriter(program, ssa, eventListener);
                while (!eventListener.IsCanceled() && icrw.Rewrite())
                {
                    vp.Transform();
                    sst.RenameFrameAccesses = true;
                    sst.Transform();
                }

                var fpuGuesser = new FpuStackReturnGuesser(ssa);
                fpuGuesser.Rewrite();

                // By placing use statements in the exit block, we will collect
                // reaching definitions in the use statements.
                sst.AddUsesToExitBlock();
                sst.RemoveDeadSsaIdentifiers();

                // Backpropagate stack pointer from procedure return.
                var spBackpropagator = new StackPointerBackpropagator(ssa);
                spBackpropagator.BackpropagateStackPointer();
                DumpWatchedProcedure("After SP BP", ssa.Procedure);

                // Propagate those newly created stack-based identifiers.
                vp.Transform();
                DumpWatchedProcedure("After VP2", ssa.Procedure);

                return(sst);
            }
            else
            {
                // We are assuming phi functions are already generated.
                var sst = new SsaTransform(program, proc, sccProcs, dynamicLinker, this.ProgramDataFlow);
                return(sst);
            }
        }
        /// <summary>
        /// Converts all registers and stack accesses to SSA variables.
        /// </summary>
        /// <param name="proc"></param>
        /// <returns>The SsaTransform for the procedure.</returns>
        public SsaTransform ConvertToSsa(Procedure proc)
        {
            if (!program.NeedsSsaTransform)
            {
                // Some formats, like LLVM, already have phi functions.
                var sst = new SsaTransform(program, proc, sccProcs !, dynamicLinker, this.ProgramDataFlow);
                return(sst);
            }

            try
            {
                // Transform the procedure to SSA state. When encountering 'call'
                // instructions, they can be to functions already visited. If so,
                // they have a "ProcedureFlow" associated with them. If they have
                // not been visited, or are computed destinations  (e.g. vtables)
                // they will have no "ProcedureFlow" associated with them yet, in
                // which case the the SSA treats the call as a "hell node".
                var sst = new SsaTransform(program, proc, sccProcs !, dynamicLinker, this.ProgramDataFlow);
                var ssa = sst.Transform();
                DumpWatchedProcedure("ssa", "After SSA", ssa);
                // Merge unaligned memory accesses.
                var fuser = new UnalignedMemoryAccessFuser(ssa);
                fuser.Transform();

                // Fuse additions and subtractions that are linked by the carry flag.
                var larw = new LongAddRewriter(ssa, eventListener);
                larw.Transform();
                DumpWatchedProcedure("larw", "After long add rewriter", ssa);

                // After value propagation expressions like (x86)
                // mem[esp_42+4] will have been converted to mem[fp - 30].
                // We also hope that procedure constants
                // kept in registers are propagated to the corresponding call
                // sites.
                var vp = new ValuePropagator(program.SegmentMap, ssa, program.CallGraph, dynamicLinker, eventListener);
                vp.Transform();
                DumpWatchedProcedure("vp", "After first VP", ssa);

                // Value propagation may uncover more opportunities.
                larw = new LongAddRewriter(ssa, eventListener);
                larw.Transform();
                DumpWatchedProcedure("larw2", "After second long add rewriter", ssa);

                // Eliminate condition codes by discovering uses of ccodes
                // and replacing them with higher-level constructs.
                var cce = new ConditionCodeEliminator(program, ssa, eventListener);
                cce.Transform();
                vp.Transform();
                DumpWatchedProcedure("cce", "After CCE", ssa);

                // Now compute SSA for the stack-based variables as well. That is:
                // mem[fp - 30] becomes wLoc30, while
                // mem[fp + 30] becomes wArg30.
                // This allows us to compute the dataflow of this procedure.
                sst.RenameFrameAccesses = true;
                sst.Transform();
                DumpWatchedProcedure("ssaframe", "After SSA frame accesses", ssa);

                var icrw = new IndirectCallRewriter(program, ssa, eventListener);
                while (!eventListener.IsCanceled() && icrw.Rewrite())
                {
                    vp.Transform();
                    sst.RenameFrameAccesses = true;
                    sst.Transform();
                }

                var fpuGuesser = new FpuStackReturnGuesser(ssa, eventListener);
                fpuGuesser.Transform();
                DumpWatchedProcedure("fpug", "After FPU stack guesser", ssa);

                // By placing use statements in the exit block, we will collect
                // reaching definitions in the use statements.
                sst.AddUsesToExitBlock();
                sst.RemoveDeadSsaIdentifiers();

                // Backpropagate stack pointer from procedure return.
                var spBackpropagator = new StackPointerBackpropagator(ssa, eventListener);
                spBackpropagator.BackpropagateStackPointer();
                DumpWatchedProcedure("spbp", "After SP BP", ssa);

                // Propagate those newly created stack-based identifiers.
                vp.Transform();
                DumpWatchedProcedure("vp2", "After VP2", ssa);

                return(sst);
            }
            catch (Exception ex)
            {
                var nl     = Environment.NewLine;
                var banner = $"// {proc.Name} ==========={nl}{ex.Message}{nl}{ex.StackTrace}{nl}{nl}";
                services.GetService <ITestGenerationService>()?
                .ReportProcedure($"analysis_{99:00}_crash.txt", banner, proc);
                throw;
            }
        }