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); }
public void BlockCloner_CloneCall() { var call = new CallInstruction(new ProcedureConstant(arch.PointerType, procCalling), new CallSite(0, 0)); var block = new Block(procCalling, "test"); var stmOld = new Statement(42, call, block); callgraph.AddStatement(stmOld); callgraph.AddProcedure(procCalling); callgraph.AddEdge(stmOld, procCalling); var cloner = new BlockCloner(null, procCalling, callgraph); cloner.Statement = stmOld; cloner.StatementNew = new Statement(42, null, block); var newCall = (CallInstruction)call.Accept(cloner); cloner.StatementNew.Instruction = newCall; Assert.AreEqual(call.Callee, newCall.Callee); Assert.AreEqual(2, callgraph.CallerStatements(procCalling).Count(), "Should've added a call to the callgraph"); Assert.AreEqual(1, callgraph.Callees(cloner.Statement).Count()); Assert.AreEqual(1, callgraph.Callees(cloner.StatementNew).Count()); }
public bool EnqueueRoutine(IPhpRoutineSymbol routine, T caller, BoundRoutineCall callExpression) { Contract.ThrowIfNull(routine); if (routine.ControlFlowGraph == null) { var routine2 = routine is SynthesizedMethodSymbol sr ? sr.ForwardedCall : routine.OriginalDefinition as IPhpRoutineSymbol; if (routine2 != null && !ReferenceEquals(routine, routine2)) { return(EnqueueRoutine(routine2, caller, callExpression)); } // library (sourceless) function return(false); } var sourceRoutine = (SourceRoutineSymbol)routine; if (sourceRoutine.SyntaxReturnType != null) { // we don't have to wait for return type, // nor reanalyse itself when routine analyses return(false); } _callGraph.AddEdge(caller.FlowState.Routine, sourceRoutine, new CallSite(caller, callExpression)); // ensure caller is subscribed to routine's ExitBlock ((ExitBlock)routine.ControlFlowGraph.Exit).Subscribe(caller); // TODO: check if routine has to be reanalyzed => enqueue routine's StartBlock // Return whether the routine exit block will certainly be analysed in the future return(!sourceRoutine.IsReturnAnalysed); }
public Instruction VisitCallInstruction(CallInstruction ci) { var oldCallee = ci.Callee; ci.Callee = ci.Callee.Accept(eval); if (ci.Callee is ProcedureConstant pc) { if (pc.Procedure.Signature.ParametersValid) { var sig = pc.Procedure.Signature; var chr = pc.Procedure.Characteristics; RewriteCall(stmCur, ci, sig, chr); return(stmCur.Instruction); } if (oldCallee != pc && pc.Procedure is Procedure procCallee) { // This was an indirect call, but is now a direct call. // Make sure the call graph knows about the link between // this statement and the callee. callGraph.AddEdge(stmCur, procCallee); } } return(ci); }