/// <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); }
/// <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); }
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); }
/// 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); }
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)); }
public RangeAnalysisVisitor(RangeAnalysis rangeAnalysis, VariableRangeDomain oldState) { this.rangeAnalysis = rangeAnalysis; this.State = oldState; }