@Test public void testSystemProperties() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope( TestConstants.WALA_TESTDATA, CallGraphTestUtil.REGRESSION_EXCLUSIONS); ClassHierarchy cha = ClassHierarchy.make(scope); Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints( scope, cha, "LstaticInit/TestSystemProperties"); AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints); SSAPropagationCallGraphBuilder builder = Util.makeZeroCFABuilder(options, new AnalysisCache(), cha, scope); CallGraph cg = builder.makeCallGraph(options); for (CGNode n : cg) { if (n.toString() .equals( "Node: < Application, LstaticInit/TestSystemProperties, main([Ljava/lang/String;)V > Context: Everywhere")) { boolean foundToCharArray = false; for (CGNode callee : Iterator2Iterable.make(cg.getSuccNodes(n))) { if (callee.getMethod().getName().toString().equals("toCharArray")) { foundToCharArray = true; break; } } Assert.assertTrue(foundToCharArray); break; } } }
private void addParamEdges(LocalPointerKey pk, CGNode node) { // get parameter position: value number - 1? int paramPos = pk.getValueNumber() - 1; // iterate over callers for (CGNode caller : cg) { // TODO we don't need to add the graph if null is passed // as the argument addSubgraphForNode(caller); IR ir = caller.getIR(); for (Iterator<CallSiteReference> iterator = ir.iterateCallSites(); iterator.hasNext(); ) { CallSiteReference call = iterator.next(); if (cg.getPossibleTargets(caller, call).contains(node)) { SSAAbstractInvokeInstruction[] callInstrs = ir.getCalls(call); for (int i = 0; i < callInstrs.length; i++) { SSAAbstractInvokeInstruction callInstr = callInstrs[i]; PointerKey actualPk = heapModel.getPointerKeyForLocal(caller, callInstr.getUse(paramPos)); assert containsNode(actualPk); assert containsNode(pk); addEdge(pk, actualPk); } } } } }
public void addSubgraphForNode(CGNode node) { int n = cg.getNumber(node); if (!cgNodesVisited.contains(n)) { cgNodesVisited.add(n); unconditionallyAddConstraintsFromNode(node); addNodesForParameters(node); } }
/** @param pk value being def'fed by a call instruction (either normal or exceptional) */ private void addReturnEdges(LocalPointerKey pk, SSAInvokeInstruction callInstr) { boolean isExceptional = pk.getValueNumber() == callInstr.getException(); // get call targets Collection<CGNode> possibleCallees = cg.getPossibleTargets(pk.getNode(), callInstr.getCallSite()); // construct graph for each target for (CGNode callee : possibleCallees) { addSubgraphForNode(callee); PointerKey retVal = isExceptional ? heapModel.getPointerKeyForExceptionalReturnValue(callee) : heapModel.getPointerKeyForReturnValue(callee); assert containsNode(retVal); addEdge(pk, retVal); } }
private void createActualInAndOut( final Map<PDGNode, Node> pdg2cfg, final ModRefCandidates modref, final PDG pdg, final CallGraph cg) { for (final PDGNode call : pdg.getCalls()) { final Node cn = pdg2cfg.get(call); final SSAInvokeInstruction invk = (SSAInvokeInstruction) pdg.getInstruction(call); final CallSiteReference site = invk.getCallSite(); final Set<ModRefFieldCandidate> modRefCands = new HashSet<ModRefFieldCandidate>(); for (final CGNode tgt : cg.getPossibleTargets(pdg.cgNode, site)) { final InterProcCandidateModel tgtModRef = modref.getCandidates(tgt); if (tgtModRef == null) { continue; } for (final ModRefFieldCandidate c : tgtModRef) { modRefCands.add(c); } } final List<ModRefFieldCandidate> refs = new LinkedList<ModRefFieldCandidate>(); final List<ModRefFieldCandidate> mods = new LinkedList<ModRefFieldCandidate>(); for (final ModRefFieldCandidate c : modRefCands) { if (c.isMod()) { mods.add(c); } if (c.isRef()) { refs.add(c); } } addNodesBefore(cn, refs, Node.Kind.ACTUAL_IN); addNodesAfter(cn, mods, Node.Kind.ACTUAL_OUT); } }
private static List<Pair<CGNode, SSACheckCastInstruction>> findFailingCasts( CallGraph cg, DemandRefinementPointsTo dmp) { final IClassHierarchy cha = dmp.getClassHierarchy(); List<Pair<CGNode, SSACheckCastInstruction>> failing = new ArrayList<Pair<CGNode, SSACheckCastInstruction>>(); int numSafe = 0, numMightFail = 0; outer: for (Iterator<? extends CGNode> nodeIter = cg.iterator(); nodeIter.hasNext(); ) { CGNode node = nodeIter.next(); TypeReference declaringClass = node.getMethod().getReference().getDeclaringClass(); // skip library classes if (declaringClass.getClassLoader().equals(ClassLoaderReference.Primordial)) { continue; } IR ir = node.getIR(); if (ir == null) continue; SSAInstruction[] instrs = ir.getInstructions(); for (int i = 0; i < instrs.length; i++) { if (numSafe + numMightFail > MAX_CASTS) break outer; SSAInstruction instruction = instrs[i]; if (instruction instanceof SSACheckCastInstruction) { SSACheckCastInstruction castInstr = (SSACheckCastInstruction) instruction; final TypeReference[] declaredResultTypes = castInstr.getDeclaredResultTypes(); boolean primOnly = true; for (TypeReference t : declaredResultTypes) { if (!t.isPrimitiveType()) { primOnly = false; } } if (primOnly) { continue; } System.err.println("CHECKING " + castInstr + " in " + node.getMethod()); PointerKey castedPk = heapModel.getPointerKeyForLocal(node, castInstr.getUse(0)); Predicate<InstanceKey> castPred = new Predicate<InstanceKey>() { @Override public boolean test(InstanceKey ik) { TypeReference ikTypeRef = ik.getConcreteType().getReference(); for (TypeReference t : declaredResultTypes) { if (cha.isAssignableFrom(cha.lookupClass(t), cha.lookupClass(ikTypeRef))) { return true; } } return false; } }; long startTime = System.currentTimeMillis(); Pair<PointsToResult, Collection<InstanceKey>> queryResult = dmp.getPointsTo(castedPk, castPred); long runningTime = System.currentTimeMillis() - startTime; System.err.println("running time: " + runningTime + "ms"); final FieldRefinePolicy fieldRefinePolicy = dmp.getRefinementPolicy().getFieldRefinePolicy(); switch (queryResult.fst) { case SUCCESS: System.err.println("SAFE: " + castInstr + " in " + node.getMethod()); if (fieldRefinePolicy instanceof ManualFieldPolicy) { ManualFieldPolicy hackedFieldPolicy = (ManualFieldPolicy) fieldRefinePolicy; System.err.println(hackedFieldPolicy.getHistory()); } System.err.println("TRAVERSED " + dmp.getNumNodesTraversed() + " nodes"); numSafe++; break; case NOMOREREFINE: if (queryResult.snd != null) { System.err.println( "MIGHT FAIL: no more refinement possible for " + castInstr + " in " + node.getMethod()); } else { System.err.println( "MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod()); } failing.add(Pair.make(node, castInstr)); numMightFail++; break; case BUDGETEXCEEDED: System.err.println( "MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod()); failing.add(Pair.make(node, castInstr)); numMightFail++; break; default: Assertions.UNREACHABLE(); } } } // break outer; } System.err.println("TOTAL SAFE: " + numSafe); System.err.println("TOTAL MIGHT FAIL: " + numMightFail); return failing; }
private static Result getOrigSDG(Config cfg, IProgressMonitor progress) throws IllegalArgumentException, CancelException, PDGFormatException, IOException, WalaException, InvalidClassFileException { progress.beginTask(Messages.getString("Analyzer.Task_Prepare_IR"), -1); // $NON-NLS-1$ com.ibm.wala.ipa.callgraph.impl.Util.setNativeSpec(cfg.nativesXML); progress.subTask(Messages.getString("Analyzer.SubTask_Analysis_Scope")); // $NON-NLS-1$ ClassLoader loader = cfg.getClass().getClassLoader(); AnalysisScope scope = Util.makeAnalysisScope(cfg, loader); // AnalysisScopeReader.makeJavaBinaryAnalysisScope(cfg.scopeFile, cfg.classpath, null); progress.done(); ClassHierarchy cha = ClassHierarchy.make(scope, progress); Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, cfg.mainClass); AnalysisOptions options = new AnalysisOptions(scope, entrypoints); AnalysisCache cache = new AnalysisCache(); progress.subTask( Messages.getString("Analyzer.SubTask_Call_Graph_Builder") + cfg.pointsTo); // $NON-NLS-1$ SSAPropagationCallGraphBuilder builder = SDGFactory.getCallGraphBuilder(cfg.pointsTo, options, cache, cha, scope); /** * Change the wala internal pointer and instancekeyfactory of the callgraph builder to our * adapter. So we can keep track of the created InstanceKeys and PointerKeys. This information * is used later on when creating subobject trees for accessed field variables. */ InstanceAndPointerKeyFactoryAdapter adapter = null; InstanceKeyFactory ikFact = builder.getInstanceKeys(); PointerKeyFactory pkFact = builder.getPointerKeyFactory(); adapter = new InstanceAndPointerKeyFactoryAdapter(ikFact, pkFact); builder.setInstanceKeys(adapter); builder.setPointerKeyFactory(adapter); progress.done(); progress.subTask(Messages.getString("Analyzer.SubTask_Call_Graph")); // $NON-NLS-1$ CallGraph cg = builder.makeCallGraph(options, progress); if (cfg.optimizeCg >= 0) { CallGraphPruning opt = new CallGraphPruning(cg); System.out.println("Call Graph has " + cg.getNumberOfNodes() + " Nodes."); Set<CGNode> sopt = opt.findApplicationNodes(cfg.optimizeCg); cg = new PrunedCallGraph(cg, sopt); System.out.println("Optimized Call Graph has " + cg.getNumberOfNodes() + " Nodes."); } if (Debug.Var.DUMP_CALLGRAPH.isSet()) { Util.dumpCallGraph(cg, cfg.mainClass.replace('/', '.').substring(1), progress); } if (Debug.Var.DUMP_HEAP_GRAPH.isSet()) { PointerAnalysis pta = builder.getPointerAnalysis(); HeapGraph hg = pta.getHeapGraph(); Util.dumpHeapGraph( cfg.mainClass.replace('/', '.').substring(1) + "." + cfg.pointsTo, hg, null); } PointerAnalysis pta = builder.getPointerAnalysis(); progress.done(); DemandRefinementPointsTo demandPts = null; if (cfg.useDemandPts) { throw new UnsupportedOperationException(); // MemoryAccessMap mam = new PABasedMemoryAccessMap(cg, builder.getPointerAnalysis()); // demandPts = new DemandRefinementPointsTo(cg, // new ThisFilteringHeapModel(builder,cha), mam, cha, options, getStateMachineFactory()); } IPointerAnalysis pts = new PointsToWrapper(demandPts, pta); progress.subTask(Messages.getString("Analyzer.SubTask_Search_Main")); // $NON-NLS-1$ IMethod main = edu.kit.joana.deprecated.jsdg.util.Util.searchMethod( entrypoints, "main([Ljava/lang/String;)V"); // $NON-NLS-1$ progress.done(); progress.done(); SDG sdg = SDG.create(main, cg, cache, adapter, pts, cfg, progress); sdg.setAnalysisScope(scope); sdg.setPointerAnalysis(pta); progress.done(); if (Debug.Var.PRINT_FIELD_PTS_INFO.isSet()) { Log.info("search for field allocs called " + PDG.searchFieldAllocs + " times."); } if (Debug.Var.PRINT_UNRESOLVED_CLASSES.isSet()) { for (TypeReference tRef : cg.getClassHierarchy().getUnresolvedClasses()) { Log.warn("Could not resolve: " + Util.typeName(tRef.getName())); } } return new Result(null, sdg, cg, pta, null); }
/** * @param name * @param cg * @return a graph whose nodes are MethodReferences, and whose edges represent calls between * MethodReferences * @throws IllegalArgumentException if cg is null */ public static Graph<MethodReference> squashCallGraph(final String name, final CallGraph cg) { if (cg == null) { throw new IllegalArgumentException("cg is null"); } final Set<MethodReference> nodes = HashSetFactory.make(); for (Iterator<CGNode> nodesI = cg.iterator(); nodesI.hasNext(); ) { nodes.add((nodesI.next()).getMethod().getReference()); } return new Graph<MethodReference>() { @Override public String toString() { StringBuffer result = new StringBuffer(); result.append("squashed " + name + " call graph\n"); result.append("Original graph:"); result.append(cg.toString()); return result.toString(); } /* * @see com.ibm.wala.util.graph.NodeManager#iterateNodes() */ @Override public Iterator<MethodReference> iterator() { return nodes.iterator(); } /* * @see com.ibm.wala.util.graph.NodeManager#containsNode(java.lang.Object) */ @Override public boolean containsNode(MethodReference N) { return nodes.contains(N); } /* * @see com.ibm.wala.util.graph.NodeManager#getNumberOfNodes() */ @Override public int getNumberOfNodes() { return nodes.size(); } /* * @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(java.lang.Object) */ @Override public Iterator<MethodReference> getPredNodes(MethodReference N) { Set<MethodReference> pred = HashSetFactory.make(10); MethodReference methodReference = N; for (Iterator<CGNode> i = cg.getNodes(methodReference).iterator(); i.hasNext(); ) for (Iterator<? extends CGNode> ps = cg.getPredNodes(i.next()); ps.hasNext(); ) pred.add(((CGNode) ps.next()).getMethod().getReference()); return pred.iterator(); } /* * @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(java.lang.Object) */ @Override public int getPredNodeCount(MethodReference N) { int count = 0; for (Iterator<? extends MethodReference> ps = getPredNodes(N); ps.hasNext(); count++, ps.next()) ; return count; } /* * @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(java.lang.Object) */ @Override public Iterator<MethodReference> getSuccNodes(MethodReference N) { Set<MethodReference> succ = HashSetFactory.make(10); MethodReference methodReference = N; for (Iterator<? extends CGNode> i = cg.getNodes(methodReference).iterator(); i.hasNext(); ) for (Iterator<? extends CGNode> ps = cg.getSuccNodes(i.next()); ps.hasNext(); ) succ.add(((CGNode) ps.next()).getMethod().getReference()); return succ.iterator(); } /* * @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(java.lang.Object) */ @Override public int getSuccNodeCount(MethodReference N) { int count = 0; for (Iterator<MethodReference> ps = getSuccNodes(N); ps.hasNext(); count++, ps.next()) ; return count; } /* * @see com.ibm.wala.util.graph.NodeManager#addNode(java.lang.Object) */ @Override public void addNode(MethodReference n) { Assertions.UNREACHABLE(); } /* * @see com.ibm.wala.util.graph.NodeManager#removeNode(java.lang.Object) */ @Override public void removeNode(MethodReference n) { Assertions.UNREACHABLE(); } /* * @see com.ibm.wala.util.graph.EdgeManager#addEdge(java.lang.Object, java.lang.Object) */ @Override public void addEdge(MethodReference src, MethodReference dst) { Assertions.UNREACHABLE(); } @Override public void removeEdge(MethodReference src, MethodReference dst) { Assertions.UNREACHABLE(); } /* * @see com.ibm.wala.util.graph.EdgeManager#removeAllIncidentEdges(java.lang.Object) */ @Override public void removeAllIncidentEdges(MethodReference node) { Assertions.UNREACHABLE(); } /* * @see com.ibm.wala.util.graph.Graph#removeNodeAndEdges(java.lang.Object) */ @Override public void removeNodeAndEdges(MethodReference N) { Assertions.UNREACHABLE(); } @Override public void removeIncomingEdges(MethodReference node) { // TODO Auto-generated method stubMethodReference Assertions.UNREACHABLE(); } @Override public void removeOutgoingEdges(MethodReference node) { // TODO Auto-generated method stub Assertions.UNREACHABLE(); } @Override public boolean hasEdge(MethodReference src, MethodReference dst) { for (Iterator<MethodReference> succNodes = getSuccNodes(src); succNodes.hasNext(); ) { if (dst.equals(succNodes.next())) { return true; } } return false; } }; }
public ContextSensitiveProbablyNotInitializedAnalysis(CallGraph cg, AnalysisCache cache) { this.cha = cg.getClassHierarchy(); // we use an ICFGSupergraph, which basically adapts ExplodedInterproceduralCFG to the // ISupergraph interface this.supergraph = ICFGSupergraph.make(cg, cache); }