add more functionality to analysis engine: create SDGs and

parameterize to do both regular and field-based analysis in JavaScript
This commit is contained in:
Julian Dolby 2016-08-18 22:43:12 -04:00
parent d0fdd2cdf0
commit 0f0c3d6bd9
14 changed files with 130 additions and 31 deletions

View File

@ -12,9 +12,10 @@ package com.ibm.wala.cast.java.client;
import com.ibm.wala.cast.java.translator.jdt.ejc.ECJClassLoaderFactory;
import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.util.config.SetOfClasses;
public class ECJJavaSourceAnalysisEngine extends JavaSourceAnalysisEngine {
public class ECJJavaSourceAnalysisEngine extends JavaSourceAnalysisEngine<InstanceKey> {
@Override
protected ClassLoaderFactory getClassLoaderFactory(SetOfClasses exclusions) {

View File

@ -348,9 +348,9 @@ public abstract class IRTests {
protected abstract AbstractAnalysisEngine getAnalysisEngine(String[] mainClassDescriptors, Collection<String> sources, List<String> libs);
public Pair<CallGraph, PointerAnalysis<InstanceKey>> runTest(Collection<String> sources, List<String> libs,
public <I extends InstanceKey> Pair<CallGraph, PointerAnalysis<I>> runTest(Collection<String> sources, List<String> libs,
String[] mainClassDescriptors, List<? extends IRAssertion> ca, boolean assertReachable) throws IllegalArgumentException, CancelException, IOException {
AbstractAnalysisEngine engine = getAnalysisEngine(mainClassDescriptors, sources, libs);
AbstractAnalysisEngine<I> engine = getAnalysisEngine(mainClassDescriptors, sources, libs);
CallGraph callGraph;
callGraph = engine.buildDefaultCallGraph();

View File

@ -28,6 +28,7 @@ import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
@ -41,7 +42,7 @@ import com.ibm.wala.util.io.FileProvider;
/**
*/
public abstract class JavaSourceAnalysisEngine extends AbstractAnalysisEngine {
public abstract class JavaSourceAnalysisEngine<I extends InstanceKey> extends AbstractAnalysisEngine<I> {
/**
* Modules which are user-space code

View File

@ -107,7 +107,7 @@ public abstract class FieldBasedCallGraphBuilder {
/**
* Main entry point: builds a flow graph, then extracts a call graph and returns it.
*/
public Pair<JSCallGraph,PointerAnalysis<ObjectVertex>> buildCallGraph(Iterable<Entrypoint> eps, IProgressMonitor monitor) throws CancelException {
public Pair<JSCallGraph,PointerAnalysis<ObjectVertex>> buildCallGraph(Iterable<? extends Entrypoint> eps, IProgressMonitor monitor) throws CancelException {
long fgBegin, fgEnd, cgBegin, cgEnd;
if(LOG_TIMINGS) fgBegin = System.currentTimeMillis();
@ -138,7 +138,7 @@ public abstract class FieldBasedCallGraphBuilder {
* Extract a call graph from a given flow graph.
*/
@SuppressWarnings("deprecation")
protected JSCallGraph extract(FlowGraph flowgraph, Iterable<Entrypoint> eps, IProgressMonitor monitor) throws CancelException {
protected JSCallGraph extract(FlowGraph flowgraph, Iterable<? extends Entrypoint> eps, IProgressMonitor monitor) throws CancelException {
// set up call graph
final JSCallGraph cg = new JSCallGraph(cha, options, cache);
cg.init();
@ -153,7 +153,7 @@ public abstract class FieldBasedCallGraphBuilder {
// set up call edges from fake root to all script nodes
AbstractRootMethod fakeRootMethod = (AbstractRootMethod)cg.getFakeRootNode().getMethod();
CGNode fakeRootNode = cg.findOrCreateNode(fakeRootMethod, Everywhere.EVERYWHERE);
for(Iterator<Entrypoint> iter = eps.iterator(); iter.hasNext();) {
for(Iterator<? extends Entrypoint> iter = eps.iterator(); iter.hasNext();) {
Entrypoint ep = iter.next();
CGNode nd = cg.findOrCreateNode(ep.getMethod(), Everywhere.EVERYWHERE);
SSAAbstractInvokeInstruction invk = ep.addCall(fakeRootMethod);

View File

@ -12,12 +12,19 @@ package com.ibm.wala.cast.js.client;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import java.util.jar.JarFile;
import com.ibm.wala.cast.ipa.callgraph.CAstAnalysisScope;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.callgraph.fieldbased.FieldBasedCallGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.OptimisticCallgraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.PessimisticCallGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.ObjectVertex;
import com.ibm.wala.cast.js.client.impl.ZeroCFABuilderFactory;
import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraph;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptEntryPoints;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
@ -29,22 +36,26 @@ import com.ibm.wala.client.AbstractAnalysisEngine;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions;
public class JavaScriptAnalysisEngine extends AbstractAnalysisEngine {
public abstract class JavaScriptAnalysisEngine<I extends InstanceKey> extends AbstractAnalysisEngine<I> {
protected JavaScriptLoaderFactory loaderFactory;
protected JavaScriptTranslatorFactory translatorFactory;
public JavaScriptAnalysisEngine() {
}
@Override
public void buildAnalysisScope() {
try {
@ -103,8 +114,82 @@ public class JavaScriptAnalysisEngine extends AbstractAnalysisEngine {
return options;
}
public static class FieldBasedJavaScriptAnalysisEngine extends JavaScriptAnalysisEngine<ObjectVertex> {
public enum BuilderType { PESSIMISTIC, OPTIMISTIC, REFLECTIVE };
private BuilderType builderType = BuilderType.OPTIMISTIC;
/**
* @return the builderType
*/
public BuilderType getBuilderType() {
return builderType;
}
/**
* @param builderType the builderType to set
*/
public void setBuilderType(BuilderType builderType) {
this.builderType = builderType;
}
@Override
public JSAnalysisOptions getDefaultOptions(Iterable<Entrypoint> roots) {
return JSCallGraphUtil.makeOptions(scope, getClassHierarchy(), roots);
}
@Override
protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
return new ZeroCFABuilderFactory().make((JSAnalysisOptions) options, cache, cha, scope, false);
protected CallGraphBuilder<ObjectVertex> getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, final AnalysisCache cache) {
Set<Entrypoint> roots = HashSetFactory.make();
for(Entrypoint e : options.getEntrypoints()) {
roots.add(e);
}
if (builderType.equals(BuilderType.OPTIMISTIC)) {
((JSAnalysisOptions)options).setHandleCallApply(false);
}
final FieldBasedCallGraphBuilder builder =
builderType.equals(BuilderType.PESSIMISTIC)?
new PessimisticCallGraphBuilder(getClassHierarchy(), options, makeDefaultCache(), true)
: new OptimisticCallgraphBuilder(getClassHierarchy(), options, makeDefaultCache(), true);
return new CallGraphBuilder<ObjectVertex>() {
private PointerAnalysis<ObjectVertex> ptr;
@Override
public CallGraph makeCallGraph(AnalysisOptions options, IProgressMonitor monitor) throws IllegalArgumentException, CallGraphBuilderCancelException {
Pair<JSCallGraph, PointerAnalysis<ObjectVertex>> dat;
try {
dat = builder.buildCallGraph(options.getEntrypoints(), monitor);
} catch (CancelException e) {
throw CallGraphBuilderCancelException.createCallGraphBuilderCancelException(e, null, null);
}
ptr = dat.snd;
return dat.fst;
}
@Override
public PointerAnalysis<ObjectVertex> getPointerAnalysis() {
return ptr;
}
@Override
public AnalysisCache getAnalysisCache() {
return cache;
}
};
}
}
public static class PropagationJavaScriptAnalysisEngine extends JavaScriptAnalysisEngine<InstanceKey> {
@Override
protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
return new ZeroCFABuilderFactory().make((JSAnalysisOptions) options, cache, cha, scope, false);
}
}
}

View File

@ -48,7 +48,7 @@ import com.ibm.wala.util.intset.SparseIntSet;
/**
* Basic implementation of {@link HeapGraph}
*/
public class BasicHeapGraph extends HeapGraphImpl {
public class BasicHeapGraph<T extends InstanceKey> extends HeapGraphImpl<T> {
private final static boolean VERBOSE = false;
@ -70,7 +70,7 @@ public class BasicHeapGraph extends HeapGraphImpl {
* @param P governing pointer analysis
* @throws NullPointerException if P is null
*/
public BasicHeapGraph(final PointerAnalysis<InstanceKey> P, final CallGraph callGraph) throws NullPointerException {
public BasicHeapGraph(final PointerAnalysis<T> P, final CallGraph callGraph) throws NullPointerException {
super(P);
this.callGraph = callGraph;
@ -256,10 +256,10 @@ public class BasicHeapGraph extends HeapGraphImpl {
private int[] computeSuccNodeNumbers(Object N, NumberedNodeManager<Object> nodeManager) {
if (N instanceof PointerKey) {
PointerKey P = (PointerKey) N;
OrdinalSet<InstanceKey> S = getPointerAnalysis().getPointsToSet(P);
OrdinalSet<T> S = getPointerAnalysis().getPointsToSet(P);
int[] result = new int[S.size()];
int i = 0;
for (Iterator<InstanceKey> it = S.iterator(); it.hasNext();) {
for (Iterator<T> it = S.iterator(); it.hasNext();) {
result[i] = nodeManager.getNumber(it.next());
i++;
}

View File

@ -33,6 +33,7 @@ import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ipa.slicer.SDG;
import com.ibm.wala.ssa.DefaultIRFactory;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.CancelException;
@ -42,13 +43,15 @@ import com.ibm.wala.util.config.SetOfClasses;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.io.FileProvider;
import static com.ibm.wala.ipa.slicer.Slicer.*;
/**
* Abstract base class for analysis engine implementations
*
* Some clients choose to build on this, but many don't. I usually don't in new code; I usually don't find the re-use enabled by
* this class compelling. I would probably nuke this except for some legacy code that uses it.
*/
public abstract class AbstractAnalysisEngine implements AnalysisEngine {
public abstract class AbstractAnalysisEngine<I extends InstanceKey> implements AnalysisEngine {
public interface EntrypointBuilder {
Iterable<Entrypoint> createEntrypoints(AnalysisScope scope, IClassHierarchy cha);
@ -114,7 +117,7 @@ public abstract class AbstractAnalysisEngine implements AnalysisEngine {
/**
* Results of pointer analysis
*/
protected PointerAnalysis<InstanceKey> pointerAnalysis;
protected PointerAnalysis<I> pointerAnalysis;
/**
* Graph view of flow of pointers between heap abstractions
@ -256,17 +259,21 @@ public abstract class AbstractAnalysisEngine implements AnalysisEngine {
return scope;
}
public PointerAnalysis<InstanceKey> getPointerAnalysis() {
public PointerAnalysis<I> getPointerAnalysis() {
return pointerAnalysis;
}
public HeapGraph getHeapGraph() {
if (heapGraph == null) {
heapGraph = new BasicHeapGraph(getPointerAnalysis(), cg);
heapGraph = new BasicHeapGraph<>(getPointerAnalysis(), cg);
}
return heapGraph;
}
public SDG<I> getSDG(DataDependenceOptions data, ControlDependenceOptions ctrl) {
return new SDG<I>(getCallGraph(), getPointerAnalysis(), data, ctrl);
}
public String getExclusionsFile() {
return exclusionsFile;
}

View File

@ -13,17 +13,19 @@ package com.ibm.wala.ipa.callgraph;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
/**
* Basic interface for an object that can build a call graph.
*/
public interface CallGraphBuilder {
public interface CallGraphBuilder<I extends InstanceKey> {
/**
* Build a call graph.
*
* @param options an object representing controlling options that the call graph building algorithm needs to know.
* @return the built call graph
* @throws
*/
public CallGraph makeCallGraph(AnalysisOptions options, IProgressMonitor monitor) throws IllegalArgumentException,
CallGraphBuilderCancelException;
@ -31,7 +33,7 @@ public interface CallGraphBuilder {
/**
* @return the Pointer Analysis information computed as a side-effect of call graph construction.
*/
public PointerAnalysis<InstanceKey> getPointerAnalysis();
public PointerAnalysis<I> getPointerAnalysis();
/**
* @return A cache of various analysis artifacts used during call graph construction.

View File

@ -130,7 +130,7 @@ public class Slicer {
* @return the backward slice of s.
* @throws CancelException
*/
public static Collection<Statement> computeBackwardSlice(Statement s, CallGraph cg, PointerAnalysis<InstanceKey> pa,
public static Collection<Statement> computeBackwardSlice(Statement s, CallGraph cg, PointerAnalysis<? extends InstanceKey> pa,
DataDependenceOptions dOptions, ControlDependenceOptions cOptions) throws IllegalArgumentException, CancelException {
return computeSlice(new SDG(cg, pa, ModRef.make(), dOptions, cOptions), Collections.singleton(s), true);
}
@ -140,7 +140,7 @@ public class Slicer {
* @return the forward slice of s.
* @throws CancelException
*/
public static Collection<Statement> computeForwardSlice(Statement s, CallGraph cg, PointerAnalysis<InstanceKey> pa,
public static Collection<Statement> computeForwardSlice(Statement s, CallGraph cg, PointerAnalysis<? extends InstanceKey> pa,
DataDependenceOptions dOptions, ControlDependenceOptions cOptions) throws IllegalArgumentException, CancelException {
return computeSlice(new SDG(cg, pa, ModRef.make(), dOptions, cOptions), Collections.singleton(s), false);
}

View File

@ -57,11 +57,12 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.config.SetOfClasses;
public class JDTJavaSourceAnalysisEngine extends EclipseProjectSourceAnalysisEngine<IJavaProject> {
public class JDTJavaSourceAnalysisEngine<I extends InstanceKey> extends EclipseProjectSourceAnalysisEngine<IJavaProject, I> {
private boolean dump;
public JDTJavaSourceAnalysisEngine(IJavaProject project) throws IOException, CoreException {

View File

@ -26,7 +26,6 @@ import com.ibm.wala.cast.js.callgraph.fieldbased.PessimisticCallGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FilteredFlowGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraph;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.FuncVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.ObjectVertex;
import com.ibm.wala.cast.js.client.impl.ZeroCFABuilderFactory;
import com.ibm.wala.cast.js.html.IncludedPosition;
@ -48,6 +47,7 @@ import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.ClassLoaderReference;
@ -58,7 +58,7 @@ import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.config.SetOfClasses;
import com.ibm.wala.util.functions.Function;
public class EclipseJavaScriptAnalysisEngine extends EclipseProjectSourceAnalysisEngine<IJavaScriptProject> {
public class EclipseJavaScriptAnalysisEngine<I extends InstanceKey> extends EclipseProjectSourceAnalysisEngine<IJavaScriptProject, I> {
public enum BuilderType { PESSIMISTIC, OPTIMISTIC, REFLECTIVE };

View File

@ -25,11 +25,12 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.config.FileOfClasses;
import com.ibm.wala.util.io.FileProvider;
abstract public class EclipseProjectAnalysisEngine<P> extends AbstractAnalysisEngine {
abstract public class EclipseProjectAnalysisEngine<P, I extends InstanceKey> extends AbstractAnalysisEngine<I> {
protected final P project;

View File

@ -19,6 +19,7 @@ import com.ibm.wala.ide.util.EclipseFileProvider;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.ClassLoaderReference;
@ -28,7 +29,7 @@ import com.ibm.wala.util.io.FileProvider;
/**
* An {@link EclipseProjectAnalysisEngine} specialized for source code analysis
*/
abstract public class EclipseProjectSourceAnalysisEngine<P> extends EclipseProjectAnalysisEngine<P> {
abstract public class EclipseProjectSourceAnalysisEngine<P, I extends InstanceKey> extends EclipseProjectAnalysisEngine<P, I> {
public static final String defaultFileExt = "java";