示例#1
0
        /// <summary>
        /// Analize the MoveNext method
        /// </summary>
        /// <param name="cfg"></param>
        /// <param name="pointsToAnalyzer"></param>
        /// <param name="protectedNodes"></param>
        /// <returns></returns>
        DependencyPTGDomain AnalyzeScopeMethod(ControlFlowGraph cfg, IteratorPointsToAnalysis pointsToAnalyzer,
                                               IEnumerable <ProtectedRowNode> protectedNodes)
        {
            // Before I did Points-to analysis beforehand the dependnecy analysis. Now I compute then together
            ////var iteratorAnalysis = new IteratorStateAnalysis(cfg, ptgs, this.equalities);
            ////var result = iteratorAnalysis.Analyze();
            //// var dependencyAnalysis = new IteratorDependencyAnalysis(this.moveNextMethod, cfg, ptgs, this.specialFields , this.equalities);

            //var nodeEntry = cfg.Entry.Successors.First();
            //var nodeExit = cfg.NormalExit;
            //nodeExit.NormalSuccessors.Add(nodeEntry);
            //nodeEntry.Predecessors.Add(nodeExit);

            var rangeAnalysis      = new RangeAnalysis(cfg);
            var ranges             = rangeAnalysis.Analyze();
            var exitRange          = ranges[cfg.Exit.Id];
            var dependencyAnalysis = new IteratorDependencyAnalysis(this.moveNextMethod, cfg, pointsToAnalyzer, protectedNodes, this.equalities, this.interprocManager, rangeAnalysis);
            var resultDepAnalysis  = dependencyAnalysis.Analyze();

            //dependencyAnalysis.SetPreviousResult(resultDepAnalysis);

            //resultDepAnalysis = dependencyAnalysis.Analyze();

            var node = cfg.Exit;

            System.Console.Out.WriteLine("At {0}\nBefore {1}\nAfter {2}\n", node.Id, resultDepAnalysis[node.Id].Input, resultDepAnalysis[node.Id].Output);

            this.InputColumns  = dependencyAnalysis.InputColumns;
            this.OutputColumns = dependencyAnalysis.OutputColumns;

            return(resultDepAnalysis[node.Id].Output);
        }
示例#2
0
        /// <summary>
        /// Analize the MoveNext method
        /// </summary>
        /// <param name="cfg"></param>
        /// <param name="pointsToAnalyzer"></param>
        /// <param name="protectedNodes"></param>
        /// <returns></returns>
        DependencyPTGDomain AnalyzeScopeMethod(ControlFlowGraph cfg, SimplePointsToAnalysis pointsToAnalyzer,
                                               IEnumerable <ProtectedRowNode> protectedNodes)
        {
            var nodeEntry = cfg.Entry.Successors.First();
            var nodeExit  = cfg.Exit;

            nodeExit.Successors.Add(nodeEntry);
            nodeEntry.Predecessors.Add(nodeExit);

            var rangeAnalysis = new RangeAnalysis(cfg, this.processToAnalyze.MoveNextMethod);
            var ranges        = rangeAnalysis.Analyze();
            var exitRange     = ranges[cfg.Exit.Id];

            var dependencyAnalysis = new IteratorDependencyAnalysis(this.processToAnalyze, this.processToAnalyze.MoveNextMethod, cfg, pointsToAnalyzer, protectedNodes, this.equalities, this.interprocManager, rangeAnalysis);
            var resultDepAnalysis  = dependencyAnalysis.Analyze();

            //dependencyAnalysis.SetPreviousResult(resultDepAnalysis);

            //resultDepAnalysis = dependencyAnalysis.Analyze();

            var node = cfg.Exit;

            //System.Console.Out.WriteLine("At {0}\nBefore {1}\nAfter {2}\n", node.Id, resultDepAnalysis[node.Id].Input, resultDepAnalysis[node.Id].Output);

            this.InputColumns  = dependencyAnalysis.InputColumns;
            this.OutputColumns = dependencyAnalysis.OutputColumns;

            var result = resultDepAnalysis[node.Id].Output;

            if (!this.OutputColumns.Any())
            {
                var thisVariable      = result.PTG.Roots.Where(v => v.Name == "this").Single();
                var currentTraceables = this.GetTraceablesFromYieldReturn(result).OfType <TraceableTable>();
                if (currentTraceables.Any(t => t.TableKind == ProtectedRowKind.Input))
                {
                    var inputSchema = processToAnalyze.InputSchema;

                    dependencyAnalysis.CopyRow(result, thisVariable, inputSchema, inputTable, outputTable);
                }
            }


            return(result);
        }
示例#3
0
        private DependencyPTGDomain BindCalleeCaller(InterProceduralCallInfo callInfo, ControlFlowGraph calleeCFG,
                                                     IteratorDependencyAnalysis depAnalysis, RangeAnalysis rangeAnalysis)
        {
            var exitResult = depAnalysis.Result[calleeCFG.Exit.Id].Output;
            var exitRange  = rangeAnalysis.Result[calleeCFG.Exit.Id].Output;

            var body = MethodBodyProvider.Instance.GetBody(callInfo.Callee);

            for (int i = 0; i < body.Parameters.Count(); i++)
            {
                var arg   = callInfo.CallArguments[i];
                var param = body.Parameters[i];

                arg   = AdaptIsReference(arg);
                param = AdaptIsReference(param);

                if (exitResult.HasTraceables(param))
                {
                    callInfo.CallerState.AddTraceables(arg, exitResult.GetTraceables(param));
                }

                if (exitResult.HasOutputTraceables(param))
                {
                    callInfo.CallerState.AddOutputTraceables(arg, exitResult.GetOutputTraceables(param));
                }
                if (exitResult.HasOutputControlTraceables(param))
                {
                    callInfo.CallerState.AddOutputControlTraceables(arg, exitResult.GetOutputControlTraceables(param));
                }
            }

            foreach (var outputVar in exitResult.Dependencies.A4_Ouput.Keys)
            {
                //if (exitResult.HasOutputTraceables(outputVar))
                {
                    var newVar = new LocalVariable(callInfo.Callee.Name + "_" + outputVar.Name, callInfo.Callee)
                    {
                        Type = outputVar.Type
                    };
                    callInfo.CallerState.AddTraceables(newVar, exitResult.GetTraceables(outputVar));
                    callInfo.CallerState.AddOutputTraceables(newVar, exitResult.GetOutputTraceables(outputVar));
                    callInfo.CallerState.AddOutputControlTraceables(newVar, exitResult.GetOutputControlTraceables(outputVar));
                }
            }
            foreach (var outputVar in exitResult.Dependencies.A4_Ouput_Control.Keys.Except(exitResult.Dependencies.A4_Ouput.Keys))
            {
                //if (exitResult.HasOutputControlTraceables(outputVar))
                {
                    var newVar = new LocalVariable(callInfo.Callee.Name + "_" + outputVar.Name, callInfo.Callee)
                    {
                        Type = outputVar.Type
                    };
                    callInfo.CallerState.AddTraceables(newVar, exitResult.GetTraceables(outputVar));
                    callInfo.CallerState.AddOutputControlTraceables(newVar, exitResult.GetOutputControlTraceables(outputVar));
                }
            }


            callInfo.CallerState.Dependencies.A1_Escaping.UnionWith(exitResult.Dependencies.A1_Escaping);

            callInfo.CallerState.Dependencies.A2_References.UnionWith(exitResult.Dependencies.A2_References);
            callInfo.CallerState.Dependencies.A3_Fields.UnionWith(exitResult.Dependencies.A3_Fields);

            //callInfo.CallerState.Dependencies.ControlTraceables.UnionWith(exitResult.Dependencies.ControlTraceables);


            callInfo.CallerState.Dependencies.IsTop |= exitResult.Dependencies.IsTop;

            if (callInfo.CallLHS != null)
            {
                // Need to bind the return value
                if (exitResult.Dependencies.A2_Variables.ContainsKey(depAnalysis.ReturnVariable) &&
                    exitResult.HasTraceables(depAnalysis.ReturnVariable))
                {
                    callInfo.CallerState.AssignTraceables(callInfo.CallLHS, exitResult.GetTraceables(depAnalysis.ReturnVariable));
                }
                if (exitResult.Dependencies.A4_Ouput.ContainsKey(depAnalysis.ReturnVariable) &&
                    exitResult.HasOutputTraceables(depAnalysis.ReturnVariable))
                {
                    callInfo.CallerState.AddOutputTraceables(callInfo.CallLHS, exitResult.GetOutputTraceables(depAnalysis.ReturnVariable));
                }
                if (exitResult.Dependencies.A4_Ouput_Control.ContainsKey(depAnalysis.ReturnVariable) &&
                    exitResult.HasOutputControlTraceables(depAnalysis.ReturnVariable))
                {
                    callInfo.CallerState.AddOutputControlTraceables(callInfo.CallLHS, exitResult.GetOutputControlTraceables(depAnalysis.ReturnVariable));
                }

                // DIEGODIEGO: Need to propagate range of return value
                callInfo.VariableRanges.AssignValue(callInfo.CallLHS, exitRange.GetValue(rangeAnalysis.ReturnVariable));
            }

            return(callInfo.CallerState);
        }
示例#4
0
        /// This does the interprocedural analysis.
        /// It (currently) does NOT support recursive method invocations
        /// </summary>
        /// <param name="instruction"></param>
        /// <param name="resolvedCallee"></param>
        /// <param name="calleeCFG"></param>
        private InterProceduralReturnInfo InterproceduralAnalysis(InterProceduralCallInfo callInfo, ControlFlowGraph calleeCFG)
        {
            if (stackDepth > InterproceduralManager.MaxStackDepth)
            {
                callInfo.CallerState.Dependencies.IsTop = true;
                AnalysisStats.AddAnalysisReason(new AnalysisReason(callInfo.Caller, callInfo.Instruction, String.Format(CultureInfo.InvariantCulture, "Reach maximum call depth {0}", callInfo.Callee.Name)));
                return(new InterProceduralReturnInfo(callInfo.CallerState));
            }

            stackDepth++;
            // I currently do not support recursive calls
            // Will add support for this in the near future
            if (callStack.Contains(callInfo.Callee))
            {
                callInfo.CallerState.Dependencies.IsTop = true;
                AnalysisStats.AddAnalysisReason(new AnalysisReason(callInfo.Caller, callInfo.Instruction, String.Format(CultureInfo.InvariantCulture, "Recursive call to {0}", callInfo.Callee.Name)));
                return(new InterProceduralReturnInfo(callInfo.CallerState));
            }

            this.callStack.Push(callInfo.Callee);
            //Console.WriteLine("Analyzing Method {0} Stack: {1}", new string(' ',stackDepth*2) + callInfo.Callee.ToString(), stackDepth);
            // 1) Bind PTG and create a Poinst-to Analysis for the  callee. In pta.Result[node.Exit] is the PTG at exit of the callee
            var calleePTG = PTABindCallerCallee(callInfo.CallerPTG, callInfo.CallArguments, callInfo.Callee);
            SimplePointsToAnalysis calleePTA = new SimplePointsToAnalysis(calleeCFG, callInfo.Callee, calleePTG);

            IDictionary <IVariable, IExpression> equalities = new Dictionary <IVariable, IExpression>();

            calleeCFG.PropagateExpressions(equalities);

            // 2) Bind Parameters of the dependency analysis
            VariableRangeDomain boundVariablesRanges;
            var calleeDomain   = BindCallerCallee(callInfo, out boundVariablesRanges);
            var rangesAnalysis = new RangeAnalysis(calleeCFG, callInfo.Callee, boundVariablesRanges);

            // 4) Now we perform the analyses
            rangesAnalysis.Analyze();

            calleeDomain.PTG = calleePTG;
            var dependencyAnalysis = new IteratorDependencyAnalysis(processToAnalyze, callInfo.Callee, calleeCFG, calleePTA, callInfo.ProtectedNodes, equalities, this, rangesAnalysis, calleeDomain, callInfo.ScopeData);

            // If we already did the dataflow analysis for this method we recover the dataflow state
            // This should be adapted (or removed) if we want the analysis to be context sensitive

            //if (dataflowCache.ContainsKey(callInfo.Callee))
            //{
            //    var previosResult = dataflowCache[callInfo.Callee];
            //    //DataFlowAnalysisResult<DependencyPTGDomain>[] resultsCopy = new DataFlowAnalysisResult<DependencyPTGDomain>[previosResult.Length];
            //    //for(int i=0; i< previosResult.Length; i++)
            //    //{
            //    //    resultsCopy[i] = new DataFlowAnalysisResult<DependencyPTGDomain>();
            //    //    resultsCopy[i].Input = previosResult[i].Input!=null? previosResult[i].Input.Clone(): null;
            //    //    resultsCopy[i].Output = previosResult[i].Output!=null? previosResult[i].Output.Clone(): null;
            //    //}
            //    //dependencyAnalysis.SetPreviousResult(resultsCopy);

            //    dependencyAnalysis.SetPreviousResult(previosResult);
            //}

            dependencyAnalysis.Analyze();


            this.dataflowCache[callInfo.Callee] = dependencyAnalysis.Result;

            stackDepth--;
            this.callStack.Pop();

            // 3) Bind callee with caller
            // Should I need the PTG of caller and callee?
            //var exitCalleePTG = calleePTA.Result[calleeCFG.Exit.Id].Output;
            var exitCalleePTG = dependencyAnalysis.Result[calleeCFG.Exit.Id].Output.PTG;


            var exitResult = BindCalleeCaller(callInfo, calleeCFG, dependencyAnalysis, rangesAnalysis);

            // Recover the frame of the original Ptg and bind ptg results
            //PointsToGraph bindPtg = PTABindCaleeCalleer(callInfo.CallLHS, calleeCFG, calleePTA);
            var bindPtg = PTABindCaleeCalleer(callInfo.CallLHS, calleeCFG, exitCalleePTG, calleePTA.ReturnVariable);

            exitResult.PTG = bindPtg;

            return(new InterProceduralReturnInfo(exitResult)
            {
                InputColumns = dependencyAnalysis.InputColumns,
                OutputColumns = dependencyAnalysis.OutputColumns
            });
            //return new InterProceduralReturnInfo(exitResult, bindPtg);
        }
示例#5
0
        public Tuple <DependencyPTGDomain, TimeSpan> AnalyzeMoveNextMethod()
        {
            AnalysisStats.extraAnalysisOverHead = new Stopwatch();
            var sw = new Stopwatch();

            sw.Start();

            // 0) Analyze static fields.
            // DIEGODIEGO: Should I also Include the points-to graph???
            var staticConstructor = processToAnalyze.ProcessorClass.Methods.SingleOrDefault(m => m.Name.Value == ".cctor");

            if (staticConstructor != null)
            {
                var cfgcCtor           = staticConstructor.DoAnalysisPhases(host, sourceLocationProvider);
                var rangeAnalysisCctor = new RangeAnalysis(cfgcCtor, staticConstructor);
                rangeAnalysisCctor.Analyze();
            }

            // The following steps generates a PTG for the MoveNext method that takes into account the context of invocation
            // This is the Producer entry method and the call to GetEnumerator which then is used in the Movenext method

            // 1) Analyze the entry method that creates, populates  and return the clousure
            var cfgEntry      = processToAnalyze.EntryMethod.DoAnalysisPhases(host, sourceLocationProvider);
            var pointsToEntry = new SimplePointsToAnalysis(cfgEntry, processToAnalyze.EntryMethod);
            var entryResult   = pointsToEntry.Analyze();
            var ptgOfEntry    = entryResult[cfgEntry.Exit.Id].Output;

            // 2) Call the GetEnumerator that may create a new clousure and polulate it
            var myGetEnumResult = new LocalVariable("$_temp_it", processToAnalyze.EntryMethod)
            {
                Type = processToAnalyze.GetIteratorMethod.Type
            };

            ptgOfEntry.Add(myGetEnumResult);
            var ptgAfterEnum = this.interprocManager.PTAInterProcAnalysis(ptgOfEntry, new List <IVariable> {
                pointsToEntry.ReturnVariable
            }, myGetEnumResult, processToAnalyze.GetIteratorMethod);

            // These are the nodes that we want to protect/analyze
            var protectedNodes = ptgOfEntry.Nodes.OfType <ParameterNode>()
                                 .Where(n => IsScopeType(n.Type)).Select(n => new ProtectedRowNode(n, ProtectedRowNode.GetKind(n.Type)));

            // Create tables representing the input and output tables
            this.inputTable  = new TraceableTable(protectedNodes.Single(pn => pn.RowKind == ProtectedRowKind.Input));
            this.outputTable = new TraceableTable(protectedNodes.Single(pn => pn.RowKind == ProtectedRowKind.Output));

            // 3) I bing the current PTG with the parameters of MoveNext method on the clousure

            // Well... Inlining is broken we we added the Exceptional control graph. Let's avoid it
            //var cfg = this.moveNextMethod.DoAnalysisPhases(host, this.GetMethodsToInline());

            var cfg = this.interprocManager.GetCFG(processToAnalyze.MoveNextMethod);

            cfg.PropagateExpressions(this.equalities);
            // In general, the variable to bind is going to be pointsToEntry.ReturnVariable which is aliased with "$_temp_it" (myGetEnumResult)
            SimplePointsToGraph calleePTG = InterproceduralManager.PTABindCallerCallee(ptgAfterEnum, new List <IVariable> {
                myGetEnumResult
            }, processToAnalyze.MoveNextMethod);

            this.pointsToAnalyzer = new SimplePointsToAnalysis(cfg, processToAnalyze.MoveNextMethod, calleePTG);


            // Now I analyze the Movenext method with the proper initialization
            var result = this.AnalyzeScopeMethod(cfg, pointsToAnalyzer, protectedNodes);

            sw.Stop();
            //return Tuple.Create(result, sw.Elapsed - AnalysisStats.extraAnalysisOverHead.Elapsed);
            return(Tuple.Create(result, sw.Elapsed));
        }
示例#6
0
 public RangeAnalysisVisitor(RangeAnalysis rangeAnalysis, VariableRangeDomain oldState)
 {
     this.rangeAnalysis = rangeAnalysis;
     this.State         = oldState;
 }