예제 #1
0
        private bool OnAfterCall(FunctionType sigCallee, ProcedureCharacteristics characteristics)
        {
            UserCallData userCall = null;

            if (program.User.Calls.TryGetUpperBound(ric.Address, out userCall))
            {
                var linStart    = ric.Address.ToLinear();
                var linEnd      = linStart + ric.Length;
                var linUserCall = userCall.Address.ToLinear();
                if (linStart > linUserCall || linUserCall >= linEnd)
                {
                    userCall = null;
                }
            }
            if ((characteristics != null && characteristics.Terminates) ||
                (userCall != null && userCall.NoReturn))
            {
                scanner.TerminateBlock(blockCur, ric.Address + ric.Length);
                return(false);
            }

            if (sigCallee != null)
            {
                if (sigCallee.StackDelta != 0)
                {
                    Expression newVal = new BinaryExpression(
                        Operator.IAdd,
                        stackReg.DataType,
                        stackReg,
                        Constant.Create(
                            PrimitiveType.CreateWord(stackReg.DataType.Size),
                            sigCallee.StackDelta));
                    newVal = newVal.Accept(eval);
                    SetValue(stackReg, newVal);
                }
            }
            state.OnAfterCall(sigCallee);

            // Adjust stack after call
            if (sigCallee != null)
            {
                int delta = sigCallee.StackDelta - sigCallee.ReturnAddressOnStack;
                if (delta != 0)
                {
                    var d = Constant.Create(stackReg.DataType, delta);
                    this.Emit(new Assignment(
                                  stackReg,
                                  new BinaryExpression(Operator.IAdd, stackReg.DataType, stackReg, d)));
                }
            }
            return(true);
        }
예제 #2
0
        private bool GenerateCallToOutsideProcedure(CallSite site, Address addr)
        {
            scanner.Warn(ric.Address, "Call target address {0} is invalid.", addr);
            var sig = new FunctionType();
            ProcedureCharacteristics chr = null;

            EmitCall(
                CreateProcedureConstant(
                    new ExternalProcedure(Procedure.GenerateName(addr), sig)),
                sig,
                chr,
                site);
            return(OnAfterCall(sig, chr));
        }
예제 #3
0
 private void EmitCall(
     Expression callee,
     FunctionType sig,
     ProcedureCharacteristics chr,
     CallSite site)
 {
     if (vaScanner.TryScan(ric.Address, sig, chr))
     {
         Emit(vaScanner.BuildInstruction(callee, site));
     }
     else if (sig != null && sig.ParametersValid)
     {
         Emit(BuildApplication(callee, sig, site));
     }
     else
     {
         Emit(new CallInstruction(callee, site));
     }
 }
예제 #4
0
        private bool OnAfterCall(ProcedureSignature sigCallee, ProcedureCharacteristics characteristics)
        {
            if (sigCallee == null)
            {
                return(true);
            }
            state.OnAfterCall(stackReg, sigCallee, eval);
            if (characteristics != null && characteristics.Terminates)
            {
                scanner.TerminateBlock(blockCur, ric.Address + ric.Length);
                return(false);
            }
            int delta = sigCallee.StackDelta - sigCallee.ReturnAddressOnStack;

            if (delta != 0)
            {
                var d = Constant.Create(stackReg.DataType, delta);
                this.Emit(new Assignment(
                              stackReg,
                              new BinaryExpression(Operator.IAdd, stackReg.DataType, stackReg, d)));
            }
            return(true);
        }
예제 #5
0
        public bool VisitCall(RtlCall call)
        {
            if ((call.Class & RtlClass.Delay) != 0)
            {
                // Get delay slot instruction cluster.
                rtlStream.MoveNext();
                ProcessRtlCluster(rtlStream.Current);
            }
            var                      site = OnBeforeCall(stackReg, call.ReturnAddressSize);
            FunctionType             sig;
            ProcedureCharacteristics chr  = null;
            Address                  addr = call.Target as Address;

            if (addr != null)
            {
                var impProc = scanner.GetImportedProcedure(addr, this.ric.Address);
                if (impProc != null)
                {
                    sig = impProc.Signature;
                    chr = impProc.Characteristics;
                    if (chr != null && chr.IsAlloca)
                    {
                        return(ProcessAlloca(site, impProc));
                    }
                    EmitCall(CreateProcedureConstant(impProc), sig, chr, site);
                    return(OnAfterCall(sig, chr));
                }
                if (!program.SegmentMap.IsValidAddress(addr))
                {
                    return(GenerateCallToOutsideProcedure(site, addr));
                }
                var callee   = scanner.ScanProcedure(addr, null, state);
                var pcCallee = CreateProcedureConstant(callee);
                sig = callee.Signature;
                chr = callee.Characteristics;
                EmitCall(pcCallee, sig, chr, site);
                var pCallee = callee as Procedure;
                if (pCallee != null)
                {
                    program.CallGraph.AddEdge(blockCur.Statements.Last, pCallee);
                }
                return(OnAfterCall(sig, chr));
            }

            var procCallee = call.Target as ProcedureConstant;

            if (procCallee != null)
            {
                sig = procCallee.Procedure.Signature;
                chr = procCallee.Procedure.Characteristics;
                EmitCall(procCallee, sig, chr, site);
                return(OnAfterCall(sig, chr));
            }
            sig = GetCallSignatureAtAddress(ric.Address);
            if (sig != null)
            {
                EmitCall(call.Target, sig, chr, site);
                return(OnAfterCall(sig, chr));  //$TODO: make characteristics available
            }

            Identifier id;

            if (call.Target.As <Identifier>(out id))
            {
                var ppp = SearchBackForProcedureConstant(id);
                if (ppp != null)
                {
                    var e = CreateProcedureConstant(ppp);
                    sig = ppp.Signature;
                    chr = ppp.Characteristics;
                    EmitCall(e, sig, chr, site);
                    return(OnAfterCall(sig, chr));
                }
            }

            var imp = ImportedProcedureName(call.Target);

            if (imp != null)
            {
                sig = imp.Signature;
                chr = imp.Characteristics;
                EmitCall(CreateProcedureConstant(imp), sig, chr, site);
                return(OnAfterCall(sig, chr));
            }

            var syscall = program.Platform.FindService(call, state);

            if (syscall != null)
            {
                return(!EmitSystemServiceCall(syscall));
            }

            ProcessIndirectControlTransfer(ric.Address, call);

            var ic = new CallInstruction(call.Target, site);

            Emit(ic);
            sig = GuessProcedureSignature(ic);
            return(OnAfterCall(sig, chr));
        }