package soot.jimple.toolkits.infoflow; import soot.*; import java.util.*; import soot.toolkits.graph.*; // SimpleMethodLocalObjectsAnalysis written by Richard L. Halpert, 2007-02-23 // Finds objects that are local to the scope of the LocalObjectsScopeAnalysis // that is provided. // This is a specialized version of SimpleMethodInfoFlowAnalysis, in which the data // source is the abstract "shared" data source. public class SimpleMethodLocalObjectsAnalysis extends SimpleMethodInfoFlowAnalysis { public static int mlocounter = 0; public SimpleMethodLocalObjectsAnalysis(UnitGraph g, ClassLocalObjectsAnalysis cloa, InfoFlowAnalysis dfa) { super(g, dfa, true, true); // special version doesn't run analysis yet mlocounter++; printMessages = false; SootMethod method = g.getBody().getMethod(); AbstractDataSource sharedDataSource = new AbstractDataSource(new String("SHARED")); // Add a source for every parameter that is shared for(int i = 0; i < method.getParameterCount(); i++) // no need to worry about return value... { EquivalentValue paramEqVal = InfoFlowAnalysis.getNodeForParameterRef(method, i); if(!cloa.parameterIsLocal(method, paramEqVal)) { addToEntryInitialFlow(sharedDataSource, paramEqVal.getValue()); addToNewInitialFlow(sharedDataSource, paramEqVal.getValue()); } } for (SootField sf : cloa.getSharedFields()) { EquivalentValue fieldRefEqVal = InfoFlowAnalysis.getNodeForFieldRef(method, sf); addToEntryInitialFlow(sharedDataSource, fieldRefEqVal.getValue()); addToNewInitialFlow(sharedDataSource, fieldRefEqVal.getValue()); } if(printMessages) G.v().out.println("----- STARTING SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----"); doFlowInsensitiveAnalysis(); if(printMessages) G.v().out.println("----- ENDING SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----"); } public SimpleMethodLocalObjectsAnalysis(UnitGraph g, CallLocalityContext context, InfoFlowAnalysis dfa) { super(g, dfa, true, true); // special version doesn't run analysis yet mlocounter++; printMessages = false; SootMethod method = g.getBody().getMethod(); AbstractDataSource sharedDataSource = new AbstractDataSource(new String("SHARED")); List<Object> sharedRefs = context.getSharedRefs(); Iterator<Object> sharedRefEqValIt = sharedRefs.iterator(); // returns a list of (correctly structured) EquivalentValue wrapped refs that should be treated as shared while(sharedRefEqValIt.hasNext()) { EquivalentValue refEqVal = (EquivalentValue) sharedRefEqValIt.next(); addToEntryInitialFlow(sharedDataSource, refEqVal.getValue()); addToNewInitialFlow(sharedDataSource, refEqVal.getValue()); } if(printMessages) { G.v().out.println("----- STARTING SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----"); G.v().out.print(" " + context.toString().replaceAll("\n","\n ")); G.v().out.println("found " + sharedRefs.size() + " shared refs in context."); } doFlowInsensitiveAnalysis(); if(printMessages) G.v().out.println("----- ENDING SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----"); } // Interesting sources are summarized (and possibly printed) public boolean isInterestingSource(Value source) { return (source instanceof AbstractDataSource); } // Interesting sinks are possibly printed public boolean isInterestingSink(Value sink) { return true; //(sink instanceof Local); // we're interested in all values } // public boolean isObjectLocal(Value local) // to this analysis of this method (which depends on context) { EquivalentValue source = new CachedEquivalentValue(new AbstractDataSource(new String("SHARED"))); if(infoFlowGraph.containsNode(source)) { List sinks = infoFlowGraph.getSuccsOf(source); if(printMessages) G.v().out.println(" Requested value " + local + " is " + ( !sinks.contains(new CachedEquivalentValue(local)) ? "Local" : "Shared" ) + " in " + sm + " "); return !sinks.contains(new CachedEquivalentValue(local)); } else { if(printMessages) G.v().out.println(" Requested value " + local + " is Local (LIKE ALL VALUES) in " + sm + " "); return true; // no shared data in this method } } }