InterProcMapping(PTGraph caller, PTGraph callee, Variable thisRef, ExpressionList arguments) { this.calleePTG = callee; this.callerPTG = caller; this.callerThisRef = thisRef; this.arguments = arguments; }
InterProcMapping(InterProcMapping ipm) { this.calleePTG = ipm.calleePTG; this.callerPTG = ipm.callerPTG; this.callerThisRef = ipm.callerThisRef; this.arguments = ipm.arguments; this.mapping = new Dictionary<IPTAnalysisNode, Nodes>(ipm.mapping); }
// Copy Constructor public PointsToState(PointsToState cState) { this.pta = cState.pta; pointsToGraph = new PTGraph(cState.pointsToGraph); // callToNonAnalyzableMethods = new Dictionary<Label, Set<Method>>(cState.callToNonAnalyzableMethods); method = cState.method; methodLabel = cState.methodLabel; //exceptions = cState.exceptions; currentException = cState.currentException; methodAssumptions = cState.methodAssumptions; isDefault = cState.isDefault; }
// Constructor public PointsToState(Method m, PointsToAnalysis pta) { this.pta = pta; this.pointsToGraph = new PTGraph(m); // this.callToNonAnalyzableMethods = new Dictionary<Label, Set<Method>>(); this.method = m; // this.exceptions = new Set<TypeNode>(); this.currentException = null; this.methodAssumptions = new Set<Method>(); this.isDefault = true; }
/// <summary> /// Bind an output or ref result with the argument /// </summary> /// <param name="calleePTG"></param> /// <param name="vr"></param> /// <param name="outParameter"></param> /// <param name="ipm"></param> /// <returns></returns> private void bindRefOrOutParameter(PTGraph callerPTG, PTGraph calleePTG, Variable argVar, Variable outParameter) { if (argVar != null) { // This is like a StoreInditect of LoadIndirect but using the mapping // *arg = related(*outP) // PTAnalysisNode addrArg = callerPTG.GetAddress(argVar); // Nodes callerValues = callerPTG.Values(addrArg); Nodes callerValues = callerPTG.Values(callerPTG.GetLocations(argVar)); // PTAnalysisNode addrOutP = calleePTG.GetAddress(outParameter); // Nodes calleeValues = calleePTG.Values(addrOutP); Nodes calleeValues = calleePTG.Values(calleePTG.GetLocations(outParameter)); Nodes relatedValues2 = Nodes.Empty; foreach (IPTAnalysisNode n2 in calleePTG.Values(calleeValues)) { relatedValues2.AddRange(RelatedExtended(n2)); } // I am assuming Strong Update. Adding an aditional argument false // it become weak update callerPTG.Assign(callerValues, relatedValues2, calleePTG.MethodLabel); } }
/// <summary> /// Bind the caller with the callee and simplify the resulting pointsToGraph /// by removing the load nodes that has been resolved (captured objects) /// </summary> /// <param name="callerPTG"></param> /// <param name="calleePTG"></param> /// <param name="vr"></param> /// <returns></returns> private void bindCallerWithCalleePTG(PTGraph callerPTG, PTGraph calleePTG, Variable vr) { // Compute Edges Edges Inew = new Edges(); foreach (Edge ie in calleePTG.I) { foreach (IPTAnalysisNode nu1 in RelatedExtended(ie.Src)) { foreach (IPTAnalysisNode nu2 in RelatedExtended(ie.Dst)) { Inew.AddIEdge(nu1, ie.Field, nu2); } } } // Compute Edges Edges Onew = new Edges(); foreach (Edge oe in calleePTG.O) { foreach (IPTAnalysisNode nu1 in RelatedExtended(oe.Src)) { if (!nu1.IsNull) Onew.AddOEdge(nu1, oe.Field, oe.Dst); } } // Compute Escape Nodes eNew = new Nodes(); foreach (IPTAnalysisNode n in calleePTG.E) { eNew.AddRange(RelatedExtended(n)); } callerPTG.I.AddEdges(Inew); callerPTG.O.AddEdges(Onew); callerPTG.E.AddRange(eNew); /// Assign vr = related(retValue) Nodes argNodes = Nodes.Empty; if (callerThisRef != null) { // argNodes.Add(callerPTG.GetAddress(callerThisRef)); argNodes.AddRange(callerPTG.GetLocations(callerThisRef)); } if (calleePTG.Method.Parameters != null) { for (int i = 0; i < calleePTG.Method.Parameters.Count; i++) { Parameter p = calleePTG.Method.Parameters[i]; PNode pn = calleePTG.ParameterMap[p]; if (!pn.IsByValue) { if (arguments[i] is Variable) { Variable vArg = (Variable)arguments[i]; bindRefOrOutParameter(callerPTG, calleePTG, arguments[i] as Variable, p); } } if (arguments[i] is Variable) { Variable vArg = (Variable)arguments[i]; // PTAnalysisNode addrArg = callerPTG.GetAddress(vArg); // argNodes.Add(addrArg); argNodes.AddRange(callerPTG.GetLocations(vArg)); } } } if (vr != null) { if (!vr.Type.IsPrimitive && calleePTG.RetValue != null) { callerPTG.AddVariable(vr, callerPTG.MethodLabel); Nodes relatedValues2 = Nodes.Empty; // PTAnalysisNode addrRetValue = calleePTG.GetAddress(calleePTG.RetValue); // foreach (PTAnalysisNode n2 in calleePTG.Values(addrRetValue)) foreach (IPTAnalysisNode n2 in calleePTG.Values(calleePTG.GetLocations(calleePTG.RetValue))) { relatedValues2.AddRange(RelatedExtended(n2)); } callerPTG.Assign(vr, relatedValues2, calleePTG.MethodLabel); } else { callerPTG.ForgetVariable(vr); } } // Now we can remove the load nodes that don't escape Set<LNode> lNodes = callerPTG.LoadNodes; // B = Nodes forward reachable from from Escaping, Parameters, callee Arguments and Global nodes Nodes B = callerPTG.ReachableFromParametersReturnAndGlobalsAnd(argNodes); foreach (LNode ln in lNodes) { Set<Edge> IToRemove = new Set<Edge>(); Set<Edge> OToRemove = new Set<Edge>(); // If the LoadNode is not reachable or it is captured if (!B.Contains(ln) || (Related(ln).Count > 0)) // if (!B.Contains(ln) || (ln.IsParameterValueLNode && (Related(ln).Count > 0 || !Related(ln).Contains(ln)))) //if (!B.Contains(ln) /*&& (ln is LAddrFieldNode */ // /*&& ln.Label.Method.Equals(callerPTG.Method)*/) { foreach (Edge ie in callerPTG.I.EdgesFromSrc(ln)) IToRemove.Add(ie); foreach (Edge ie in callerPTG.I.EdgesFromDst(ln)) IToRemove.Add(ie); foreach (Edge oe in callerPTG.O.EdgesFromDst(ln)) OToRemove.Add(oe); foreach (Edge oe in callerPTG.O.EdgesFromSrc(ln)) OToRemove.Add(oe); removedLoadNodes.Add(ln); } callerPTG.I.RemoveEdges(IToRemove); callerPTG.O.RemoveEdges(OToRemove); } }
public PTGraph ComputeInterProgGraph(PTGraph caller, PTGraph callee, Variable thisRef, ExpressionList arguments, Variable vr, Label lb) { // Compute the new graph using the interproc mapping PTGraph newPTG = new PTGraph(caller); // Compute a new PointsToGraph from the caller by binding it with the callee // and simplifying resolved load nodes bindCallerWithCalleePTG(newPTG, callee, vr); return newPTG; }
/// <summary> /// Computes the PTGraph that binds caller with callee /// </summary> /// <param name="caller"></param> /// <param name="callee"></param> /// <param name="thisRef"></param> /// <param name="arguments"></param> /// <param name="vr"></param> /// <returns></returns> public static InterProcMapping ComputeInterProgMapping(PTGraph caller, PTGraph callee, Variable thisRef, ExpressionList arguments, Variable vr, Label lb) { PTGraph calleeCopy = callee.Simplify(); // InterProcMapping ipm = ComputeInterMapping(caller, callee, thisRef, arguments); InterProcMapping ipm = ComputeInterMapping(caller, calleeCopy, thisRef, arguments, vr); return ipm; }
/// <summary> /// Compute the interProc mapping between callee and caller. /// This is a fixpoint of steps 1,2 and 3 /// </summary> /// <param name="caller"></param> /// <param name="callee"></param> /// <param name="thisRef"></param> /// <param name="arguments"></param> /// <returns></returns> private static InterProcMapping ComputeInterMapping(PTGraph callerPTG, PTGraph calleePTG, Variable thisRef, ExpressionList arguments, Variable vr) { /* // Be sure that every parameter has its value or load node foreach (Parameter p in callerPTG.ParameterMap.Keys) { callerPTG.GetValuesIfEmptyLoadNode(p, callerPTG.MethodLabel); } */ InterProcMapping ipm = new InterProcMapping(callerPTG, calleePTG, thisRef, arguments); ipm.RelateParams(); InterProcMapping oldImp = new InterProcMapping(ipm); do { oldImp = new InterProcMapping(ipm); ipm.MatchOutsideEdges(); ipm.MatchOutsideWithInsideInCallee(); } while (change(oldImp, ipm)); return ipm; }
/// <summary> /// Apply the inter-procedural analysis, binding information from caller and callee /// </summary> /// <param name="vr"></param> /// <param name="callee"></param> /// <param name="receiver"></param> /// <param name="arguments"></param> /// <param name="calleecState"></param> /// <param name="lb"></param> public virtual void ApplyAnalyzableCall(Variable vr, Method callee, Variable receiver, ExpressionList arguments, PointsToState calleecState, Label lb, out InterProcMapping ipm) { // Apply the binding between the pointsToGraph of the caller and the callee // Returns also the mapping used during the parameter-arguments nodes binding if (PointsToAnalysis.debug) { Console.Out.WriteLine("before call to {0}", callee.Name); //pointsToGraph.Dump(); this.Dump(); } if (this.Method.Name.Name.StartsWith("UsingFoo")) { } ipm = InterProcMapping.ComputeInterProgMapping(this.pointsToGraph, calleecState.pointsToGraph, receiver, arguments, vr, lb); BeforeBindCallWithCallee(this, calleecState, receiver, arguments, vr, lb, ipm); PTGraph interProcPTG = ipm.ComputeInterProgGraph(this.pointsToGraph, calleecState.pointsToGraph, receiver, arguments, vr, lb); pointsToGraph = interProcPTG; AfterBindCallWithCallee(this, calleecState, receiver, arguments, vr, lb, ipm); if (PointsToAnalysis.debug) { Console.Out.WriteLine("after call to {0}", callee.Name); Console.Out.WriteLine(ipm); Console.Out.WriteLine("Callee:"); calleecState.Dump(); Console.Out.WriteLine("Caller:"); this.Dump(); } // Update the set of write effects considering the writeffects of the callee // in nodes that will stay in the caller Set<LNode> removedLoadNodes = ipm.removedLoadNodes; // Join the set of non-analyzable calls //joinCalledMethod(callToNonAnalyzableMethods, calleecState.callToNonAnalyzableMethods); }
/// <summary> /// The old support for non Analyzables. TO DELETE /// </summary> /// <param name="vr"></param> /// <param name="callee"></param> /// <param name="receiver"></param> /// <param name="arguments"></param> /// <param name="lb"></param> /// <param name="ipm"></param> public virtual void ApplyNonAnalyzableCallOld(Variable vr, Method callee, Variable receiver, ExpressionList arguments, Label lb, out InterProcMapping ipm) { bool isPure = false; bool isReturnFresh = false; bool isReadingGlobals = true; bool isWritingGlobals = true; Set<Parameter> freshOutParameters = new Set<Parameter>(); Set<Parameter> escapingParameters = new Set<Parameter>(); Set<Parameter> capturedParameters = new Set<Parameter>(); Set<Variable> outArguments = new Set<Variable>(); isPure = PointsToAndEffectsAnnotations.IsAssumedPureMethod(callee); isReadingGlobals = PointsToAndEffectsAnnotations.IsDeclaredReadingGlobals(callee); isWritingGlobals = PointsToAndEffectsAnnotations.IsDeclaredWritingGlobals(callee); if (PointsToAnalysis.debug) { Console.Out.WriteLine("before NON call to {0}", callee.Name); pointsToGraph.Dump(); } if (!callee.ReturnType.IsPrimitive && !CciHelper.IsVoid(callee.ReturnType)) { isReturnFresh = PointsToAndEffectsAnnotations.IsDeclaredFresh(callee); } else if (CciHelper.IsConstructor(callee)) isReturnFresh = true; if (!callee.IsStatic && callee.ThisParameter != null) { bool captured; if (PointsToAndEffectsAnnotations.IsDeclaredEscaping(callee.ThisParameter, out captured)) { escapingParameters.Add(callee.ThisParameter); if (captured) capturedParameters.Add(callee.ThisParameter); } } if (callee.Parameters != null) { for (int i = 0; i < callee.Parameters.Count; i++) { Parameter p = callee.Parameters[i]; if (p.IsOut) { if (PointsToAndEffectsAnnotations.IsDeclaredFresh(p)) { freshOutParameters.Add(p); } outArguments.Add(arguments[i] as Variable); } bool captured; if (PointsToAndEffectsAnnotations.IsDeclaredEscaping(p, out captured)) { escapingParameters.Add(p); if (captured) capturedParameters.Add(p); } } } //if (isWritingGlobals) //{ // addNonAnalyzableMethod(lb, callee); //} if (callee.Name.Name.Equals("Hola") || callee.Name.Name.Equals("GetEnumerator2")) { } PTGraph calleFakePTG = null; // Create a fake PTG for the calle using annotations... calleFakePTG = PTGraph.PTGraphFromAnnotations(callee); // , isPure, isReturnFresh, isWritingGlobals, isReadingGlobals); // calleFakePTG.GenerateDotGraph(callee.FullName + ".dot"); NonAnalyzableCallBeforeUpdatingPTG(vr, callee, receiver, arguments, lb, isPure, isReturnFresh, isWritingGlobals, isReadingGlobals, escapingParameters, capturedParameters, freshOutParameters); /*InterProcMapping */ ipm = InterProcMapping.ComputeInterProgMapping(this.pointsToGraph, calleFakePTG, receiver, arguments, vr, lb); PTGraph interProcPTG = ipm.ComputeInterProgGraph(this.pointsToGraph, calleFakePTG, receiver, arguments, vr, lb); pointsToGraph = interProcPTG; NonAnalyzableCallAfterUpdatingPTG(vr, callee, receiver, arguments, lb, isPure, isReturnFresh, isWritingGlobals, isReadingGlobals, escapingParameters, capturedParameters, freshOutParameters); if (PointsToAnalysis.debug) { Console.Out.WriteLine("after NON call to {0}", callee.Name); pointsToGraph.Dump(); } }