public SimplePointsToAnalysis PTABindAndRunInterProcAnalysis(SimplePointsToGraph ptg, IList <IVariable> arguments, IMethodDefinition resolvedCallee, ControlFlowGraph calleeCFG) { var bindPtg = PTABindCallerCallee(ptg, arguments, resolvedCallee); // Compute PT analysis for callee var pta = new SimplePointsToAnalysis(calleeCFG, resolvedCallee, bindPtg); pta.Analyze(); return(pta); }
/// 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> public SimplePointsToGraph PTAInterProcAnalysis(SimplePointsToGraph ptg, IList <IVariable> arguments, IVariable result, IMethodDefinition resolvedCallee) { if (resolvedCallee.ResolvedMethod.Body.Operations.Any()) { ControlFlowGraph calleeCFG = this.GetCFG(resolvedCallee); //DGMLSerializer.Serialize(calleeCFG); stackDepth++; SimplePointsToAnalysis pta = this.PTABindAndRunInterProcAnalysis(ptg, arguments, resolvedCallee, calleeCFG); stackDepth--; return(PTABindCaleeCalleer(result, calleeCFG, pta)); } return(ptg); }
/// <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 SimplePointsToGraph PTABindCaleeCalleer(IVariable result, ControlFlowGraph calleeCFG, SimplePointsToAnalysis pta) { var exitPTG = pta.Result[calleeCFG.Exit.Id].Output; if (result != null) { exitPTG.RestoreFrame(pta.ReturnVariable, result); } else { exitPTG.RestoreFrame(); } return(exitPTG); }
/// 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)); }