Java Examples for soot.jimple.toolkits.callgraph.CallGraph

The following java examples will help you to understand the usage of soot.jimple.toolkits.callgraph.CallGraph. These source code samples are taken from different open source projects.

Example 1
Project: apkinspector-master  File: MultiRunStatementsFinder.java View source code
private void findMultiCalledMethodsIntra(Set<Object> multiCalledMethods, CallGraph callGraph) {
    Iterator<Unit> it = multiRunStatements.iterator();
    while (it.hasNext()) {
        Unit unit = it.next();
        if (((Stmt) unit).containsInvokeExpr()) {
            Value invokeExpr = ((Stmt) unit).getInvokeExpr();
            List<SootMethod> targetList = new ArrayList<SootMethod>();
            SootMethod method = ((InvokeExpr) invokeExpr).getMethod();
            if (invokeExpr instanceof StaticInvokeExpr) {
                targetList.add(method);
            } else if (invokeExpr instanceof InstanceInvokeExpr) {
                if (method.isConcrete() && !method.getDeclaringClass().isLibraryClass()) {
                    TargetMethodsFinder tmd = new TargetMethodsFinder();
                    //	targetList = tmd.find(unit, callGraph, false, true);
                    // list could be empty... that's ok
                    targetList = tmd.find(unit, callGraph, true, true);
                }
            }
            if (targetList != null) {
                Iterator<SootMethod> iterator = targetList.iterator();
                while (iterator.hasNext()) {
                    SootMethod obj = iterator.next();
                    if (!obj.isNative()) {
                        multiCalledMethods.add(obj);
                    }
                }
            }
        }
    }
}
Example 2
Project: DesignPatternAnalysis-master  File: AnalysisUtil.java View source code
// Independent Role Analysis over a Type
public void analyzeRole(SootClass aType, Map<String, MetaInfo> metaInfoMap, RoleRepository roles, Map<String, SootClass> classMap, Hierarchy hierarchy, CallGraph cg) {
    for (String key : metaInfoMap.keySet()) {
        MetaInfo metaInfo = metaInfoMap.get(key);
        if (metaInfo.getElement() instanceof SootMethod) {
            SootMethod method = (SootMethod) metaInfo.getElement();
            Map<String, LocalInfo> callLocalInfos = calls(method, aType, classMap);
            Map<String, LocalInfo> creationLocalInfos = typeFilterOfLocalMap(creations(method), aType, hierarchy, classMap);
            for (LocalInfo callLocalInfo : callLocalInfos.values()) {
                checkCaller(aType, metaInfo, callLocalInfo, roles);
            }
            for (LocalInfo creationLocalInfo : creationLocalInfos.values()) {
                checkCreator(aType, metaInfo, creationLocalInfo, roles, classMap);
            }
            checkInjector(method, aType, metaInfoMap, roles, classMap, hierarchy, cg);
        } else if (metaInfo.getElement() instanceof SootField) {
            SootField field = (SootField) metaInfo.getElement();
            SootClass fieldType = typeToClass(field.getType(), classMap);
            if (fieldType != null) {
                if (fieldType.equals(aType)) {
                    Store store = new Store();
                    store.setInterfaceType(aType);
                    metaInfo.addRole(store);
                    roles.addStore(metaInfo);
                }
            }
        }
    }
}
Example 3
Project: Slithice-master  File: SootUtils.java View source code
/**
	 * get graph of strong connected components. 
	 * XXX: Here we break thread start calls in the call graph when finding SCCs
	 */
public static DirectedGraph<Collection> getSCCGraph(CallGraph cg, Collection entries) {
    ReachableMethods rm = CallGraphHelper.getReachableMethod(cg, entries);
    CallGraphNodeFilter nodeFilter = CallGraphHelper.getCallGraphNodeFilter(rm);
    CallGraphEdgeFilter edgeFilter = new CallGraphEdgeFilter() {

        public boolean isIgnored(Edge e) {
            return (e.kind() == Kind.THREAD);
        }
    };
    DirectedCallGraph dcg = new DirectedCallGraph(cg, entries, nodeFilter, edgeFilter);
    StronglyConnectedComponents scc = new StronglyConnectedComponents(dcg);
    return scc.getSuperGraph();
}
Example 4
Project: soot-master  File: GeomEvaluator.java View source code
/**
	 * Report the virtual callsites resolution result for the user's code.
	 */
public void checkCallGraph() {
    Map<Stmt, Set<SootMethod>> my_vir_tgts = new HashMap<Stmt, Set<SootMethod>>();
    int n_func;
    int total_virtual_calls = 0;
    int n_geom_call_edges = 0, n_geom_user_edges = 0;
    int n_spark_user_edges = 0, n_spark_cinit_edges = 0;
    int geom_solved = 0, spark_solved = 0;
    n_func = ptsProvider.n_func;
    // We first collect the internal call graph information
    for (int i = 1; i < n_func; ++i) {
        if (!ptsProvider.isReachableMethod(i))
            continue;
        CgEdge p = ptsProvider.getCallEgesOutFrom(i);
        int edge_cnt = 0;
        while (p != null) {
            if (p.base_var != null) {
                Stmt expr = p.sootEdge.srcStmt();
                if (expr != null) {
                    Set<SootMethod> tgts = my_vir_tgts.get(expr);
                    if (tgts == null) {
                        tgts = new HashSet<SootMethod>();
                        my_vir_tgts.put(expr, tgts);
                    }
                    tgts.add(p.sootEdge.tgt().method());
                }
            }
            ++edge_cnt;
            p = p.next;
        }
        n_geom_call_edges += edge_cnt;
        if (!ptsProvider.getSootMethodFromID(i).isJavaLibraryMethod())
            n_geom_user_edges += edge_cnt;
    }
    int[] limits = new int[] { 1, 2, 4, 8 };
    Histogram total_call_edges = new Histogram(limits);
    System.gc();
    System.gc();
    System.gc();
    CallGraph cGraph = Scene.v().getCallGraph();
    // Scan all the callsites
    for (SootMethod sm : ptsProvider.getAllReachableMethods()) {
        // Skip the uninteresting methods
        if (sm.isJavaLibraryMethod())
            continue;
        if (!sm.isConcrete())
            continue;
        if (!sm.hasActiveBody()) {
            sm.retrieveActiveBody();
        }
        if (!ptsProvider.isValidMethod(sm))
            continue;
        // All the statements in the method
        for (Iterator stmts = sm.getActiveBody().getUnits().iterator(); stmts.hasNext(); ) {
            Stmt st = (Stmt) stmts.next();
            if (st.containsInvokeExpr()) {
                InvokeExpr ie = st.getInvokeExpr();
                if (ie instanceof VirtualInvokeExpr) {
                    total_virtual_calls++;
                    Local l = (Local) ((VirtualInvokeExpr) ie).getBase();
                    LocalVarNode vn = ptsProvider.findLocalVarNode(l);
                    // Test my points-to analysis
                    solved = false;
                    if (my_vir_tgts.containsKey(st)) {
                        Set<SootMethod> tgts = my_vir_tgts.get(st);
                        if (tgts.size() == 1) {
                            ++geom_solved;
                            solved = true;
                        } else {
                            // We try to test if this callsite is solvable under some contexts
                            Histogram call_edges = new Histogram(limits);
                            test_1cfa_call_graph(vn, sm, ie.getMethod(), call_edges);
                            total_call_edges.merge(call_edges);
                            call_edges = null;
                        }
                    } else {
                        // It has zero target, dead code
                        ++geom_solved;
                        solved = true;
                    }
                    int count = 0;
                    for (Iterator<Edge> it = cGraph.edgesOutOf(st); it.hasNext(); ) {
                        it.next();
                        ++count;
                    }
                    if (count <= 1)
                        spark_solved++;
                    if (count > 1 && solved == true && ptsProvider.getOpts().verbose()) {
                        outputer.println();
                        outputer.println("<<<<<<<<<   Additional Solved Call   >>>>>>>>>>");
                        outputer.println(sm.toString());
                        outputer.println(ie.toString());
                        EvalHelper.debug_succint_pointsto_info(vn, ptsProvider);
                    }
                }
            }
        }
        for (Iterator<Edge> it = cGraph.edgesOutOf(sm); it.hasNext(); ) {
            Edge e = it.next();
            if (!e.isClinit())
                ++n_spark_user_edges;
        }
    }
    // Now we count the cinit edges
    QueueReader<Edge> edgeList = Scene.v().getCallGraph().listener();
    while (edgeList.hasNext()) {
        Edge edge = edgeList.next();
        if (edge.isClinit())
            ++n_spark_cinit_edges;
    }
    ptsProvider.ps.println();
    ptsProvider.ps.printf("Call graph edges (total): Geom = %d, SPARK = %d\n", n_geom_call_edges, cGraph.size() - n_spark_cinit_edges);
    ptsProvider.ps.printf("Call graph edges (app code): Geom = %d, SPARK = %d\n", n_geom_user_edges, n_spark_user_edges);
    ptsProvider.ps.println("Total virtual callsites (app code): " + total_virtual_calls);
    ptsProvider.ps.println("Resolved virtual callsites : Geom = " + geom_solved + ", SPARK = " + spark_solved);
    total_call_edges.printResult(ptsProvider.ps, "Random testing of the 1-CFA call graph : ");
    if (ptsProvider.getOpts().verbose())
        ptsProvider.outputNotEvaluatedMethods();
}
Example 5
Project: ptii-master  File: SideEffectFreeInvocationRemover.java View source code
protected void internalTransform(String phaseName, Map options) {
    System.out.println("SideEffectFreeInvocationRemover.internalTransform(" + phaseName + ", " + options + ")");
    Scene.v().releaseCallGraph();
    // Temporary hack to deal with interfaces...  assume that methods of
    // interfaces are automatically reachable.
    HashSet forcedReachableMethodSet = new HashSet();
    forcedReachableMethodSet.addAll(EntryPoints.v().application());
    // Loop over all the classes...
    for (Iterator i = Scene.v().getApplicationClasses().iterator(); i.hasNext(); ) {
        SootClass theClass = (SootClass) i.next();
        //  System.out.println("forcing interfaces of " + theClass);
        if (!theClass.isInterface()) {
            for (Iterator interfaces = theClass.getInterfaces().iterator(); interfaces.hasNext(); ) {
                SootClass theInterface = (SootClass) interfaces.next();
                _addMethodsFrom(forcedReachableMethodSet, theInterface, theClass);
            }
        }
    }
    System.out.println("forcedMethods = " + forcedReachableMethodSet);
    // Loop over all the classes...
    for (Iterator i = Scene.v().getApplicationClasses().iterator(); i.hasNext(); ) {
        SootClass theClass = (SootClass) i.next();
        Scene.v().loadClassAndSupport(theClass.getName());
    }
    System.out.println("done loading classes!");
    // Construct the graph of methods that are directly reachable
    // from any method.
    // Construct the graph of all method invocations, so we know what
    // method contains each invocation and what method(s) can be
    // targeted by that invocation.
    CallGraphBuilder cg = new CallGraphBuilder(DumbPointerAnalysis.v(), true);
    cg.build();
    CallGraph callGraph = Scene.v().getCallGraph();
    Scene.v().setCallGraph(callGraph);
    SideEffectAnalysis analysis = new SideEffectAnalysis();
    for (Iterator classes = Scene.v().getApplicationClasses().iterator(); classes.hasNext(); ) {
        SootClass theClass = (SootClass) classes.next();
        for (Iterator methods = theClass.getMethods().iterator(); methods.hasNext(); ) {
            SootMethod method = (SootMethod) methods.next();
            _removeSideEffectFreeMethodCalls(method, callGraph, analysis);
        }
    }
}
Example 6
Project: SPLlift-master  File: UnitUtil.java View source code
/**
	 * Serialize a CallGraph in the DOT format into a provided file path.
	 * 
	 * TODO: describe the behaviour of this method in case the file already exists.
	 * 
	 * @param graph
	 *            the graph to be serialized
	 * @param fileName
	 *            the file name, or null to use the default Soot output folder.
	 */
public static File serializeCallGraph(CallGraph graph, String fileName) {
    if (fileName == null) {
        fileName = soot.SourceLocator.v().getOutputDir();
        if (fileName.length() > 0) {
            fileName = fileName + java.io.File.separator;
        }
        fileName = fileName + "call-graph" + DotGraph.DOT_EXTENSION;
    }
    DotGraph canvas = new DotGraph("call-graph");
    QueueReader<Edge> listener = graph.listener();
    while (listener.hasNext()) {
        Edge next = listener.next();
        MethodOrMethodContext src = next.getSrc();
        MethodOrMethodContext tgt = next.getTgt();
        canvas.drawNode(src.toString());
        canvas.drawNode(tgt.toString());
        canvas.drawEdge(src.toString(), tgt.toString());
    }
    canvas.plot(fileName);
    return new File(fileName);
}
Example 7
Project: ic3-master  File: EntryPointMappingSceneTransformer.java View source code
@Override
protected void internalTransform(String phaseName, @SuppressWarnings("rawtypes") Map options) {
    PropagationTimers.v().totalTimer.start();
    Timers.v().entryPointMapping.start();
    // Set<String> signatures = new HashSet<>();
    Map<SootMethod, Set<String>> entryPointMap = this.entryPointMap;
    if (logger.isDebugEnabled()) {
        Set<String> difference = new HashSet<>(this.callbackMethods.keySet());
        difference.removeAll(entryPointClasses);
        if (difference.size() == 0) {
            logger.debug("Difference size is 0");
        } else {
            logger.debug("Difference is " + difference);
        }
    }
    // Set<String> lifecycleMethods = new HashSet<>();
    // lifecycleMethods.addAll(AndroidEntryPointConstants.getActivityLifecycleMethods());
    // lifecycleMethods.addAll(AndroidEntryPointConstants.getApplicationLifecycleMethods());
    // lifecycleMethods.addAll(AndroidEntryPointConstants.getBroadcastLifecycleMethods());
    // lifecycleMethods.addAll(AndroidEntryPointConstants.getContentproviderLifecycleMethods());
    // lifecycleMethods.addAll(AndroidEntryPointConstants.getServiceLifecycleMethods());
    activityClass = Scene.v().getSootClass(AndroidEntryPointConstants.ACTIVITYCLASS);
    serviceClass = Scene.v().getSootClass(AndroidEntryPointConstants.SERVICECLASS);
    gcmBaseIntentServiceClass = Scene.v().getSootClass(AndroidEntryPointConstants.GCMBASEINTENTSERVICECLASS);
    receiverClass = Scene.v().getSootClass(AndroidEntryPointConstants.BROADCASTRECEIVERCLASS);
    providerClass = Scene.v().getSootClass(AndroidEntryPointConstants.CONTENTPROVIDERCLASS);
    applicationClass = Scene.v().getSootClass(AndroidEntryPointConstants.APPLICATIONCLASS);
    if (logger.isDebugEnabled()) {
        logger.debug(this.callbackMethods.toString());
    }
    for (String entryPoint : entryPointClasses) {
        // if (!entryPointClasses.contains(entryPoint)) {
        // System.err.println("Warning: " + entryPoint + " is not an entry point");
        // continue;
        // }
        SootClass entryPointClass = Scene.v().getSootClass(entryPoint);
        List<MethodOrMethodContext> callbacks = new ArrayList<>();
        // Add methods for component.
        boolean knownComponentType = addLifecycleMethods(entryPointClass, callbacks);
        for (SootMethod method : entryPointClass.getMethods()) {
            String methodName = method.getName();
            if (methodName.equals(SootMethod.constructorName) || methodName.equals(SootMethod.staticInitializerName) || !knownComponentType) {
                callbacks.add(method);
            }
        }
        Set<String> callbackMethodStrings = this.callbackMethods.get(entryPoint);
        if (callbackMethodStrings != null) {
            for (String callbackMethodString : callbackMethodStrings) {
                if (!Scene.v().containsMethod(callbackMethodString)) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Warning: " + callbackMethodString + " is not in scene");
                    }
                    continue;
                }
                SootMethod method = Scene.v().getMethod(callbackMethodString);
                // Add constructors for callbacks.
                for (SootMethod potentialInit : method.getDeclaringClass().getMethods()) {
                    if (potentialInit.isPrivate()) {
                        continue;
                    }
                    String name = potentialInit.getName();
                    if (name.equals(SootMethod.constructorName)) {
                        addConstructorStack(potentialInit, callbacks);
                    } else if (name.equals(SootMethod.staticInitializerName)) {
                        callbacks.add(potentialInit);
                    }
                }
                callbacks.add(method);
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug(callbacks.toString());
        }
        ReachableMethods reachableMethods = new ReachableMethods(Scene.v().getCallGraph(), callbacks.iterator(), null);
        reachableMethods.update();
        for (Iterator<MethodOrMethodContext> iter = reachableMethods.listener(); iter.hasNext(); ) {
            SootMethod method = iter.next().method();
            if (!AnalysisParameters.v().isAnalysisClass(method.getDeclaringClass().getName())) {
                continue;
            }
            if (logger.isDebugEnabled()) {
                logger.debug(method.toString());
            }
            Set<String> entryPoints = entryPointMap.get(method);
            if (entryPoints == null) {
                entryPoints = new HashSet<>();
                entryPointMap.put(method, entryPoints);
            }
            entryPoints.add(entryPoint);
        }
    }
    if (logger.isDebugEnabled()) {
        logger.debug("Entry points");
        logger.debug(entryPointMap.toString());
        CallGraph cg = Scene.v().getCallGraph();
        Iterator<Edge> it = cg.listener();
        StringBuilder stringBuilder = new StringBuilder("Call graph:\n");
        while (it.hasNext()) {
            soot.jimple.toolkits.callgraph.Edge e = it.next();
            stringBuilder.append("" + e.src() + e.srcStmt() + " =" + e.kind() + "=> " + e.tgt() + "\n");
        }
        logger.debug(stringBuilder.toString());
    }
    Timers.v().entryPointMapping.end();
    PropagationTimers.v().totalTimer.end();
}
Example 8
Project: vasco-master  File: CallGraphTransformer.java View source code
/**
	 * {@inheritDoc}
	 */
@SuppressWarnings("deprecation")
@Override
protected void internalTransform(String arg0, @SuppressWarnings("rawtypes") Map arg1) {
    // Perform the points-to analysis
    pointsToAnalysis = new PointsToAnalysis();
    pointsToAnalysis.doAnalysis();
    // Use the context transition table generated by the analysis to construct soot call graphs
    final ContextTransitionTable<SootMethod, Unit, PointsToGraph> ctt = pointsToAnalysis.getContextTransitionTable();
    // Initialize collections (for creating the soot context-sensitive call graph)
    final Set<SootMethod> allMethods = pointsToAnalysis.getMethods();
    final Map<Context<SootMethod, Unit, PointsToGraph>, Collection<ContextSensitiveEdge>> csEdgesIntoContext = new HashMap<Context<SootMethod, Unit, PointsToGraph>, Collection<ContextSensitiveEdge>>();
    final Map<Context<SootMethod, Unit, PointsToGraph>, Collection<ContextSensitiveEdge>> csEdgesOutOfContext = new HashMap<Context<SootMethod, Unit, PointsToGraph>, Collection<ContextSensitiveEdge>>();
    final Map<CallSite<SootMethod, Unit, PointsToGraph>, Collection<ContextSensitiveEdge>> csEdgesOutOfCallSite = new HashMap<CallSite<SootMethod, Unit, PointsToGraph>, Collection<ContextSensitiveEdge>>();
    final Collection<ContextSensitiveEdge> csEdges = new ArrayList<ContextSensitiveEdge>();
    // Initialize the context-insensitive call graph
    CallGraph callGraph = new CallGraph();
    // Create soot-style edges for every context transition
    for (Map.Entry<CallSite<SootMethod, Unit, PointsToGraph>, Map<SootMethod, Context<SootMethod, Unit, PointsToGraph>>> e : ctt.getTransitions().entrySet()) {
        CallSite<SootMethod, Unit, PointsToGraph> cs = e.getKey();
        final Context<SootMethod, Unit, PointsToGraph> sourceContext = cs.getCallingContext();
        final SootMethod sourceMethod = sourceContext.getMethod();
        final Unit stmt = cs.getCallNode();
        final Map<SootMethod, Context<SootMethod, Unit, PointsToGraph>> targets = e.getValue();
        for (final SootMethod targetMethod : targets.keySet()) {
            final Context<SootMethod, Unit, PointsToGraph> targetContext = targets.get(targetMethod);
            Kind k;
            if (stmt instanceof InvokeExpr) {
                k = Edge.ieToKind((InvokeExpr) stmt);
            } else {
                k = Kind.INVALID;
            }
            // The context-insensitive edge
            Edge cgEdge = new Edge(sourceMethod, stmt, targetMethod, k);
            // Add it to the context-insensitive call-graph
            callGraph.addEdge(cgEdge);
            // The context-sensitive edge
            ContextSensitiveEdge csEdge = new ContextSensitiveEdge() {

                @Override
                public Kind kind() {
                    if (stmt instanceof InvokeExpr) {
                        return Edge.ieToKind((InvokeExpr) stmt);
                    } else {
                        return Kind.INVALID;
                    }
                }

                @Override
                public SootMethod src() {
                    return sourceMethod;
                }

                @Override
                public soot.Context srcCtxt() {
                    return sourceContext;
                }

                @Override
                public Stmt srcStmt() {
                    return (Stmt) stmt;
                }

                @Override
                public Unit srcUnit() {
                    return stmt;
                }

                @Override
                public SootMethod tgt() {
                    return targetMethod;
                }

                @Override
                public soot.Context tgtCtxt() {
                    return targetContext;
                }
            };
            // Add this in all the collections
            csEdges.add(csEdge);
            if (!csEdgesOutOfContext.containsKey(sourceContext))
                csEdgesOutOfContext.put(sourceContext, new ArrayList<ContextSensitiveEdge>());
            csEdgesOutOfContext.get(sourceContext).add(csEdge);
            if (!csEdgesOutOfCallSite.containsKey(cs))
                csEdgesOutOfCallSite.put(cs, new ArrayList<ContextSensitiveEdge>());
            csEdgesOutOfCallSite.get(cs).add(csEdge);
            if (!csEdgesIntoContext.containsKey(targetContext))
                csEdgesIntoContext.put(targetContext, new ArrayList<ContextSensitiveEdge>());
            csEdgesIntoContext.get(targetContext).add(csEdge);
        }
    }
    // Set the scene's context-insensitive call-graph to what we just created
    Scene.v().setCallGraph(callGraph);
    // Set the scene's context-sensitive call graph to one that we construct on-the-fly using the above collections
    Scene.v().setContextSensitiveCallGraph(new ContextSensitiveCallGraph() {

        @SuppressWarnings("unchecked")
        private Context<SootMethod, Unit, PointsToGraph> vContext(soot.Context sContext) {
            return (Context<SootMethod, Unit, PointsToGraph>) sContext;
        }

        private CallSite<SootMethod, Unit, PointsToGraph> vCallSite(soot.Context sContext, Unit unit) {
            return new CallSite<SootMethod, Unit, PointsToGraph>(vContext(sContext), unit);
        }

        @Override
        public Iterator<?> edgesOutOf(soot.Context sContext, SootMethod m, Unit stmt) {
            return csEdgesOutOfCallSite.get((vCallSite(sContext, stmt))).iterator();
        }

        @Override
        public Iterator<?> edgesOutOf(soot.Context sContext, SootMethod m) {
            return csEdgesOutOfContext.get(vContext(sContext)).iterator();
        }

        @Override
        public Iterator<?> edgesInto(soot.Context sContext, SootMethod m) {
            return csEdgesIntoContext.get(vContext(sContext)).iterator();
        }

        @Override
        public Iterator<?> edgeSources() {
            return allMethods.iterator();
        }

        @Override
        public Iterator<?> allEdges() {
            return csEdges.iterator();
        }
    });
}
Example 9
Project: bugvm-master  File: LocalMustAliasAnalysis.java View source code
/**
     * Computes the set of {@link EquivalentValue}s of all field references that are used
     * in this method but not set by the method or any method transitively called by this method.
     */
private Set<Value> trackableFields() {
    Set<Value> usedFieldRefs = new HashSet<Value>();
    //add all field references that are in use boxes
    for (Unit unit : this.graph) {
        Stmt s = (Stmt) unit;
        List<ValueBox> useBoxes = s.getUseBoxes();
        for (ValueBox useBox : useBoxes) {
            Value val = useBox.getValue();
            if (val instanceof FieldRef) {
                FieldRef fieldRef = (FieldRef) val;
                if (fieldRef.getType() instanceof RefLikeType)
                    usedFieldRefs.add(new EquivalentValue(fieldRef));
            }
        }
    }
    //prune all fields that are written to
    if (!usedFieldRefs.isEmpty()) {
        if (!Scene.v().hasCallGraph()) {
            throw new IllegalStateException("No call graph found!");
        }
        CallGraph cg = Scene.v().getCallGraph();
        ReachableMethods reachableMethods = new ReachableMethods(cg, Collections.<MethodOrMethodContext>singletonList(container));
        reachableMethods.update();
        for (Iterator<MethodOrMethodContext> iterator = reachableMethods.listener(); iterator.hasNext(); ) {
            SootMethod m = (SootMethod) iterator.next();
            if (m.hasActiveBody() && //exclude static initializer of same class (assume that it has already been executed)
            !(m.getName().equals(SootMethod.staticInitializerName) && m.getDeclaringClass().equals(container.getDeclaringClass()))) {
                for (Unit u : m.getActiveBody().getUnits()) {
                    List<ValueBox> defBoxes = u.getDefBoxes();
                    for (ValueBox defBox : defBoxes) {
                        Value value = defBox.getValue();
                        if (value instanceof FieldRef) {
                            usedFieldRefs.remove(new EquivalentValue(value));
                        }
                    }
                }
            }
        }
    }
    return usedFieldRefs;
}