public ContractMetadataTemplate(string fullName, Dictionary <string, FunctionMetadataTemplate> methodMetadataTemplates, Dictionary <string, Address> contractReferences) { FullName = fullName; MethodMetadataTemplates = methodMetadataTemplates; ContractReferences = contractReferences; ExternalFuncCall = new Dictionary <string, List <string> >(); TrySetLocalCallingGraph(out var callGraph, out var topologicRes); ProcessFunctionOrder = topologicRes.Reverse().ToList(); LocalCallingGraph = callGraph; }
private CallGraph CreateCallGraph(params ICallGraphNode[] nodes) { var callGraph = new CallGraph(); foreach (var node in nodes) { callGraph.Nodes.Add(node.MethodSignature, node); } return(callGraph); }
private SerializedCallGraph SerializeCallingGraph(CallGraph graph) { var serializedCallGraph = new SerializedCallGraph(); serializedCallGraph.Edges.AddRange(graph.Edges.Select(edge => new GraphEdge { Source = edge.Source, Target = edge.Target })); serializedCallGraph.Vertices.AddRange(graph.Vertices); return(serializedCallGraph); }
/// <summary> /// Creates a new forward analysis for the given control flow graph. /// </summary> /// <param name="rootCfg">The root control flow graph to create the analysis of.</param> /// <param name="callGraph">The graph identifying the calls of methods for interprocedural analysis.</param> /// <param name="procedures">The control flow graphs of the invoked methods.</param> protected ForwardFlowAnalysis(ControlFlowGraph rootCfg, CallGraph callGraph, IEnumerable <ControlFlowGraph> procedures) : base(rootCfg.Nodes.Concat(procedures.SelectMany(procedure => procedure.Nodes)).Concat(callGraph.Nodes)) { Flow = rootCfg.Edges .Concat(procedures.SelectMany(procedure => procedure.Edges)) .Concat(callGraph.Edges) .Select(edge => new FlowTransition(edge.From, edge.To)) .ToImmutableList(); ExtremalNodes = ImmutableHashSet.Create <FlowNode>(rootCfg.Start); }
public static void GenerateDotGraph(System.IO.TextWriter output, CallGraph cg) { foreach (CGNode mn in cg.cgNodes) { output.WriteLine("\"{0}\" [shape = box]", mn.ToString()); } foreach (CGEdge e in cg.calls) { EdgeToDot(output, e, true); } output.WriteLine(); }
public CallGraph GenerateCallGraph() { var callGraph = new CallGraph(); callGraph.BeginRecording(); Console.WriteLine("Recording " + Elements.Count + " instructions in the call graph!"); var firstCall = Elements.First(); var lastCall = Elements.Last(); foreach (var instruction in Elements) { //if (instruction.Eip!=0) // Console.WriteLine("Found an instruction that's not at zero! It's at " + instruction.Eip); var instVersion = instruction as InstInstruction; if (instVersion != null) { callGraph.RecordInstructionCall(instVersion); } if (instruction.CpuTime > lastCall.CpuTime) { lastCall = instruction; } if (instruction.CpuTime < firstCall.CpuTime) { firstCall = instruction; } } callGraph.RecordFunctionCall(0, firstCall.CpuTime); foreach (var instruction in Elements.Where(i => i is InstInstruction).Cast <InstInstruction>()) { if (instruction.Nature == InstInstructionNature.FunctionCall) { callGraph.RecordFunctionCall(instruction.GetCalledAddress(), instruction.CpuTime); } else if (instruction.Nature == InstInstructionNature.FunctionReturn) { callGraph.RecordFunctionReturn(instruction.CpuTime); } } callGraph.RecordFunctionReturn(lastCall.CpuTime); callGraph.EndRecording(lastCall.CpuTime); return(callGraph); }
private void FindIndirectCallersOfSP2010LoggingAPI(Method method) { MetadataCollection <Method> .Enumerator enumerator = CallGraph.CallersFor(method).GetEnumerator(); while (enumerator.MoveNext()) { Method current = enumerator.Current; this.FindIndirectCallersOfSP2010LoggingAPI(current); } if (!(this.methodsThatCallSP2010SPDiagnosticsServiceWriteTraceDirectly.ContainsKey(this.GetOnlyTheMethodName(method.FullName)) || this.methodsThatCallSP2010SPDiagnosticsServiceWriteTraceIndirectly.ContainsKey(this.GetOnlyTheMethodName(method.FullName)))) { this.methodsThatCallSP2010SPDiagnosticsServiceWriteTraceIndirectly.Add(this.GetOnlyTheMethodName(method.FullName), method); } }
private void FindCallersOfTraceEventAPI(Method method) { MetadataCollection <Method> .Enumerator enumerator = CallGraph.CallersFor(method).GetEnumerator(); while (enumerator.MoveNext()) { Method current = enumerator.Current; this.FindCallersOfTraceEventAPI(current); } if (!this.methodsThatCallOneOfTraceEventMethods.ContainsKey(this.GetOnlyTheMethodName(method.FullName))) { this.methodsThatCallOneOfTraceEventMethods.Add(this.GetOnlyTheMethodName(method.FullName), method); } }
private void FindIndirectCallersOfUnsupportedMethod(Method method) { MetadataCollection <Method> .Enumerator enumerator = CallGraph.CallersFor(method).GetEnumerator(); while (enumerator.MoveNext()) { Method current = enumerator.Current; this.FindIndirectCallersOfUnsupportedMethod(current); } if (!(this.methodsThatCallUnsupportedMethodsDirectly.ContainsKey(this.GetOnlyTheMethodName(method.FullName)) || this.methodsThatCallUnsupportedMethodsIndirectly.ContainsKey(this.GetOnlyTheMethodName(method.FullName)))) { this.methodsThatCallUnsupportedMethodsIndirectly.Add(this.GetOnlyTheMethodName(method.FullName), method); } }
public void Creation() { CallGraph g = new CallGraph(); var arch = MockRepository.GenerateStub <IProcessorArchitecture>(); arch.Replay(); Procedure p1 = new Procedure(arch, "p1000", Address.Ptr32(0x1000), null); Procedure p2 = new Procedure(arch, "p2000", Address.Ptr32(0x2000), null); Procedure p3 = new Procedure(arch, "p3000", Address.Ptr32(0x3000), null); Procedure p4 = new Procedure(arch, "p4000", Address.Ptr32(0x4000), null); var pc2 = new ProcedureConstant(PrimitiveType.Ptr32, p2); var pc3 = new ProcedureConstant(PrimitiveType.Ptr32, p3); var pc4 = new ProcedureConstant(PrimitiveType.Ptr32, p4); Statement s11 = new Statement(0, CreateCall(pc2), p1.EntryBlock); Statement s12 = new Statement(0, CreateCall(pc2), p1.EntryBlock); Statement s13 = new Statement(0, CreateCall(pc3), p1.EntryBlock); p1.EntryBlock.Statements.Add(s11); p1.EntryBlock.Statements.Add(s12); p1.EntryBlock.Statements.Add(s13); Statement s21 = new Statement(0, CreateCall(pc3), p2.EntryBlock); Statement s22 = new Statement(0, CreateCall(pc4), p2.EntryBlock); p2.EntryBlock.Statements.Add(s21); p2.EntryBlock.Statements.Add(s22); Statement s31 = new Statement(0, CreateCall(pc4), p3.EntryBlock); p3.EntryBlock.Statements.Add(s31); Statement s41 = new Statement(0, CreateCall(pc4), p4.EntryBlock); g.AddEntryPoint(p1); g.AddEdge(s11, p2); g.AddEdge(s12, p2); g.AddEdge(s13, p3); g.AddEdge(s21, p3); g.AddEdge(s22, p4); g.AddEdge(s31, p4); g.AddEdge(s41, p4); // recursion! //$TODO: need Count // Assert.IsTrue(g.Callees(p1).Count == 3); // Assert.IsTrue(g.CallerStatements(p4).Count == 3); }
public CallGraph GetSCC(Method m) { Set <CallGraph> sccs = this.SCC; CallGraph res = null; foreach (CallGraph scc in sccs) { if (scc.Methods.Contains(m)) { return(scc); } } return(res); }
public void Creation() { CallGraph g = new CallGraph(); Procedure p1 = new Procedure("p1000", null); Procedure p2 = new Procedure("p2000", null); Procedure p3 = new Procedure("p3000", null); Procedure p4 = new Procedure("p4000", null); var pc1 = new ProcedureConstant(PrimitiveType.Pointer32, p1); var pc2 = new ProcedureConstant(PrimitiveType.Pointer32, p2); var pc3 = new ProcedureConstant(PrimitiveType.Pointer32, p3); var pc4 = new ProcedureConstant(PrimitiveType.Pointer32, p4); Statement s11 = new Statement(0, CreateCall(pc2), p1.EntryBlock); Statement s12 = new Statement(0, CreateCall(pc2), p1.EntryBlock); Statement s13 = new Statement(0, CreateCall(pc3), p1.EntryBlock); p1.EntryBlock.Statements.Add(s11); p1.EntryBlock.Statements.Add(s12); p1.EntryBlock.Statements.Add(s13); Statement s21 = new Statement(0, CreateCall(pc3), p2.EntryBlock); Statement s22 = new Statement(0, CreateCall(pc4), p2.EntryBlock); p2.EntryBlock.Statements.Add(s21); p2.EntryBlock.Statements.Add(s22); Statement s31 = new Statement(0, CreateCall(pc4), p3.EntryBlock); p3.EntryBlock.Statements.Add(s31); Statement s41 = new Statement(0, CreateCall(pc4), p4.EntryBlock); g.AddEntryPoint(p1); g.AddEdge(s11, p2); g.AddEdge(s12, p2); g.AddEdge(s13, p3); g.AddEdge(s21, p3); g.AddEdge(s22, p4); g.AddEdge(s31, p4); g.AddEdge(s41, p4); // recursion! //$TODO: need Count // Assert.IsTrue(g.Callees(p1).Count == 3); // Assert.IsTrue(g.CallerStatements(p4).Count == 3); }
private Statement?stmCur; //$REFACTOR: try to make this a context paramter. public ValuePropagator( SegmentMap segmentMap, SsaState ssa, CallGraph callGraph, IDynamicLinker dynamicLinker, DecompilerEventListener eventListener) { this.ssa = ssa; this.callGraph = callGraph; this.arch = ssa.Procedure.Architecture; this.eventListener = eventListener; this.ssam = new SsaMutator(ssa); this.evalCtx = new SsaEvaluationContext(arch, ssa.Identifiers, dynamicLinker); this.eval = new ExpressionSimplifier(segmentMap, evalCtx, eventListener); }
public ValuePropagator( SegmentMap segmentMap, SsaState ssa, CallGraph callGraph, IImportResolver importResolver, DecompilerEventListener eventListener) { this.ssa = ssa; this.callGraph = callGraph; this.arch = ssa.Procedure.Architecture; this.eventListener = eventListener; this.ssaIdTransformer = new SsaIdentifierTransformer(ssa); this.evalCtx = new SsaEvaluationContext(arch, ssa.Identifiers, importResolver); this.eval = new ExpressionSimplifier(segmentMap, evalCtx, eventListener); }
public TrashedRegisterFinder( Program program, ProgramDataFlow flow, IEnumerable <SsaTransform> sccGroup, DecompilerEventListener listener) { this.arch = program.Architecture; this.segmentMap = program.SegmentMap; this.flow = flow; this.sccGroup = sccGroup.ToHashSet(); this.callGraph = program.CallGraph; this.listener = listener; this.cmp = new ExpressionValueComparer(); this.worklist = new WorkStack <Block>(); this.ssas = sccGroup.ToDictionary(s => s.SsaState.Procedure, s => s.SsaState); }
public Set <CGNode> NodesOutgoingSCC(CallGraph scc) { Set <CGNode> nodes = new Set <CGNode>(); foreach (CGNode n in scc.cgNodes) { Set <CGNode> adj = this.calls.Successors(n); foreach (CGNode succ in adj) { if (scc.cgNodes.Contains(succ)) { nodes.Add(succ); } } } return(nodes); }
/// <summary> /// calling graph is prepared for update contract code (check for DAG at that time) /// </summary> /// <param name="edges"></param> /// <returns></returns> /// <exception cref="FunctionMetadataException"></exception> private CallGraph BuildCallingGraph(SerializedCallGraph callGraph) { CallGraph graph = new CallGraph(); graph.AddVertexRange(callGraph.Vertices); graph.AddEdgeRange(callGraph.Edges.Select(serializedEdge => new Edge <string>(serializedEdge.Source, serializedEdge.Target))); try { graph.TopologicalSort(); } catch (NonAcyclicGraphException) { throw new FunctionMetadataException("The calling graph ISNOT DAG when restoring the calling graph according to the ContractMetadataTemplateMap from the database"); } return(graph); }
public static bool SetModifies(List <Declaration> program, CallGraph cg) { foreach (var decl in program) { var p = decl as Procedure; if (p != null) { var cgNode = cg.NodeOfName(p.Name); if (cgNode == null) { Log.Out(Log.Error, "No callgraph node found for " + p.Name + "!"); return(true); } p.Modifies = U.IdentifierExprSeqOfVariableSeq(cgNode.WriteSetGlobals.ToVariableSeq()); } } return(false); }
public void VisitGraph(CallGraph graph) { m_graph = graph; // If the assembly is mixed transparent/critical then we may have critical // methods. if (m_mixed) { List <string> lines = new List <string>(); // So, for each method, foreach (KeyValuePair <MethodReference, List <MethodReference> > entry in graph.Entries()) { MethodInfo caller = Cache.FindMethod(entry.Key); if (caller != null) { // if it's public, MethodAttributes access = caller.Method.Attributes & MethodAttributes.MemberAccessMask; if (access == MethodAttributes.Public) { // and transparent, if (!caller.Method.CustomAttributes.Has("SecurityCriticalAttribute")) { // then fail if it calls a non-public critical method. string line = DoIsBad(caller.Method, entry.Value, 1); if (line.Length > 0) { lines.Add(line); } } } } } if (lines.Count > 0) { string details = string.Join(Environment.NewLine, lines.ToArray()); // Console.WriteLine(details); Reporter.AssemblyFailed(Cache.Assembly, CheckID, details); } } }
public static void TestCallGraph(string xmlArchive, List<Tuple<string,string,bool>> testData) { CallGraph callGraph; var dbName = SrcMLDataContext.MakeDBName(xmlArchive); SrcMLDataContext.DropUserInstanceDatabase(dbName); var sw = Stopwatch.StartNew(); using (var db = SrcMLDataContext.CreateDatabaseConnection(dbName)) { callGraph = new CallGraph(xmlArchive, db); } sw.Stop(); Assert.IsNotNull(callGraph); Console.WriteLine("{0} to build the call graph", sw.Elapsed); List<bool> statuses = new List<bool>(); foreach (var test in testData) { var caller = test.Item1; var callee = test.Item2; var expected = test.Item3; var should = test.Item3 ? "should" : "shouldn't"; Console.Write("{0} {1} call {2}: ", caller, should, callee); var status = (expected == callGraph.ContainsRelationship(caller, callee)); statuses.Add(status); Console.WriteLine(status ? "PASS" : "FAIL"); Console.Write("{0} {1} be in the caller list for {2}: ", callee, should, callee); status = (expected == callGraph.GetCallers(callee).Any(c => (c.CallerDefinition as MethodDefinition).MethodSignature == caller)); statuses.Add(status); Console.WriteLine(status ? "PASS" : "FAIL"); Console.Write("{0} {1} be in the callee list for {2}: ", callee, should, caller); status = (expected == callGraph.GetCallees(caller).Any(c => (c.CalleeDefinition as MethodDefinition).MethodSignature == callee)); statuses.Add(status); Console.WriteLine(status ? "PASS" : "FAIL"); Console.WriteLine(); } Assert.IsTrue(statuses.All(s => s)); }
public async Task <CallGraph <MethodDescriptor, LocationDescriptor> > GenerateCallGraphAsync() { Logger.LogS("SolutionAnalyzer", "GenerateCallGraphAsync", "Start building CG"); var callgraph = new CallGraph <MethodDescriptor, LocationDescriptor>(); var roots = await this.SolutionManager.GetRootsAsync(this.RootKind); var worklist = new Queue <MethodDescriptor>(roots); var visited = new HashSet <MethodDescriptor>(); callgraph.AddRootMethods(roots); while (worklist.Count > 0) { var currentMethodDescriptor = worklist.Dequeue(); visited.Add(currentMethodDescriptor); Logger.LogS("SolutionAnalyzer", "GenerateCallGraphAsync", "Proccesing {0}", currentMethodDescriptor); var methodEntity = await this.SolutionManager.GetMethodEntityAsync(currentMethodDescriptor); var calleesInfoForMethod = await methodEntity.GetCalleesInfoAsync(); foreach (var entry in calleesInfoForMethod) { var analysisNode = entry.Key; var callees = entry.Value; foreach (var calleeDescriptor in callees) { Logger.LogS("SolutionAnalyzer", "GenerateCallGraphAsync", "Adding {0}-{1} to CG", currentMethodDescriptor, calleeDescriptor); callgraph.AddCallAtLocation(analysisNode.LocationDescriptor, currentMethodDescriptor, calleeDescriptor); if (!visited.Contains(calleeDescriptor) && !worklist.Contains(calleeDescriptor)) { worklist.Enqueue(calleeDescriptor); } } } } return(callgraph); }
private Set <CallGraph> BFSTranspose(Dictionary <int, CGNode> nodesOrder) { Set <CallGraph> cgs = new Set <CallGraph>(); List <CGNode> qeue = new List <CGNode>(); Set <CGNode> visited = new Set <CGNode>(); int cNodes = nodesOrder.Count; for (int i = cNodes - 1; i >= 0; i--) { CGNode n = nodesOrder[i]; CallGraph cg = new CallGraph(); if (!visited.Contains(n)) { qeue.Add(n); visited.Add(n); while (qeue.Count > 0) { CGNode mn = qeue[0]; visited.Add(mn); cg.AddNode(mn); qeue.RemoveAt(0); foreach (CGEdge e in calls.EdgesTo(mn)) { if (!visited.Contains(e.Src)) { visited.Add(e.Src); // DIEGO-CHECK: I dont remember why I inverted this cg.AddEdge(new CGEdge(e.Dst, e.Label, e.Src, e.IsVirtual)); qeue.Add(e.Src); } } } } if (cg.cgNodes.Count > 1) { cgs.Add(cg); } } return(cgs); }
private void OnSelectionChanged(object sender, SelectionEventArgs args) { if (args.definition is MethodDefinition) { CGPrettyPrinter.PrintPretty(args.definition, textView); CGPrettyDrawer drawer = new CGPrettyDrawer(drawingArea); var builder = new CallGraphBuilder(args.definition as MethodDefinition); CallGraph currentCg = builder.Create(2); drawer.DrawCallGraph(currentCg); if (args.module != null) { // Dump the module if (args.assembly != null) { // Dump assembly modules. } } } }
private bool DoFoundBadSetter(CallGraph graph, MethodReference method, List <string> chain) { if (m_visited.IndexOf(method) >= 0) { return(false); } m_visited.Add(method); bool found = false; Log.DebugLine(this, "checking {0}", method); if (m_unlocked.IndexOf(method) >= 0 && m_setters.IndexOf(method) >= 0) { Log.DebugLine(this, "it's a setter"); found = true; } else { foreach (MethodReference callee in graph.Calls(method)) { Log.Indent(); if (DoFoundBadSetter(graph, callee, chain)) { found = true; Log.Unindent(); break; } Log.Unindent(); } } if (found) { chain.Insert(0, method.ToString()); } return(found); }
public bool ShouldCheckMethod(Method method) { Queue <Method> MethodsToCheck = new Queue <Method>(); List <Method> MethodsChecked = new List <Method>(); MethodsToCheck.Enqueue(method); while (MethodsToCheck.Count != 0) { Method MethodToCheck = MethodsToCheck.Dequeue(); if (!MethodsChecked.Contains(MethodToCheck) && MethodToCheck != null) { /*if (IsSubClassOf(MethodToCheck.DeclaringType, "Microsoft.Xna.Framework.Game") && * MethodsToCheckNames.Contains(MethodToCheck.Name.Name)) * { * return true; * }*/ foreach (var attribute in MethodToCheck.Attributes.Union(MethodToCheck.DeclaringType.Attributes)) { if (attribute.Type != null && attribute.Type.FullName == "GridEngine.Components.Debugging.Attributes.FxCop.PerformanceCriticalAttribute") { return(true); } } // Add methods up the class tree MethodsToCheck.Enqueue(MethodToCheck.OverriddenMethod); MethodsToCheck.Enqueue(MethodToCheck.HiddenMethod); // Add calling methods foreach (var CallingMethod in CallGraph.CallersFor(MethodToCheck)) { MethodsToCheck.Enqueue(CallingMethod); } } MethodsChecked.Add(MethodToCheck); } return(false); }
public void VisitCallGraph(CallGraph graph) { foreach (KeyValuePair <TypeDefinition, Entry> entry1 in m_table) { foreach (KeyValuePair <Source, List <MethodReference> > entry2 in entry1.Value.Calls) { foreach (MethodReference method in entry2.Value) { List <string> chain = new List <string>(); chain.Add(entry2.Key.Method.ToString()); if (DoCallsLock(method, entry2.Key.Field, entry1.Value, graph, chain, 0)) { string details = "Field: " + entry2.Key.Field.Name + Environment.NewLine; details += "Calls: " + string.Join(" =>" + Environment.NewLine + " ", chain.ToArray()); Log.DebugLine(this, details); Reporter.TypeFailed(entry1.Key, CheckID, details); } } } } }
public static CallGraph ComputeAnalyzableMethods(Node node, PointsToAnalysis ptwe) { Set <AssemblyNode> assemblies = new Set <AssemblyNode>(); // AnalyzableMethodFinder amf = new AnalyzableMethodFinder(node,); AnalyzableMethodFinder amf = new AnalyzableMethodFinder(ptwe); if (node is AssemblyNode) { AssemblyNode assemblyNode = (AssemblyNode)node; amf.assemblies.Add(node); foreach (AssemblyReference reference in assemblyNode.AssemblyReferences) { amf.assemblies.Add(reference.Assembly); } } amf.Visit(node); /* * foreach (AssemblyNode an in amf.assemblies) * { * Console.Out.WriteLine("*ENTRE*"); * amf.Visit(an); * } */ // amf.Visit(node); if (PointsToAnalysis.verbose) { Set <CallGraph> cgs; cgs = new Set <CallGraph>(); cgs.Add(amf.cg); CallGraph.GenerateDotGraph(Console.Out, cgs); } return(amf.cg); }
public void VisitCalls(CallGraph graph) { if (!m_disabled) { string details = string.Empty; IEnumerable <MethodReference> roots = m_dispatcher.ClassifyMethod.ThreadRoots(); details += DoCheckForUnmarkedRoots(roots); if (m_knownRoots.Count > 0) { details += DoCheckForUnsafeMethods(graph); } details += DoCheckForBadSafe(roots); details += DoCheckForBadSafeTypes(); details = details.Trim(); if (details.Length > 0) { Log.DebugLine(this, "Details: {0}", details); Reporter.AssemblyFailed(Cache.Assembly, CheckID, details); } } }
/// <summary> /// try to get /// (1) local calling graph, where only local function calls are considered /// (2) process function order ( reverse order of topological order of the calling graph) /// (3) external function call list for every function /// </summary> /// <param name="callGraph"></param> /// <param name="topologicRes"></param> private void TrySetLocalCallingGraph(out CallGraph callGraph, out IEnumerable <string> topologicRes) { callGraph = new CallGraph(); foreach (var kvPair in MethodMetadataTemplates) { callGraph.AddVertex(kvPair.Key); foreach (var calledFunc in kvPair.Value.CallingSet) { if (calledFunc.StartsWith(Replacement.This)) { callGraph.AddVerticesAndEdge(new Edge <string>(kvPair.Key, calledFunc)); } else { if (!ExternalFuncCall.TryGetValue(kvPair.Key, out var callingList)) { callingList = new List <string>(); ExternalFuncCall.Add(kvPair.Key, callingList); } callingList.Add(calledFunc); } } } try { topologicRes = callGraph.TopologicalSort(); } catch (NonAcyclicGraphException) { callGraph.Clear(); callGraph = null; topologicRes = null; throw new FunctionMetadataException($"Calling graph of contract {FullName} is Non-DAG thus nothing take effect"); } }
private void DoSetChains(string root, MethodDefinition caller, CallGraph graph, List <MethodDefinition> chain, bool multiple, int depth) { // if (depth > 12) // this can't be too large or the rule takes a very long time to run // return false; // For each method the caller calls, IEnumerable <MethodReference> callees = graph.GetCalls(caller); if (callees != null) { foreach (MethodReference callee in callees) { // if it's a method in the assembly we're testing, MethodState state; if (m_methods.TryGetValue(callee, out state)) { // and we haven't already called it from our root, if (!state.IsCalledFrom(root)) { // then update it's call chain and update all the methods it calls. List <MethodDefinition> schain = new List <MethodDefinition>(chain.Count + 1); schain.AddRange(chain); schain.Add(state.Method); state.SetCallChain(root, schain, multiple); DoSetChains(root, state.Method, graph, schain, multiple, depth + 1); if (m_requiredSafeTypes.IndexOf(state.Method.DeclaringType) < 0) { m_requiredSafeTypes.Add(state.Method.DeclaringType); } } } } } }
public void Traverse(CallGraph cgraph, Procedure rootProc) { var q = new Queue<Procedure>(); q.Enqueue(rootProc); while (q.Count > 0) { var proc = q.Dequeue(); if (visited.Contains(proc)) continue; visited.Add(proc); Debug.Print("Node {0}", proc.Name); visited.Add(proc); Render(proc); foreach (var pred in cgraph.CallerProcedures(proc).Where(p => p != rootProc)) { Debug.Print("Edge {0} - {1}", pred.Name, proc.Name); graph.AddEdge(pred.Name, proc.Name); } foreach (var succ in cgraph.Callees(proc)) { q.Enqueue(succ); } } }
internal static SyntaxNode GenerateCode(CallGraph<string,int> callgraph) { List<MethodDeclarationSyntax> methods = new List<MethodDeclarationSyntax>(); foreach (var vertex in callgraph.GetNodes()) { methods.Add(GetMethod(vertex, callgraph.GetCallees(vertex))); } //methods.Add(GetMain(callgraph.GetNodes())); return SyntaxFactory.CompilationUnit() .WithMembers( SyntaxFactory.SingletonList<MemberDeclarationSyntax>( SyntaxFactory.ClassDeclaration( @"C") .WithMembers( SyntaxFactory.List<MemberDeclarationSyntax>(methods) ))) .NormalizeWhitespace(); }
internal static CallGraph<string, int> GenerateCallGraph(int n) { var result = new CallGraph<string,int>(); for (var i = 0; i < n; i++) { result.Add(string.Format("N{0}", i)); } // now generate the edges var rand = new Random(); for (var i = 0; i < 5 * n; i++) { var source = rand.Next(n - 1); var dest = rand.Next(n - 1); result.AddCall(string.Format("N{0}", source), string.Format("N{0}", dest)); } result.Add("Main"); result.AddRootMethod("Main"); foreach (var method in result.GetNodes()) { result.AddCall("Main", method); } return result; }
public CallGraph<MethodDescriptor, LocationDescriptor> GenerateCallGraph() { var roots = ProjectCodeProvider.GetMainMethods(this.Solution); Contract.Assert(this.Dispatcher != null); //Contract.Assert(this.Dispatcher.GetAllEntites() != null); var callgraph = new CallGraph<MethodDescriptor, LocationDescriptor>(); callgraph.AddRootMethods(roots); // var allEntities = new HashSet<IEntity>(this.Dispatcher.GetAllEntites()); var allEntityDescriptors =this.Dispatcher.GetAllEntitiesDescriptors(); foreach (var entityDesc in allEntityDescriptors) { // entity.GetEntityProcessor(this.Dispatcher); //var entityProcessor = new MethodEntityProcessor((MethodEntity)entity, this.Dispatcher); var entityProcessor = this.Dispatcher.GetEntityWithProcessor(entityDesc); // Updates the callGraph UpdateCallGraph(entityProcessor, callgraph,this.Solution); MethodEntity methodEntity = (MethodEntity) entityProcessor.Entity; methodEntity.Save(Path.Combine(Path.GetTempPath(), methodEntity.MethodDescriptor.ClassName + "_" + methodEntity.MethodDescriptor.Name + ".dot")); } //callgraph.Save("cg.dot"); return callgraph; }
private static CallGraph<MethodDescriptor, LocationDescriptor> ReBuildCallGraph(Dispatcher dispatcher, Solution solution) { var callgraph = new CallGraph<MethodDescriptor, LocationDescriptor>(); // pg.PropagateDeletionOfNodes(); foreach (var e in dispatcher.GetAllEntites()) { var entityProcessor = new MethodEntityProcessor((MethodEntity)e, dispatcher);// e.GetEntityProcessor(dispatcher); var methodEntity = (MethodEntity)entityProcessor.Entity; if (methodEntity.MethodDescriptor.ToString().Contains("Main")) { callgraph.AddRootMethod(methodEntity.MethodDescriptor); } // Updates the callGraph UpdateCallGraph(entityProcessor, callgraph, solution); } //callgraph.Save("cg_d.dot"); return callgraph; }
internal bool IsCaller(MethodDescriptor callerDescriptor, MethodDescriptor calleeDescriptor, CallGraph<MethodDescriptor, LocationDescriptor> callgraph) { return callgraph.GetCallers(calleeDescriptor).Select(kp => kp.Value).Contains(callerDescriptor); }
/* private ProjectMethod FindMethodSymbolAndProjectInSolution(MethodDescriptor methodDescriptor, CallGraph<MethodDescriptor, ALocation> callgraph) { return RoslynSymbolFactory.FindMethodSymbolAndProjectInSolution(this.Solution, methodDescriptor); } #region Just a test to discard about programation of a deletion o a croncrete type internal void RemoveTypesFromNode(MethodDescriptor methodDescriptor, string text) { var m = RoslynSymbolFactory.FindMethodSymbolInSolution(this.Solution, methodDescriptor); var am = new AMethod(m); var entityProcessor = (MethodEntityProcessor<ANode, AType, AMethod>) this.Dispatcher.GetEntityWithProcessor(EntityFactory<AMethod>.Create(am)); var entity = entityProcessor.MethodEntity; var pg = entity.PropGraph; ANode n = pg.FindNodeInPropationGraph(text); var statementProcessor = new StatementProcessor<ANode, AType, AMethod>(am, entity.ReturnVariable, entity.ThisRef, entity.ParameterNodes, pg); statementProcessor.RegisterRemoveNewExpressionAssignment(n); // entity.RemoveCallees(); entityProcessor.DoDelete(); //entity.InvalidateCaches(); } internal void RemoveAsignment(MethodDescriptor methodDescriptor, string p1, string p2) { var roslynMethod = RoslynSymbolFactory.FindMethodSymbolInSolution(this.Solution, methodDescriptor); var aMethod = new AMethod(roslynMethod); var entityProcessor = this.Dispatcher.GetEntityWithProcessor( EntityFactory<AMethod>.Create(aMethod)) as MethodEntityProcessor<ANode, AType, AMethod>; var entity = entityProcessor.MethodEntity; var syntaxNode = Utils.FindMethodDeclaration(aMethod); var nodes = syntaxNode.DescendantNodes().OfType<AssignmentExpressionSyntax>(); var node = nodes.First(a => a.Left.ToString() == p1 && a.Right.ToString() == p2); ANode lhs = entity.PropGraph.FindNodeInPropationGraph(p1); ANode rhs = entity.PropGraph.FindNodeInPropationGraph(p2); var statementProcessor = new StatementProcessor<ANode, AType, AMethod>(aMethod, entity.ReturnVariable, entity.ThisRef, entity.ParameterNodes, entity.PropGraph); statementProcessor.RegisterRemoveAssignment(lhs, rhs); entityProcessor.DoDelete(); //entity.InvalidateCaches(); } /// <summary> /// A test of how we should proceed when a method is modified /// </summary> /// <param name="methodDescriptor"></param> /// <param name="newCode"></param> internal void UpdateMethod(MethodDescriptor methodDescriptor, string newCode, CallGraph<MethodDescriptor, ALocation> callgraph) { // Find the method and project of the method to be updated var projectMethdod = FindMethodSymbolAndProjectInSolution(methodDescriptor, callgraph); var oldRoslynMethod = projectMethdod.Method; var project = projectMethdod.Project; var aMethod = new AMethod(oldRoslynMethod); //entityProcessor.MethodEntity.Save(roslynMethod.ContainingType.Name + "_" + roslynMethod.Name + "_orig.dot"); //-------------------------------------------------------------------------------------------------------- // This is to mimic a change in the method. We need to create a new comp var methodDecSyntax = Utils.FindMethodDeclaration(aMethod); var newMethodBody = SyntaxFactory.ParseStatement(newCode) as BlockSyntax; // here we update the method body var newMethodSyntax = methodDecSyntax.WithBody(newMethodBody); // This is a trick to recover the part of the syntax tree after replacing the project syntax tree var annotation = new SyntaxAnnotation("Hi"); newMethodSyntax = newMethodSyntax.WithAdditionalAnnotations(annotation); // update the syntax tree var oldRoot = methodDecSyntax.SyntaxTree.GetRoot(); var newRoot = oldRoot.ReplaceNode(methodDecSyntax, newMethodSyntax); // Compute the new compilation and semantic model var oldCompilation = project.GetCompilationAsync().Result; var newCompilation = oldCompilation.ReplaceSyntaxTree(oldRoot.SyntaxTree, newRoot.SyntaxTree); var newSemanticModel = newCompilation.GetSemanticModel(newRoot.SyntaxTree); // Recover the method node var recoveredMethodNode = newRoot.GetAnnotatedNodes(annotation).Single(); ////////////////////////////////////////////////////// // Get the entity corresponding to the new (updated) method var updatedRoslynMethod = newSemanticModel.GetDeclaredSymbol(recoveredMethodNode) as IMethodSymbol; PerformUpdate(oldRoslynMethod, newSemanticModel, updatedRoslynMethod); } public void PerformUpdate(IMethodSymbol oldRoslynMethod, SemanticModel newSemanticModel, IMethodSymbol newRoslynMethod) { var aMethod = new AMethod(oldRoslynMethod); // Get the entity and processor var entityDescriptor = EntityFactory<AMethod>.Create(aMethod); var entityProcessor = this.Dispatcher.GetEntityWithProcessor(entityDescriptor) as MethodEntityProcessor<ANode, AType, AMethod>; var oldMethodEntity = entityProcessor.MethodEntity; var syntaxProcessor = new MethodSyntaxProcessor(newRoslynMethod, newSemanticModel, Dispatcher); var newEntity = syntaxProcessor.ParseMethod() as MethodEntity<ANode, AType, AMethod>; // I propagate the removal of the node that represent the input parameters of the callees // This is to simulate the deletion of the method. // Do I need to do this? var propGraphOld = oldMethodEntity.PropGraph; var invoOld = GetInvocations(propGraphOld); foreach (var invocation in invoOld) { foreach (var aCallee in invocation.ComputeCalleesForNode(propGraphOld)) { RemoveCall(aCallee,invocation); } } // This is to force the callers to call me //foreach(var callerConext in entity.Callers) //{ // var caller = callerConext.Caller; // var callerEntityProcessor = Dispatcher.GetEntityWithProcessor(new MethodEntityDescriptor<AMethod>(caller)); // callerEntityProcessor.DoAnalysis(); //} // Here we propagate the removal of the retvalue of the method we eliminate if (oldMethodEntity.ReturnVariable != null) { var returnTypes = oldMethodEntity.GetTypes(oldMethodEntity.ReturnVariable); foreach (var callersContext in oldMethodEntity.Callers) { RemoveReturnValuesFromCallerLHS(returnTypes, callersContext.Caller, callersContext.CallLHS); } } this.Dispatcher.RegisterEntity(entityDescriptor, newEntity); // I get an entity processor to analyze the new entity var newEntityProcessor = Dispatcher.GetEntityWithProcessor(entityDescriptor) as MethodEntityProcessor<ANode, AType, AMethod>; /// I need to copy all the input data from the old method newEntity.CopyInterfaceDataAndCallers(oldMethodEntity); newEntityProcessor.DoAnalysis(); var propGraphNew = newEntity.PropGraph; var invoNew = GetInvocations(propGraphNew); //newEntityProcessor.MethodEntity.Save(oldRoslynMethod.ContainingType.Name + "_" + oldRoslynMethod.Name + "_d.dot"); oldMethodEntity.InvalidateCaches(); } private void RemoveReturnValuesFromCallerLHS(ISet<AType> returnTypes, AMethod aCaller, ANode lhs) { var entityProcessorforCaller = (MethodEntityProcessor<ANode, AType, AMethod>) Dispatcher.GetEntityWithProcessor(EntityFactory<AMethod>.Create((AMethod)aCaller)); var callerEntity = entityProcessorforCaller.MethodEntity; var statementProcessor = new StatementProcessor<ANode, AType, AMethod>((AMethod)aCaller, callerEntity.ReturnVariable, callerEntity.ThisRef, callerEntity.ParameterNodes, callerEntity.PropGraph); //callerEntity.PropGraph. statementProcessor.RegisterRemoveTypes(lhs, returnTypes); //callerEntity.InvalidateCaches(); entityProcessorforCaller.DoDelete(); } private void RemoveCall(AMethod aCallee, AInvocationExp<AMethod,AType,ANode> invocation) { var entityProcessorforCallee = Dispatcher.GetEntityWithProcessor(EntityFactory<AMethod>.Create((AMethod)aCallee)) as MethodEntityProcessor<ANode, AType, AMethod>; var calleeEntity = entityProcessorforCallee.MethodEntity; calleeEntity.InvalidateCaches(); // Delete progragation of arguments and receiver var statementProcessor = new StatementProcessor<ANode, AType, AMethod>((AMethod)aCallee, calleeEntity.ReturnVariable, calleeEntity.ThisRef, calleeEntity.ParameterNodes, calleeEntity.PropGraph); foreach (var p in calleeEntity.ParameterNodes) { statementProcessor.RegisterRemoveNewExpressionAssignment(p); } if (calleeEntity.ThisRef != null) statementProcessor.RegisterRemoveNewExpressionAssignment(calleeEntity.ThisRef); // entity.RemoveCallees(); entityProcessorforCallee.DoDelete(); var context = new CallConext<AMethod, ANode>(invocation.Caller,invocation.LHS,invocation.CallNode); calleeEntity.RemoveFromCallers(context); } private static List<AInvocationExp<AMethod, AType, ANode>> GetInvocations(PropagationGraph<ANode, AType, AMethod> propGraphOld) { var invoList = new List<AInvocationExp<AMethod, AType, ANode>>(); foreach (var oldCall in propGraphOld.CallNodes) { var oldCallInfo = propGraphOld.GetInvocationInfo(oldCall); invoList.Add(oldCallInfo); } return invoList; } #endregion */ #region Callgraph private static void UpdateCallGraph(IEntityProcessor entityProcessor, CallGraph<MethodDescriptor, LocationDescriptor> callgraph, Solution solution) { Contract.Assert(entityProcessor != null); var methodEntity = (MethodEntity)entityProcessor.Entity; Contract.Assert(methodEntity.MethodDescriptor != null); var callerMethod = methodEntity.MethodDescriptor; var pair = ProjectCodeProvider.GetProjectProviderAndSyntaxAsync(callerMethod, solution).Result; if (pair != null) { var codeProvider = pair.Item1; // Hack var methodEntityProcessor = new MethodEntityProcessor(methodEntity, ((MethodEntityProcessor)entityProcessor).dispatcher, codeProvider); //(MethodEntityProcessor)entityProcessor; var callSitesForMethod = methodEntityProcessor.GetCalleesInfo(); foreach (var callSiteNode in callSitesForMethod.Keys) { foreach (var calleeAMethod in callSitesForMethod[callSiteNode]) { //var callee = Utils.FindMethodSymbolDeclaration(this.Solution, ((AMethod)calleeAMethod).RoslynMethod); var callee = calleeAMethod; Logger.Instance.Log("SolutionAnalyzer", "UpdateCallGraph", "\t-> {0}", callee); callgraph.AddCallAtLocation(callSiteNode.LocationDescriptor, callerMethod, callee); } } } }
internal bool IsCalled(MethodDescriptor methodDescriptor, MethodDescriptor calleeDescriptor, CallGraph<MethodDescriptor, LocationDescriptor> callgraph) { return callgraph.GetCallees(methodDescriptor).Contains(calleeDescriptor); }
internal ISet<MethodDescriptor> GetReachableMethods(CallGraph<MethodDescriptor, LocationDescriptor> callgraph) { return callgraph.GetReachableMethods(); }
/// <summary> /// Checks if a method is reachbable /// </summary> /// <param name="methodDescriptor"></param> /// <returns></returns> internal bool IsReachable(MethodDescriptor methodDescriptor, CallGraph<MethodDescriptor, LocationDescriptor> callgraph) { //var method = FindMethodSymbolInSolution(methodDescriptor).Method; //return method != null && Callgraph.GetReachableMethods().Contains(method); // ,new Compare()); return callgraph.GetReachableMethods().Contains(methodDescriptor); }
public static IEnumerable<Result> Check (Document input) { var unit = input != null ? input.ParsedDocument.LanguageAST as ICSharpCode.NRefactory.CSharp.CompilationUnit : null; if (unit == null) return Enumerable.Empty<Result> (); var cg = new CallGraph (); cg.Inspect (input, input.GetResolver (), unit); var data = new InspectionData () { Graph = cg, Document = input }; unit.AcceptVisitor (visitor, data); return data.Results; }
private void Dump(CallGraph cg) { var sw = new StringWriter(); cg.Write(sw); Debug.Print("{0}", sw.ToString()); }
public void Setup() { this.arch = new FakeArchitecture(new ServiceContainer()); this.procCalling = new ProcedureBuilder(arch, "procCalling").Procedure; this.callgraph = new CallGraph(); }
public void Setup() { this.arch = new FakeArchitecture(); this.procCalling = new ProcedureBuilder(arch, "procCalling").Procedure; this.callgraph = new CallGraph(); }