WALA/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGr...

317 lines
12 KiB
Java
Raw Normal View History

/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.java.ipa.callgraph;
import com.ibm.wala.analysis.typeInference.TypeInference;
import com.ibm.wala.cast.ipa.callgraph.AstSSAPropagationCallGraphBuilder;
2015-04-06 01:19:56 +00:00
import com.ibm.wala.cast.ipa.callgraph.GlobalObjectKey;
import com.ibm.wala.cast.java.analysis.typeInference.AstJavaTypeInference;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.JavaClass;
import com.ibm.wala.cast.java.ssa.AstJavaInstructionVisitor;
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
import com.ibm.wala.cast.java.ssa.AstJavaNewEnclosingInstruction;
import com.ibm.wala.cast.java.ssa.EnclosingObjectReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.fixpoint.IntSetVariable;
import com.ibm.wala.fixpoint.UnaryOperator;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.IAnalysisCacheView;
import com.ibm.wala.ipa.callgraph.propagation.AbstractFieldPointerKey;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory;
import com.ibm.wala.ipa.callgraph.propagation.PointsToSetVariable;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSANewInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.util.debug.Assertions;
2015-04-06 01:19:56 +00:00
import com.ibm.wala.util.strings.Atom;
public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraphBuilder {
protected AstJavaSSAPropagationCallGraphBuilder(IMethod fakeRootClass, AnalysisOptions options, IAnalysisCacheView cache,
PointerKeyFactory pointerKeyFactory) {
super(fakeRootClass, options, cache, pointerKeyFactory);
}
// ///////////////////////////////////////////////////////////////////////////
//
// language specialization interface
//
// ///////////////////////////////////////////////////////////////////////////
2013-06-25 15:57:37 +00:00
@Override
protected boolean useObjectCatalog() {
return false;
}
new test to remind me that prototype no longer works with correlation tracking: com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestPrototypeCallGraphShapeRhino.java com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestPrototypeCallGraphShape.java com.ibm.wala.cast.js.test.data/examples-src/pages/prototype.html work (not yet finished) on fixes to property accesses for JavaScript: com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ipa/callgraph/AstJavaSSAPropagationCallGraphBuilder.java com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java currently unused tests to remind me to fix bugs: com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java com.ibm.wala.cast.js.test.data/examples-src/tests/loops.js com.ibm.wala.cast.js.test.data/examples-src/tests/primitive_strings.js fixes to exception handler code generation in JavaScript: com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java com.ibm.wala.cast.js.test.data/examples-src/tests/try.js com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java fixes to make the system build on both juno and luna com.ibm.wala.cast.js.test.data/pom.xml pom.xml targets/e42/e42.target targets/e44/e44.target targets/pom.xml com.ibm.wala.core.tests/META-INF/MANIFEST.MF com.ibm.wala.dalvik.test/META-INF/MANIFEST.MF com.ibm.wala.ide.jdt.test/META-INF/MANIFEST.MF com.ibm.wala.ide.jdt/source/com/ibm/wala/cast/java/translator/jdt/FakeExceptionTypeBinding.java com.ibm.wala.ide.jdt/source/com/ibm/wala/ide/util/JavaEclipseProjectPath.java com.ibm.wala.ide.jsdt.tests/META-INF/MANIFEST.MF com.ibm.wala.ide.jsdt.tests/src/com/ibm/wala/ide/jsdt/tests/AbstractJSProjectScopeTest.java com.ibm.wala.ide/src/com/ibm/wala/ide/util/EclipseProjectPath.java com.ibm.wala.ide/src/com/ibm/wala/ide/util/ProgressMonitorDelegate.java beginnings of "pointer analysis" on top of field-based analysis com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/callgraph/fieldbased/flowgraph/FlowGraph.java com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/callgraph/fieldbased/flowgraph/vertices/PropVertex.java com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/callgraph/fieldbased/flowgraph/vertices/RetVertex.java com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/callgraph/fieldbased/flowgraph/vertices/VarVertex.java com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/callgraph/fieldbased/flowgraph/vertices/VertexFactory.java com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysis.java com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/cfa/ExceptionReturnValueKey.java fixes for crashes in correlartion tracking com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ClosureExtractor.java fixes for Dalvik IR generation com.ibm.wala.core/src/com/ibm/wala/cfg/BytecodeCFG.java com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java com.ibm.wala.core/src/com/ibm/wala/ssa/SSACFG.java com.ibm.wala.dalvik.test/source/com/ibm/wala/dalvik/drivers/APKCallGraphDriver.java com.ibm.wala.dalvik.test/source/com/ibm/wala/dalvik/test/callGraph/JVMLDalvikComparison.java com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/classLoader/DexCFG.java com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/dex/instructions/UnaryOperation.java com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/ssa/AbstractIntRegisterMachine.java com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/ssa/DexSSABuilder.java fixes to stack map generation when instrumenting for Java 7 com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/DynamicCallGraph.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/ConstantInstruction.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Analyzer.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/ClassHierarchy.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Verifier.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/ClassInstrumenter.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapConstants.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapTableReader.java com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapTableWriter.java
2014-10-15 07:01:38 +00:00
@Override
protected AbstractFieldPointerKey fieldKeyForUnknownWrites(AbstractFieldPointerKey fieldKey) {
assert false;
return null;
}
// ///////////////////////////////////////////////////////////////////////////
//
// enclosing object pointer flow support
//
// ///////////////////////////////////////////////////////////////////////////
public static class EnclosingObjectReferenceKey extends AbstractFieldPointerKey {
private final IClass outer;
public EnclosingObjectReferenceKey(InstanceKey inner, IClass outer) {
super(inner);
this.outer = outer;
}
2013-06-25 15:57:37 +00:00
@Override
public int hashCode() {
return getInstanceKey().hashCode() * outer.hashCode();
}
2013-06-25 15:57:37 +00:00
@Override
public boolean equals(Object o) {
return (o instanceof EnclosingObjectReferenceKey) && ((EnclosingObjectReferenceKey) o).outer.equals(outer)
&& ((EnclosingObjectReferenceKey) o).getInstanceKey().equals(getInstanceKey());
}
}
// ///////////////////////////////////////////////////////////////////////////
//
// top-level node constraint generation
//
// ///////////////////////////////////////////////////////////////////////////
protected TypeInference makeTypeInference(IR ir) {
TypeInference ti = new AstJavaTypeInference(ir, false);
if (DEBUG_TYPE_INFERENCE) {
System.err.println(("IR of " + ir.getMethod()));
System.err.println(ir);
System.err.println(("TypeInference of " + ir.getMethod()));
for (int i = 0; i <= ir.getSymbolTable().getMaxValueNumber(); i++) {
if (ti.isUndefined(i)) {
System.err.println((" value " + i + " is undefined"));
} else {
System.err.println((" value " + i + " has type " + ti.getType(i)));
}
}
}
return ti;
}
protected class AstJavaInterestingVisitor extends AstInterestingVisitor implements AstJavaInstructionVisitor {
protected AstJavaInterestingVisitor(int vn) {
super(vn);
}
2013-06-25 15:57:37 +00:00
@Override
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
Assertions.UNREACHABLE();
}
2013-06-25 15:57:37 +00:00
@Override
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
bingo = true;
}
}
2013-06-25 15:57:37 +00:00
@Override
protected InterestingVisitor makeInterestingVisitor(CGNode node, int vn) {
return new AstJavaInterestingVisitor(vn);
}
// ///////////////////////////////////////////////////////////////////////////
//
// specialized pointer analysis
//
// ///////////////////////////////////////////////////////////////////////////
protected static class AstJavaConstraintVisitor extends AstConstraintVisitor implements AstJavaInstructionVisitor {
public AstJavaConstraintVisitor(
AstSSAPropagationCallGraphBuilder builder,
CGNode node)
{
super(builder, node);
}
/**
* For each of objKey's instance keys ik, adds the constraint lvalKey = EORK(ik,cls),
* where EORK(ik,cls) will be made equivalent to the actual enclosing class by
* the handleNew() function below.
* @param lvalKey
* @param cls
* @param objKey
*/
private void handleEnclosingObject(final PointerKey lvalKey, final IClass cls, final PointerKey objKey) {
SymbolTable symtab = ir.getSymbolTable();
int objVal;
if (objKey instanceof LocalPointerKey) {
objVal = ((LocalPointerKey) objKey).getValueNumber();
} else {
objVal = 0;
}
if (objVal > 0 && contentsAreInvariant(symtab, du, objVal)) {
system.recordImplicitPointsToSet(objKey);
InstanceKey[] objs = getInvariantContents(objVal);
for (InstanceKey obj : objs) {
PointerKey enclosing = new EnclosingObjectReferenceKey(obj, cls);
system.newConstraint(lvalKey, assignOperator, enclosing);
}
} else {
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
2013-06-25 15:57:37 +00:00
@Override
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
IntSetVariable<?> tv = rhs;
if (tv.getValue() != null) {
tv.getValue().foreach(ptr -> {
InstanceKey iKey = system.getInstanceKey(ptr);
PointerKey enclosing = new EnclosingObjectReferenceKey(iKey, cls);
system.newConstraint(lvalKey, assignOperator, enclosing);
});
}
return NOT_CHANGED;
}
2013-06-25 15:57:37 +00:00
@Override
public int hashCode() {
return System.identityHashCode(this);
}
2013-06-25 15:57:37 +00:00
@Override
public boolean equals(Object o) {
return o == this;
}
2013-06-25 15:57:37 +00:00
@Override
public String toString() {
return "enclosing objects of " + objKey;
}
}, objKey);
}
}
2013-06-25 15:57:37 +00:00
@Override
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
PointerKey lvalKey = getPointerKeyForLocal(inst.getDef());
PointerKey objKey = getPointerKeyForLocal(1);
IClass cls = getClassHierarchy().lookupClass(inst.getEnclosingType());
handleEnclosingObject(lvalKey, cls, objKey);
}
2013-06-25 15:57:37 +00:00
@Override
public void visitNew(SSANewInstruction instruction) {
super.visitNew(instruction);
InstanceKey iKey = getInstanceKeyForAllocation(instruction.getNewSite());
if (iKey != null) {
IClass klass = iKey.getConcreteType();
// in the case of a AstJavaNewEnclosingInstruction (a new instruction like outer.new Bla()),
// we may need to record the instance keys if the pointer key outer is invariant (and thus implicit)
InstanceKey enclosingInvariantKeys[] = null;
if (klass instanceof JavaClass) {
IClass enclosingClass = ((JavaClass) klass).getEnclosingClass(); // the immediate enclosing class.
if (enclosingClass != null) {
IClass currentCls = node.getMethod().getDeclaringClass();
PointerKey objKey;
if ( instruction instanceof AstJavaNewEnclosingInstruction ) {
int enclosingVal = ((AstJavaNewEnclosingInstruction) instruction).getEnclosing();
SymbolTable symtab = ir.getSymbolTable();
// pk 'outer' is invariant, which means it's implicit, so can't add a constraint with the pointer key.
// we should just add constraints directly to the instance keys (below)
if ( contentsAreInvariant(symtab, du, enclosingVal) )
enclosingInvariantKeys = getInvariantContents(enclosingVal);
// what happens if objKey is implicit but the contents aren't invariant?! (it this possible?) big trouble!
objKey = getPointerKeyForLocal(enclosingVal);
}
else
objKey = getPointerKeyForLocal(1);
System.err.println(("class is " + klass + ", enclosing is " + enclosingClass + ", method is " + node.getMethod()));
if (node.getMethod().isSynthetic()) {
return;
}
currentCls = enclosingClass;
PointerKey x = new EnclosingObjectReferenceKey(iKey, currentCls);
if ( enclosingInvariantKeys != null )
for ( InstanceKey obj: enclosingInvariantKeys )
system.newConstraint(x, obj);
else
system.newConstraint(x, assignOperator, objKey);
// If the immediate inclosing class is not a top-level class, we must make EORKs for all enclosing classes up to the top level.
// for instance, if we have "D d = c.new D()", and c is of type A$B$C, methods in D may reference variables and functions from
// A, B, and C. Therefore we must also make the links from EORK(allocsite of d,enc class B) and EORK(allocsite of d,en class A).
// We do this by getting the enclosing class of C and making a link from EORK(d,B) -> EORK(c,B), etc.
currentCls = ((JavaClass) currentCls).getEnclosingClass();
while (currentCls != null) {
x = new EnclosingObjectReferenceKey(iKey, currentCls); // make EORK(d,B), EORK(d,A), etc.
handleEnclosingObject(x, currentCls, objKey);
// objKey is the pointer key representing the immediate inner class.
// handleEnclosingObject finds x's instance keys and for each one "ik" links x to EORK(ik,currentCls)
// thus, for currentCls=B, it will find the allocation site of c and make a link from EORK(d,B) to EORK(c,B)
currentCls = ((JavaClass) currentCls).getEnclosingClass();
}
}
}
}
}
2013-06-25 15:57:37 +00:00
@Override
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
visitInvokeInternal(instruction, new DefaultInvariantComputer());
}
}
2013-06-25 15:57:37 +00:00
@Override
2015-04-06 01:19:56 +00:00
public ConstraintVisitor makeVisitor(CGNode node) {
return new AstJavaConstraintVisitor(this, node);
}
@Override
protected boolean sameMethod(CGNode opNode, String definingMethod) {
MethodReference reference = opNode.getMethod().getReference();
String selector = reference.getSelector().toString();
String containingClass = reference.getDeclaringClass().getName().toString();
return definingMethod.equals(containingClass + "/" + selector);
}
2015-04-06 01:19:56 +00:00
@Override
public GlobalObjectKey getGlobalObject(Atom language) {
Assertions.UNREACHABLE();
return null;
}
}