예제 #1
0
 /// <summary>
 /// Compute the live-in of the procedure whose SSA state is
 /// in <paramref name="ssaState"/>.
 /// </summary>
 /// <remarks>
 /// Assmumes that any live-in parameters are located in the
 /// entry block of the procedure.</remarks>
 /// <param name="ssaState"></param>
 public ProcedureFlow ComputeLiveIn(SsaState ssaState, bool ignoreUse)
 {
     this.procFlow    = flow[ssaState.Procedure];
     this.ssa         = ssaState;
     this.useLiveness = ignoreUse;
     foreach (var stm in ssa.Procedure.EntryBlock.Statements)
     {
         if (!(stm.Instruction is DefInstruction def))
         {
             continue;
         }
         var sid = ssa.Identifiers[def.Identifier];
         if ((sid.Identifier.Storage is RegisterStorage ||
              sid.Identifier.Storage is StackArgumentStorage ||
              sid.Identifier.Storage is FpuStackStorage ||
              sid.Identifier.Storage is SequenceStorage))
         //$REVIEW: flag groups could theoretically be live in
         // although it's uncommon.
         {
             var n = Classify(ssa, sid, sid.Identifier.Storage, ignoreUse);
             if (!n.IsEmpty)
             {
                 procFlow.BitsUsed[sid.Identifier.Storage] = n;
             }
         }
     }
     return(procFlow);
 }
예제 #2
0
        public void DumpProgram()
        {
            foreach (Procedure proc in program.Procedures.Values)
            {
                StringWriter  output = new StringWriter();
                ProcedureFlow pf     = this.flow[proc];
                TextFormatter f      = new TextFormatter(output);
                if (pf.Signature != null)
                {
                    pf.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, f);
                }
                else
                {
                    proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, f);
                }
                output.WriteLine();
                pf.Emit(proc.Architecture, output);

                output.WriteLine("// {0}", proc.Name);
                proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, f);
                output.WriteLine();
                foreach (Block block in proc.ControlGraph.Blocks)
                {
                    if (block != null)
                    {
                        block.Write(output);
                    }
                }
                Debug.WriteLine(output.ToString());
            }
        }
예제 #3
0
        /// <summary>
        /// After running the Used register analysis, the ProcedureFlow of
        /// the procedure <paramref name="proc"/> may have been modified to
        /// exclude some parameters. Functions in the current SCC need to be
        /// adjusted to no longer refer to those parameters.
        /// </summary>
        /// <param name="proc"></param>
        private void RemoveDeadArgumentsFromCalls(
            Procedure proc,
            ProcedureFlow flow,
            IEnumerable <SsaTransform> ssts)
        {
            var mpProcSsa = ssts.ToDictionary(d => d.SsaState.Procedure, d => d.SsaState);

            foreach (Statement stm in program.CallGraph.CallerStatements(proc))
            {
                if (!mpProcSsa.TryGetValue(stm.Block.Procedure, out var ssa))
                {
                    continue;
                }

                // We have a call statement that calls `proc`. Make sure
                // that only arguments present in the procedure flow are present.
                if (!(stm.Instruction is CallInstruction call))
                {
                    continue;
                }
                var filteredUses = ProcedureFlow.IntersectCallBindingsWithUses(call.Uses, flow.BitsUsed)
                                   .ToArray();
                ssa.RemoveUses(stm);
                call.Uses.Clear();
                call.Uses.UnionWith(filteredUses);
                ssa.AddUses(stm);
            }
        }
예제 #4
0
 public override void InitializeProcedureFlow(ProcedureFlow flow)
 {
     flow.MayUse = new BitSet(flow.Summary);
     flow.Summary.SetAll(false);
     flow.grfMayUse  = flow.grfSummary;
     flow.grfSummary = 0;
 }
예제 #5
0
        /// <summary>
        /// Creates a signature for this procedure, and ensures that all registers accessed by the procedure are in the procedure
        /// Frame.
        /// </summary>
        public void EnsureSignature(Procedure proc, ProcedureFlow flow)
        {
            if (proc.Signature != null && proc.Signature.ParametersValid)
            {
                return;
            }

            SignatureBuilder sb    = new SignatureBuilder(proc, Program.Architecture);
            Frame            frame = proc.Frame;

            if (flow.grfLiveOut != 0)
            {
                sb.AddFlagGroupReturnValue(flow.grfLiveOut, frame);
            }

            var    implicitRegs = Program.Platform.CreateImplicitArgumentRegisters();
            BitSet mayUse       = flow.MayUse - implicitRegs;

            foreach (int r in mayUse)
            {
                if (!IsSubRegisterOfRegisters(r, mayUse))
                {
                    sb.AddRegisterArgument(r);
                }
            }

            foreach (KeyValuePair <int, Identifier> de in GetSortedStackArguments(proc.Frame))
            {
                AddStackArgument(de.Key, de.Value, flow, sb);
            }

            foreach (KeyValuePair <int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, 0))
            {
                sb.AddFpuStackArgument(de.Key, de.Value);
            }

            BitSet liveOut = flow.LiveOut - implicitRegs;

            foreach (int r in liveOut)
            {
                if (!IsSubRegisterOfRegisters(r, liveOut))
                {
                    sb.AddArgument(frame.EnsureRegister(Program.Architecture.GetRegister(r)), true);
                }
            }

            foreach (KeyValuePair <int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, -proc.Signature.FpuStackDelta))
            {
                int i = de.Key;
                if (i <= proc.Signature.FpuStackOutArgumentMax)
                {
                    sb.AddArgument(frame.EnsureFpuStackVariable(i, de.Value.DataType), true);
                }
            }

            var sig = sb.BuildSignature();

            flow.Signature = sig;
            proc.Signature = sig;
        }
예제 #6
0
        public static void Rewrite(
            IPlatform platform,
            List <SsaTransform> ssts,
            ProgramDataFlow summaries,
            DecompilerEventListener eventListener)
        {
            CallRewriter crw = new CallRewriter(platform, summaries, eventListener);

            foreach (SsaTransform sst in ssts)
            {
                if (eventListener.IsCanceled())
                {
                    return;
                }
                var           proc = sst.SsaState.Procedure;
                ProcedureFlow flow = crw.mpprocflow[proc];
                flow.Dump(proc.Architecture);
                crw.EnsureSignature(sst.SsaState, proc.Frame, flow);
            }

            foreach (SsaTransform sst in ssts)
            {
                if (eventListener.IsCanceled())
                {
                    return;
                }
                crw.RewriteCalls(sst.SsaState);
                crw.RewriteReturns(sst.SsaState);
                crw.RemoveStatementsFromExitBlock(sst.SsaState);
            }
        }
예제 #7
0
 public override void InitializeProcedureFlow(ProcedureFlow flow)
 {
     flow.ByPass = flow.Summary.Clone();
     flow.Summary.SetAll(false);
     flow.grfByPass  = flow.grfSummary;
     flow.grfSummary = 0;
 }
예제 #8
0
 public void CreateFlowsFor(IEnumerable <Procedure> procs)
 {
     foreach (Procedure proc in procs)
     {
         procFlow[proc] = new ProcedureFlow(proc);
     }
 }
예제 #9
0
        public static void Rewrite(
            Program program,
            ProgramDataFlow summaries,
            DecompilerEventListener eventListener)
        {
            GlobalCallRewriter crw = new GlobalCallRewriter(program, summaries, eventListener);

            foreach (Procedure proc in program.Procedures.Values)
            {
                if (eventListener.IsCanceled())
                {
                    return;
                }
                ProcedureFlow flow = crw.mpprocflow[proc];
                flow.Dump(proc.Architecture);
                crw.AdjustLiveOut(flow);
                crw.EnsureSignature(proc, flow);
                crw.AddUseInstructionsForOutArguments(proc);
            }

            foreach (Procedure proc in program.Procedures.Values)
            {
                if (eventListener.IsCanceled())
                {
                    return;
                }
                crw.RewriteCalls(proc);
                crw.RewriteReturns(proc);
            }
        }
예제 #10
0
        /// <summary>
        /// Remove any storages in the ProcedureFlow <paramref name="flow"/> associated
        /// with the procedure <paramref name="proc"/> if they are dead.
        /// </summary>
        private bool RemoveLiveInStorages(Procedure proc, ProcedureFlow flow, WorkList <SsaState> wl)
        {
            var defs = proc.EntryBlock.Statements
                       .Select(s => s.Instruction as DefInstruction)
                       .Where(s => s != null)
                       .Select(s => s !.Identifier.Storage)
                       .ToHashSet();
            var  deadStgs = flow.BitsUsed.Keys.Except(defs).ToHashSet();
            bool changed  = false;

            foreach (var d in deadStgs)
            {
                flow.BitsUsed.Remove(d);
                changed = true;
            }
            if (changed)
            {
                foreach (Statement stm in program.CallGraph.CallerStatements(proc))
                {
                    if (!(stm.Instruction is CallInstruction ci))
                    {
                        continue;
                    }
                    var ssaCaller = this.procToSsa[stm.Block.Procedure];
                    if (RemoveDeadCallUses(ssaCaller, stm, ci, deadStgs))
                    {
                        wl.Add(ssaCaller);
                    }
                }
            }
            return(changed);
        }
예제 #11
0
 public override void InitializeProcedureFlow(ProcedureFlow flow)
 {
     flow.MayUse = new HashSet <RegisterStorage>(flow.Summary);
     flow.Summary.Clear();
     flow.grfMayUse  = flow.grfSummary;
     flow.grfSummary = 0;
 }
 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);
 }
예제 #13
0
 public override void InitializeProcedureFlow(ProcedureFlow flow)
 {
     flow.ByPass = new HashSet <RegisterStorage>(flow.Summary);
     flow.ByPass.ExceptWith(flow.TrashedRegisters);
     flow.Summary.Clear();
     flow.grfByPass  = flow.grfSummary;
     flow.grfSummary = 0;
 }
예제 #14
0
		public void Setup()
		{
			program = new Program();
			program.Architecture = new IntelArchitecture(ProcessorMode.Protected32);
            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);
		}
예제 #15
0
		public void Setup()
		{
			program = new Program();
			program.Architecture = new X86ArchitectureFlat32();
            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);
		}
예제 #16
0
 private void Dump(bool enable, string s, HashSet <RegisterStorage> a)
 {
     if (enable)
     {
         StringWriter sw = new StringWriter();
         sw.Write("{0}: ", s);
         ProcedureFlow.EmitRegisters(program.Architecture, "", a, sw);
         Debug.WriteLine(sw.ToString());
     }
 }
예제 #17
0
 public TrashedRegisterSummarizer(IProcessorArchitecture arch, Procedure proc, ProcedureFlow pf, SymbolicEvaluationContext ctx)
 {
     this.arch = arch;
     this.proc = proc;
     this.pf = pf;
     trashed = new HashSet<RegisterStorage>();
     preserved = new HashSet<RegisterStorage>();
     this.ctx = ctx;
     this.cmp = new ExpressionValueComparer();
 }
예제 #18
0
 public TrashedRegisterSummarizer(IProcessorArchitecture arch, Procedure proc, ProcedureFlow pf, SymbolicEvaluationContext ctx)
 {
     this.arch = arch;
     this.proc = proc;
     this.pf   = pf;
     trashed   = new HashSet <RegisterStorage>();
     preserved = new HashSet <RegisterStorage>();
     this.ctx  = ctx;
     this.cmp  = new ExpressionValueComparer();
 }
예제 #19
0
 private void Dump()
 {
     foreach (Procedure proc in program.Procedures.Values)
     {
         StringWriter  sw   = new StringWriter();
         ProcedureFlow flow = mpprocData[proc];
         sw.WriteLine(proc.Name);
         DataFlow.EmitRegisters(program.Architecture, "\tByPass: "******"\tMayUse: ", flow.MayUse, sw); sw.WriteLine();
         Debug.WriteLine(sw.ToString());
     }
 }
예제 #20
0
        /// <summary>
        /// Creates a signature for this procedure by looking at the storages
        /// modified in the exit block, and ensures that all the registers
        /// accessed by the procedure are in the procedure Frame.
        /// </summary>
        public void EnsureSignature(SsaState ssa, IStorageBinder frame, ProcedureFlow flow)
        {
            var proc = ssa.Procedure;

            // If we already have a signature, we don't need to do this work.
            if (!proc.Signature.ParametersValid)
            {
                var sig = MakeSignature(ssa, frame, flow);
                flow.Signature = sig;
                proc.Signature = sig;
            }
        }
예제 #21
0
        private void AdjustLiveIn(Procedure proc, ProcedureFlow flow)
        {
            var liveDefStms = proc.EntryBlock.Statements
                              .Select(s => s.Instruction)
                              .OfType <DefInstruction>()
                              .Select(d => d.Identifier.Storage);
            var dead = flow.BitsUsed.Keys
                       .Except(liveDefStms).ToList();

            foreach (var dd in dead)
            {
                flow.BitsUsed.Remove(dd);
            }
        }
예제 #22
0
 private void ApplySignature(FunctionType sig, ProcedureFlow procFlow)
 {
     //$REVIEW: do we need this? if a procedure has a signature,
     // we will always trust that rather than the flow.
     if (!sig.HasVoidReturn)
     {
         procFlow.Trashed.Add(sig.ReturnValue.Storage);
     }
     foreach (var stg in sig.Parameters
              .Select(p => p.Storage)
              .OfType <OutArgumentStorage>())
     {
         procFlow.Trashed.Add(stg.OriginalIdentifier.Storage);
     }
 }
예제 #23
0
        /// <summary>
        /// Make summary information available in LiveIn and LiveOut for each procedure.
        /// </summary>
        private void CompleteWork()
        {
            foreach (Procedure proc in program.Procedures.Values)
            {
                ProcedureFlow pi = mpprocData[proc];

                BlockFlow bi = mpprocData[proc.ExitBlock];
                pi.LiveOut    = bi.DataOut;
                pi.grfLiveOut = bi.grfOut;

                // Remove unneeded data. Done for performance (and to give GC something to do).

                pi.ByPass.Clear();
            }
        }
예제 #24
0
		public ProgramDataFlow(Program program) : this()
		{
			foreach (Procedure proc in program.Procedures.Values)
			{
				procFlow[proc] = new ProcedureFlow(proc, program.Architecture);
				foreach (Block block in proc.ControlGraph.Blocks)
				{
					blockFlow[block] = new BlockFlow(
                        block, 
                        new HashSet<RegisterStorage>(),
                        new SymbolicEvaluationContext(
                            program.Architecture,
                            proc.Frame));
				}
			}
		}
예제 #25
0
		public ProgramDataFlow(Program prog) : this()
		{
			foreach (Procedure proc in prog.Procedures.Values)
			{
				procFlow[proc] = new ProcedureFlow(proc, prog.Architecture);
				foreach (Block block in proc.ControlGraph.Blocks)
				{
					blockFlow[block] = new BlockFlow(
                        block, 
                        prog.Architecture.CreateRegisterBitset(),
                        new SymbolicEvaluationContext(
                            prog.Architecture,
                            proc.Frame));
				}
			}
		}
예제 #26
0
 public ProgramDataFlow(Program program) : this()
 {
     foreach (Procedure proc in program.Procedures.Values)
     {
         procFlow[proc] = new ProcedureFlow(proc, proc.Architecture);
         foreach (Block block in proc.ControlGraph.Blocks)
         {
             blockFlow[block] = new BlockFlow(
                 block,
                 new HashSet <RegisterStorage>(),
                 new SymbolicEvaluationContext(
                     proc.Architecture,
                     proc.Frame));
         }
     }
 }
예제 #27
0
 public ProgramDataFlow(Program prog) : this()
 {
     foreach (Procedure proc in prog.Procedures.Values)
     {
         procFlow[proc] = new ProcedureFlow(proc, prog.Architecture);
         foreach (Block block in proc.ControlGraph.Blocks)
         {
             blockFlow[block] = new BlockFlow(
                 block,
                 prog.Architecture.CreateRegisterBitset(),
                 new SymbolicEvaluationContext(
                     prog.Architecture,
                     proc.Frame));
         }
     }
 }
예제 #28
0
		public void AddStackArgument(int x, Identifier id, ProcedureFlow flow, SignatureBuilder sb)
		{
			object o = flow.StackArguments[id];
			if (o != null)
			{
				int bitWidth = (int) o;
				if (bitWidth < id.DataType.BitSize)
				{
					PrimtiveType pt = id.DataType as PrimtiveType;
					if (pt != null)
					{
						id.DataType = PrimtiveType.Create(pt.Domain, bitWidth/8);
					}
				}
			}
			sb.AddStackArgument(x, id);
		}
예제 #29
0
        public bool MergeIntoProcedureFlow(IdentifierLiveness varLive, ProcedureFlow flow)
        {
            if (varLive.BitSet[0x1F])
            {
                varLive.ToString();
            }
            bool fChange = false;

            if (!(varLive.BitSet & ~flow.Summary).IsEmpty)
            {
                flow.Summary |= varLive.BitSet;
                fChange       = true;
            }
            if ((varLive.Grf & ~flow.grfSummary) != 0)
            {
                flow.grfSummary |= varLive.Grf;
                fChange          = true;
            }
            foreach (KeyValuePair <Storage, int> de in varLive.LiveStorages)
            {
                StackArgumentStorage sa = de.Key as StackArgumentStorage;
                if (sa == null)
                {
                    continue;
                }
                int bits = de.Value;

                object o = flow.StackArguments[sa];
                if (o != null)
                {
                    int bitsOld = (int)o;
                    if (bitsOld < bits)
                    {
                        flow.StackArguments[sa] = bits;
                        fChange = true;
                    }
                }
                else
                {
                    flow.StackArguments[sa] = bits;
                    fChange = true;
                }
            }
            return(fChange);
        }
예제 #30
0
        public void AddStackArgument(Identifier id, ProcedureFlow flow, SignatureBuilder sb)
        {
            object o = flow.StackArguments[id];

            if (o != null)
            {
                int bitWidth = (int)o;
                if (bitWidth < id.DataType.BitSize)
                {
                    PrimtiveType pt = id.DataType as PrimtiveType;
                    if (pt != null)
                    {
                        id.DataType = PrimtiveType.Create(pt.Domain, bitWidth);
                    }
                }
            }
            sb.AddInParam(id);
        }
예제 #31
0
        /// <summary>
        /// When liveness analysis reaches the entry block of the procedure,
        /// update the procedure summary information with the current set of
        /// live registers.
        /// </summary>
        /// <param name="p"></param>
        public void PropagateToProcedureSummary(IdentifierLiveness varLive, Procedure p)
        {
            ProcedureFlow flow = mpprocData[p];

            state.ApplySavedRegisters(flow, varLive);
            var change = MergeIntoProcedureFlow(varLive, flow);

            if (change)
            {
                Debug.WriteLineIf(trace.TraceInfo, flow.EmitRegisters(program.Architecture, p.Name + " summary:", flow.Summary));
                state.UpdateSummary(flow);
                foreach (Statement stmCaller in program.CallGraph.CallerStatements(p))
                {
                    Debug.WriteLineIf(trace.TraceVerbose, string.Format("Propagating to {0} (block {1} in {2}", stmCaller.Instruction.ToString(), stmCaller.Block.Name, stmCaller.Block.Procedure.Name));
                    worklist.Add(mpprocData[stmCaller.Block]);
                }
            }
        }
예제 #32
0
        public static void Rewrite(Program program, ProgramDataFlow summaries)
        {
            GlobalCallRewriter crw = new GlobalCallRewriter(program, summaries);

            foreach (Procedure proc in program.Procedures.Values)
            {
                ProcedureFlow flow = (ProcedureFlow)crw.mpprocflow[proc];
                flow.Dump(program.Architecture);
                crw.AdjustLiveOut(flow);
                crw.EnsureSignature(proc, flow);
                crw.AddUseInstructionsForOutArguments(proc);
            }

            foreach (Procedure proc in program.Procedures.Values)
            {
                crw.RewriteCalls(proc);
                crw.RewriteReturns(proc);
            }
        }
예제 #33
0
        public bool MergeIntoProcedureFlow(IdentifierLiveness varLive, ProcedureFlow flow)
        {
            bool fChange  = false;
            int  oldcount = flow.Summary.Count;

            flow.Summary.UnionWith(varLive.Identifiers);
            if (flow.Summary.Count != oldcount)
            {
                fChange = true;
            }
            if ((varLive.Grf & ~flow.grfSummary) != 0)
            {
                flow.grfSummary |= varLive.Grf;
                fChange          = true;
            }
            foreach (KeyValuePair <Storage, int> de in varLive.LiveStorages)
            {
                StackArgumentStorage sa = de.Key as StackArgumentStorage;
                if (sa == null)
                {
                    continue;
                }
                int bits = de.Value;

                object o = flow.StackArguments[sa];
                if (o != null)
                {
                    int bitsOld = (int)o;
                    if (bitsOld < bits)
                    {
                        flow.StackArguments[sa] = bits;
                        fChange = true;
                    }
                }
                else
                {
                    flow.StackArguments[sa] = bits;
                    fChange = true;
                }
            }
            return(fChange);
        }
예제 #34
0
 public BitRange Classify(
     SsaState ssa,
     SsaIdentifier sid,
     Storage storage,
     bool ignoreUseInstructions)
 {
     this.procFlow    = flow[ssa.Procedure];
     this.ssa         = ssa;
     this.useLiveness = ignoreUseInstructions;
     if (storage is RegisterStorage ||
         storage is StackArgumentStorage ||
         storage is FpuStackStorage ||
         storage is FlagGroupStorage ||
         storage is SequenceStorage)
     {
         var n = Classify(sid);
         return(n);
     }
     else
     {
         return(BitRange.Empty);
     }
 }
예제 #35
0
        private bool MergeLiveOut(ProcedureFlow flow, Dictionary <Storage, BitRange> newLiveOut)
        {
            bool change = false;

            foreach (var de in newLiveOut)
            {
                if (flow.BitsLiveOut.TryGetValue(de.Key, out BitRange oldRange))
                {
                    var range = oldRange | de.Value;
                    if (range != oldRange)
                    {
                        flow.BitsLiveOut[de.Key] = range;
                        change = true;
                    }
                }
                else
                {
                    var range = de.Value;
                    flow.BitsLiveOut[de.Key] = range;
                    change = true;
                }
            }
            return(change);
        }
예제 #36
0
        /// <summary>
        /// Creates a signature for this procedure, and ensures that all
        /// registers accessed by the procedure are in the procedure
        /// Frame.
        /// </summary>
        public void EnsureSignature(Procedure proc, ProcedureFlow flow)
        {
            if (proc.Signature.ParametersValid)
            {
                return;
            }

            var sb    = new SignatureBuilder(proc.Frame, proc.Architecture);
            var frame = proc.Frame;

            if (flow.grfLiveOut != 0)
            {
                sb.AddFlagGroupReturnValue(flow.grfLiveOut, frame);
            }

            var implicitRegs = Program.Platform.CreateImplicitArgumentRegisters();
            var mayUse       = new HashSet <RegisterStorage>(flow.MayUse);

            mayUse.ExceptWith(implicitRegs);
            foreach (var reg in mayUse.OrderBy(r => r.Number))
            {
                if (!IsSubRegisterOfRegisters(reg, mayUse))
                {
                    sb.AddRegisterArgument(reg);
                }
            }

            foreach (var id in GetSortedStackArguments(proc.Frame).Values)
            {
                AddStackArgument(id, flow, sb);
            }

            foreach (KeyValuePair <int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, 0))
            {
                sb.AddFpuStackArgument(de.Key, de.Value);
            }

            var liveOut = new HashSet <RegisterStorage>(flow.LiveOut);

            liveOut.ExceptWith(implicitRegs);

            // Sort the names in a stable way to avoid regression tests failing.
            foreach (var r in liveOut.OrderBy(r => r.Number).ThenBy(r => r.BitAddress))
            {
                if (!IsSubRegisterOfRegisters(r, liveOut))
                {
                    sb.AddOutParam(frame.EnsureRegister(r));
                }
            }

            foreach (KeyValuePair <int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, -proc.Signature.FpuStackDelta))
            {
                int i = de.Key;
                if (i <= proc.Signature.FpuStackOutArgumentMax)
                {
                    sb.AddOutParam(frame.EnsureFpuStackVariable(i, de.Value.DataType));
                }
            }

            var sig = sb.BuildSignature();

            flow.Signature = sig;
            proc.Signature = sig;
        }
예제 #37
0
        public void TrfCallInstruction()
        {
            var callee = new Procedure("Callee", program.Architecture.CreateFrame());
            var stm = m.Call(callee, 4);
            var pf = new ProcedureFlow(callee, program.Architecture);
            pf.TrashedRegisters.Add(Registers.ebx);
            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 Rl_MarkLiveStackParameters()
		{
            var callee = new Procedure("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;

			Identifier loc08 = m.Frame.EnsureStackLocal(-8, PrimitiveType.Word32);
			Identifier loc0C = m.Frame.EnsureStackLocal(-12, PrimitiveType.Word32);
			Identifier loc10 = m.Frame.EnsureStackLocal(-16, PrimitiveType.Word32);
			rl.CurrentState = new RegisterLiveness.ByPassState(program.Architecture);
            var ci = new CallInstruction(
                new ProcedureConstant(PrimitiveType.Pointer32, callee),
                new CallSite(4, 0) { StackDepthOnEntry = 16 });
			rl.Procedure = m.Procedure;
			rl.MarkLiveStackParameters(ci);
			Assert.AreEqual(" Local -000C Local -0010", Dump(rl.IdentifierLiveness));
		}
예제 #39
0
        /// <summary>
        /// Make a function signature based on the procedure flow <paramref name="flow"/>.
        /// </summary>
        /// <returns>A valid function signature.</returns>
        public FunctionType MakeSignature(SsaState ssa, IStorageBinder frame, ProcedureFlow flow)
        {
            var allLiveOut   = flow.BitsLiveOut;
            var sb           = new SignatureBuilder(frame, platform.Architecture);
            var implicitRegs = platform.CreateImplicitArgumentRegisters();

            var liveOutFlagGroups = flow.grfLiveOut.Select(de => platform.Architecture.GetFlagGroup(de.Key, de.Value) !);

            AddModifiedFlags(frame, liveOutFlagGroups, sb);

            var mayUseSeqs = flow.BitsUsed.Keys.OfType <SequenceStorage>().ToHashSet();
            var seqRegs    = mayUseSeqs.SelectMany(s => s.Elements).Distinct().ToHashSet();

            //$BUG: should be sorted by ABI register order.
            foreach (var seq in mayUseSeqs.OrderBy(r => r.Name))
            {
                sb.AddSequenceArgument(seq);
            }
            var mayUseRegs = flow.BitsUsed
                             .Select(de => (Key: de.Key as RegisterStorage, de.Value))
                             .Where(b =>
            {
                return(b.Key is RegisterStorage reg && !implicitRegs.Contains(reg));
            })
                             .Select(MakeRegisterParameter)
                             .ToDictionary(de => de.Item1, de => de.Item2);

            //$BUG: should be sorted by ABI register order. Need a new method
            // IPlatform.CreateAbiRegisterCollator().
            foreach (var reg in mayUseRegs.OrderBy(r => r.Key.Number))
            {
                if (!IsSubRegisterOfRegisters(reg.Key, mayUseRegs) &&
                    !seqRegs.Contains(reg.Key))
                {
                    sb.AddRegisterArgument(reg.Key);
                }
            }

            foreach (var id in GetSortedStackArguments((Frame)frame, flow.BitsUsed))
            {
                sb.AddInParam(id.Item2);
            }

            foreach (var oFpu in flow.BitsUsed
                     .Where(f => f.Key is FpuStackStorage)
                     .OrderBy(r => ((FpuStackStorage)r.Key).FpuStackOffset))
            {
                var fpu = (FpuStackStorage)oFpu.Key;
                var id  = frame.EnsureFpuStackVariable(fpu.FpuStackOffset, fpu.DataType);
                sb.AddFpuStackArgument(fpu.FpuStackOffset, id);
            }

            var liveOut = allLiveOut
                          .Select(de => (Key: de.Key as RegisterStorage, de.Value))
                          .Where(de =>
            {
                return(de.Key != null &&
                       !implicitRegs.Contains(de.Key));
            })
                          .Select(MakeRegisterParameter)
                          .ToDictionary(de => de.Item1, de => de.Item2);

            // Sort the names in a stable way to avoid regression tests failing.
            foreach (var r in liveOut.OrderBy(r => r.Key.Number).ThenBy(r => r.Key.BitAddress))
            {
                if (!IsSubRegisterOfRegisters(r.Key, liveOut))
                {
                    var regOut = sb.AddOutParam(frame.EnsureRegister(r.Key));
                    if (regOut.Storage is OutArgumentStorage &&
                        !ssa.Identifiers.TryGetValue(regOut, out var sidOut))
                    {
                        // Ensure there are SSA identifiers for 'out' registers.
                        ssa.Identifiers.Add(regOut, null, null, false);
                    }
                }
            }

            foreach (var fpu in allLiveOut.Keys.OfType <FpuStackStorage>().OrderBy(r => r.FpuStackOffset))
            {
                sb.AddOutParam(frame.EnsureFpuStackVariable(fpu.FpuStackOffset, fpu.DataType));
            }

            var sig = sb.BuildSignature();

            return(sig);
        }
		public void Rl_ProcedureWithTrashedAndPreservedRegisters()
		{
            var proc = new Procedure("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");
		}
예제 #41
0
		/// <summary>
		/// Adjusts LiveOut values for use as out registers.
		/// </summary>
		/// <remarks>
		/// LiveOut sets contain registers that aren't modified by the procedure. When determining
		/// the returned registers, those unmodified registers must be filtered away.
		/// </remarks>
		/// <param name="flow"></param>
		private void AdjustLiveOut(ProcedureFlow flow)
		{
			flow.grfLiveOut &= flow.grfTrashed;
			flow.LiveOut.IntersectWith(flow.TrashedRegisters);
		}
예제 #42
0
        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, program.Architecture);
            flow[exit].TerminatesProcess = true;
            trf = CreateTrashedRegisterFinder(program);
            trf.ProcessBlock(m.Block);
            Assert.AreEqual("", DumpValues());
        }
예제 #43
0
		/// <summary>
		/// Creates a signature for this procedure, and ensures that all 
        /// registers accessed by the procedure are in the procedure
		/// Frame.
		/// </summary>
		public void EnsureSignature(Procedure proc, ProcedureFlow flow)
		{
			if (proc.Signature != null && proc.Signature.ParametersValid)
				return;

			var sb = new SignatureBuilder(proc, Program.Architecture);
			var frame = proc.Frame;
			if (flow.grfLiveOut != 0)
			{
				sb.AddFlagGroupReturnValue(flow.grfLiveOut, frame);
			}

            var implicitRegs = Program.Platform.CreateImplicitArgumentRegisters();
            var mayUse = new HashSet<RegisterStorage>(flow.MayUse);
            mayUse.ExceptWith(implicitRegs);
			foreach (var reg in mayUse.OrderBy(r => r.Number))
			{
				if (!IsSubRegisterOfRegisters(reg, mayUse))
				{
					sb.AddRegisterArgument(reg);
				}
			}

			foreach (KeyValuePair<int,Identifier> de in GetSortedStackArguments(proc.Frame))
			{
				AddStackArgument(de.Key, de.Value, flow, sb);
			}

            foreach (KeyValuePair<int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, 0))
			{
				sb.AddFpuStackArgument(de.Key, de.Value);
			}

            var liveOut = new HashSet<RegisterStorage>(flow.LiveOut);
            liveOut.ExceptWith(implicitRegs);
			foreach (var r in liveOut.OrderBy(r => r.Number))
			{
				if (!IsSubRegisterOfRegisters(r, liveOut))
				{
					sb.AddOutParam(frame.EnsureRegister(r));
				}
			}

            foreach (KeyValuePair<int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, -proc.Signature.FpuStackDelta))
			{
				int i = de.Key;
				if (i <= proc.Signature.FpuStackOutArgumentMax)
				{
					sb.AddOutParam(frame.EnsureFpuStackVariable(i, de.Value.DataType));
				}
			}

            var sig = sb.BuildSignature();
            flow.Signature = sig;
			proc.Signature = sig;
		}
예제 #44
0
		/// <summary>
		/// Creates a signature for this procedure, and ensures that all registers accessed by the procedure are in the procedure
		/// Frame.
		/// </summary>
		public void EnsureSignature(Procedure proc, ProcedureFlow flow)
		{
			if (proc.Signature != null && proc.Signature.ParametersValid)
				return;

			SignatureBuilder sb = new SignatureBuilder(proc, Program.Architecture);
			Frame frame = proc.Frame;
			if (flow.grfLiveOut != 0)
			{
				sb.AddFlagGroupReturnValue(flow.grfLiveOut, frame);
			}

            var implicitRegs = Program.Platform.CreateImplicitArgumentRegisters();
            BitSet mayUse = flow.MayUse - implicitRegs;
			foreach (int r in mayUse)
			{
				if (!IsSubRegisterOfRegisters(r, mayUse))
				{
					sb.AddRegisterArgument(r);
				}
			}

			foreach (KeyValuePair<int,Identifier> de in GetSortedStackArguments(proc.Frame))
			{
				AddStackArgument(de.Key, de.Value, flow, sb);
			}

            foreach (KeyValuePair<int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, 0))
			{
				sb.AddFpuStackArgument(de.Key, de.Value);
			}

            BitSet liveOut = flow.LiveOut - implicitRegs;
			foreach (int r in liveOut)
			{
				if (!IsSubRegisterOfRegisters(r, liveOut))
				{
					sb.AddArgument(frame.EnsureRegister(Program.Architecture.GetRegister(r)), true);
				}
			}

            foreach (KeyValuePair<int, Identifier> de in GetSortedFpuStackArguments(proc.Frame, -proc.Signature.FpuStackDelta))
			{
				int i = de.Key;
				if (i <= proc.Signature.FpuStackOutArgumentMax)
				{
					sb.AddArgument(frame.EnsureFpuStackVariable(i, de.Value.DataType), true);
				}
			}

            var sig = sb.BuildSignature();
            flow.Signature = sig;
			proc.Signature = sig;
		}
예제 #45
0
		/// <summary>
		/// Adjusts LiveOut values for use as out registers.
		/// </summary>
		/// <remarks>
		/// LiveOut sets contain registers that aren't modified by the procedure. When determining
		/// the returned registers, those unmodified registers must be filtered away.
		/// </remarks>
		/// <param name="flow"></param>
		private void AdjustLiveOut(ProcedureFlow flow)
		{
			flow.grfLiveOut &= flow.grfTrashed;
			flow.LiveOut &= flow.TrashedRegisters;
		}
예제 #46
0
        public void Rl_ProcedureWithTrashedAndPreservedRegisters()
        {
            Procedure proc = new Procedure("test", program.Architecture.CreateFrame());
            ProcedureFlow pf = new ProcedureFlow(proc, program.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");
        }
예제 #47
0
        public void TrfPropagateToProcedureSummary()
        {
            Procedure proc = new Procedure("proc", program.Architecture.CreateFrame());
            program.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, program.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(program.Architecture, "", pf.TrashedRegisters));
            Assert.AreEqual(" eax", pf.EmitRegisters(program.Architecture, "", pf.PreservedRegisters));
        }
예제 #48
0
 public void TrfPropagateFlagsToProcedureSummary()
 {
     var proc = new Procedure("proc", program.Architecture.CreateFrame());
     program.CallGraph.AddProcedure(proc);
     var flags = program.Architecture.GetFlagGroup("SZ");
     var sz = m.Frame.EnsureFlagGroup(flags.FlagRegister, flags.FlagGroupBits, flags.Name, flags.DataType);
     var stm = m.Assign(sz, m.Int32(3));
     flow[proc] = new ProcedureFlow(proc, program.Architecture);
     trf = CreateTrashedRegisterFinder(program);
     CreateBlockFlow(m.Block, m.Frame);
     trf.StartProcessingBlock(m.Block);
     stm.Accept(trf);
     trf.PropagateToProcedureSummary(proc);
     Assert.AreEqual(" SZ", flow[proc].EmitFlagGroup(program.Architecture, "", flow[proc].grfTrashed));
 }