From fffb7ac8bce39fe798edea448187ba5b2defc7f9 Mon Sep 17 00:00:00 2001 From: sjfink Date: Tue, 5 Feb 2008 21:21:33 +0000 Subject: [PATCH] bug fixes and new tests for new Class.forName processing. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2544 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../reflection/ForNameContextSelector.java | 10 +-- .../reflection/ReflectionContextSelector.java | 2 +- .../wala/ipa/callgraph/ContextSelector.java | 1 - .../impl/DelegatingContextSelector.java | 1 - .../SSAPropagationCallGraphBuilder.java | 5 +- .../cfa/ContainerContextSelector.java | 5 ++ .../src/com/ibm/wala/ipa/slicer/PDG.java | 75 ++++++++++--------- 7 files changed, 53 insertions(+), 46 deletions(-) diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ForNameContextSelector.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ForNameContextSelector.java index 62fb4923a..87181ebf6 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ForNameContextSelector.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ForNameContextSelector.java @@ -32,11 +32,7 @@ import com.ibm.wala.util.strings.StringStuff; */ class ForNameContextSelector implements ContextSelector { - private final IMethod forNameMethod; - - public ForNameContextSelector(final IClassHierarchy cha) { - this.forNameMethod = cha.resolveMethod(ForNameContextInterpreter.FOR_NAME_REF); - assert forNameMethod != null; + public ForNameContextSelector() { } public boolean allSitesDispatchIdentically(CGNode node, CallSiteReference site) { @@ -56,7 +52,7 @@ class ForNameContextSelector implements ContextSelector { * com.ibm.wala.ipa.callgraph.propagation.InstanceKey) */ public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) { - if (callee.equals(forNameMethod)) { + if (callee.getReference().equals(ForNameContextInterpreter.FOR_NAME_REF)) { IR ir = caller.getIR(); SymbolTable symbolTable = ir.getSymbolTable(); SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site); @@ -81,7 +77,7 @@ class ForNameContextSelector implements ContextSelector { * This object may understand a dispatch to Class.forName(s) when s is a string constant. */ public boolean mayUnderstand(CGNode caller, CallSiteReference site, IMethod targetMethod, InstanceKey instance) { - if (targetMethod.equals(forNameMethod)) { + if (targetMethod.getReference().equals(ForNameContextInterpreter.FOR_NAME_REF)) { IR ir = caller.getIR(); SymbolTable symbolTable = ir.getSymbolTable(); SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site); diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectionContextSelector.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectionContextSelector.java index 2180ce4e2..7330c5fbd 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectionContextSelector.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectionContextSelector.java @@ -31,7 +31,7 @@ public class ReflectionContextSelector extends DelegatingContextSelector { * First check "forName" logic, then factory logic. */ private ReflectionContextSelector(IClassHierarchy cha, MethodTargetSelector methodTargetSelector) { - super(new ForNameContextSelector(cha), new FactoryContextSelector(cha, methodTargetSelector)); + super(new ForNameContextSelector(), new FactoryContextSelector(cha, methodTargetSelector)); } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/ContextSelector.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/ContextSelector.java index 4067e13ec..d67b7095b 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/ContextSelector.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/ContextSelector.java @@ -15,7 +15,6 @@ import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; /** - * * An interface to an object which helps control context-sensitivity * * @author sfink diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/DelegatingContextSelector.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/DelegatingContextSelector.java index e447f74f8..09edc1cb7 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/DelegatingContextSelector.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/DelegatingContextSelector.java @@ -41,7 +41,6 @@ public class DelegatingContextSelector implements ContextSelector { } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) { - if (DEBUG) { Trace.println("getCalleeTarget " + caller + " " + site + " " + callee); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java index 99075604c..80140c7f4 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java @@ -853,7 +853,6 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap } protected void visitGetInternal(int lval, int ref, boolean isStatic, FieldReference field) { - if (DEBUG) { System.err.println("visitGet " + field); } @@ -1363,6 +1362,10 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap public void visitLoadClass(SSALoadClassInstruction instruction) { PointerKey def = getPointerKeyForLocal(instruction.getDef()); InstanceKey iKey = getInstanceKeyForClassObject(instruction.getLoadedClass()); + IClass klass = getClassHierarchy().lookupClass(instruction.getLoadedClass()); + if (klass != null) { + processClassInitializer(klass); + } if (!contentsAreInvariant(symbolTable, du, instruction.getDef())) { system.newConstraint(def, iKey); diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/cfa/ContainerContextSelector.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/cfa/ContainerContextSelector.java index e3d77b668..28d7610bb 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/cfa/ContainerContextSelector.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/cfa/ContainerContextSelector.java @@ -51,6 +51,7 @@ public class ContainerContextSelector implements ContextSelector { public final static TypeReference SyntheticSystem = TypeReference.findOrCreate(ClassLoaderReference.Primordial, SyntheticSystemName); + public final static TypeReference JavaUtilHashtable = TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Ljava/util/Hashtable"); public final static Atom arraycopyAtom = Atom.findOrCreateUnicodeAtom("arraycopy"); @@ -64,6 +65,7 @@ public class ContainerContextSelector implements ContextSelector { private final static MethodReference ArraysCopyOf = MethodReference.findOrCreate(Arrays, "copyOf", "([Ljava/lang/Object;I)[Ljava/lang/Object;"); private final static MethodReference ArraysCopyOf2 = MethodReference.findOrCreate(Arrays, "copyOf", "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;"); private final static MethodReference StringValueOf = MethodReference.findOrCreate(TypeReference.JavaLangString, "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;"); + private final static MethodReference HashtableNewEntry = MethodReference.findOrCreate(JavaUtilHashtable, "newEntry", "(Ljava/lang/Object;Ljava/lang/Object;I)Ljava/util/Hashtable$Entry;"); /** * The governing class hierarchy. @@ -141,6 +143,9 @@ public class ContainerContextSelector implements ContextSelector { if (m.equals(StringValueOf)) { return true; } + if (m.equals(HashtableNewEntry)) { + return true; + } return false; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/slicer/PDG.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/slicer/PDG.java index 6466e6f74..d5270328e 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/slicer/PDG.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/slicer/PDG.java @@ -12,6 +12,7 @@ package com.ibm.wala.ipa.slicer; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -81,8 +82,6 @@ public class PDG implements NumberedGraph { private final CGNode node; - private Map instructionIndices; - private Statement[] paramCalleeStatements; private Statement[] returnStatements; @@ -159,18 +158,26 @@ public class PDG implements NumberedGraph { this.ignoreAllocHeapDefs = ignoreAllocHeapDefs; } + /** + * WARNING: Since we're using a {@link HashMap} of {@link SSAInstruction}s, and equals() of {@link SSAInstruction} + * assumes a canonical representative for each instruction, we must ensure that we use the same IR object + * throughout initialization!! + */ private void populate() { if (!isPopulated) { + // ensure that we keep the single, canonical IR live throughout initialization, while the instructionIndices map is live. + IR ir = node.getIR(); isPopulated = true; - instructionIndices = computeInstructionIndices(node.getIR()); - createNodes(ref, cOptions); - createScalarEdges(cOptions); + + Map instructionIndices = computeInstructionIndices(ir); + createNodes(ref, cOptions, ir); + createScalarEdges(cOptions, ir, instructionIndices); } } - private void createScalarEdges(ControlDependenceOptions cOptions) { - createScalarDataDependenceEdges(); - createControlDependenceEdges(cOptions); + private void createScalarEdges(ControlDependenceOptions cOptions, IR ir, Map instructionIndices) { + createScalarDataDependenceEdges(ir, instructionIndices); + createControlDependenceEdges(cOptions, ir, instructionIndices); } /** @@ -198,12 +205,10 @@ public class PDG implements NumberedGraph { /** * Create all control dependence edges in this PDG. */ - private void createControlDependenceEdges(ControlDependenceOptions cOptions) { + private void createControlDependenceEdges(ControlDependenceOptions cOptions, IR ir,Map instructionIndices) { if (cOptions.equals(ControlDependenceOptions.NONE)) { return; } - IR ir; - ir = node.getIR(); if (ir == null) { return; } @@ -237,7 +242,7 @@ public class PDG implements NumberedGraph { // should have no control dependent successors. // leave src null. } else { - src = ssaInstruction2Statement(s); + src = ssaInstruction2Statement(s, ir, instructionIndices); // add edges from call statements to parameter passing and return // SJF: Alexey and I think that we should just define ParamStatements // as @@ -266,7 +271,7 @@ public class PDG implements NumberedGraph { for (Iterator it2 = bb2.iterator(); it2.hasNext();) { SSAInstruction st = (SSAInstruction) it2.next(); if (st != null) { - Statement dest = ssaInstruction2Statement(st); + Statement dest = ssaInstruction2Statement(st, ir, instructionIndices); assert src != null; delegate.addEdge(src, dest); } @@ -284,7 +289,7 @@ public class PDG implements NumberedGraph { // this is control dependent on the method entry. for (IInstruction s : bb) { SSAInstruction st = (SSAInstruction) s; - Statement dest = ssaInstruction2Statement(st); + Statement dest = ssaInstruction2Statement(st, ir, instructionIndices); delegate.addEdge(methodEntry, dest); } } @@ -308,17 +313,18 @@ public class PDG implements NumberedGraph { * @param pa * @param mod */ - private void createScalarDataDependenceEdges() { + private void createScalarDataDependenceEdges(IR ir, Map instructionIndices) { if (dOptions.equals(DataDependenceOptions.NONE)) { return; } - IR ir = node.getIR(); if (ir == null) { return; } - DefUse DU = node.getDU(); + // this is tricky .. I'm explicitly creating a new DefUse to make sure it refers to the instructions we need from + // the "one true" ir of the moment. + DefUse DU = new DefUse(ir); SSAInstruction[] instructions = ir.getInstructions(); // @@ -331,7 +337,7 @@ public class PDG implements NumberedGraph { SSACFG.ExceptionHandlerBasicBlock ehbb = (SSACFG.ExceptionHandlerBasicBlock) bb; if (ehbb.getCatchInstruction() != null) { - Statement c = ssaInstruction2Statement(ehbb.getCatchInstruction()); + Statement c = ssaInstruction2Statement(ehbb.getCatchInstruction(), ir, instructionIndices); for (ISSABasicBlock pb : ir.getControlFlowGraph().getExceptionalPredecessors(ehbb)) { SSAInstruction pi = instructions[pb.getLastInstructionIndex()]; @@ -340,7 +346,7 @@ public class PDG implements NumberedGraph { if (pi instanceof SSAAbstractInvokeInstruction) { delegate.addEdge(new ExceptionalReturnCaller(node, pb.getLastInstructionIndex()), c); } else if (pi instanceof SSAAbstractThrowInstruction) { - delegate.addEdge(ssaInstruction2Statement(pi), c); + delegate.addEdge(ssaInstruction2Statement(pi, ir, instructionIndices), c); } } } @@ -391,7 +397,7 @@ public class PDG implements NumberedGraph { } } } - Statement u = ssaInstruction2Statement(use); + Statement u = ssaInstruction2Statement(use, ir, instructionIndices); delegate.addEdge(s, u); } } @@ -427,7 +433,7 @@ public class PDG implements NumberedGraph { } } } - Statement u = ssaInstruction2Statement(use); + Statement u = ssaInstruction2Statement(use, ir, instructionIndices); delegate.addEdge(s, u); } break; @@ -482,7 +488,7 @@ public class PDG implements NumberedGraph { delegate.addEdge(st, pac); } } else { - Statement ds = ssaInstruction2Statement(d); + Statement ds = ssaInstruction2Statement(d, ir, instructionIndices); delegate.addEdge(ds, pac); } } @@ -578,6 +584,7 @@ public class PDG implements NumberedGraph { return; } + // It's OK to create a new IR here; we're not keeping any hashing live up to this point IR ir = node.getIR(); if (ir == null) { return; @@ -710,14 +717,16 @@ public class PDG implements NumberedGraph { } /** - * Wrap an SSAInstruction in a Statement + * Wrap an {@link SSAInstruction} in a {@link Statement}. WARNING: Since we're using a {@link HashMap} of + * {@link SSAInstruction}s, and equals() of {@link SSAInstruction} assumes a canonical representative for each + * instruction, we must ensure that we use the same IR object throughout initialization!! */ - private Statement ssaInstruction2Statement(SSAInstruction s) { - return ssaInstruction2Statement(node, s, instructionIndices); + private Statement ssaInstruction2Statement(SSAInstruction s, IR ir, Map instructionIndices) { + return ssaInstruction2Statement(node, s, instructionIndices, ir); } public static synchronized Statement ssaInstruction2Statement(CGNode node, SSAInstruction s, - Map instructionIndices) { + Map instructionIndices, IR ir) { assert s != null; if (s instanceof SSAPhiInstruction) { SSAPhiInstruction phi = (SSAPhiInstruction) s; @@ -730,7 +739,7 @@ public class PDG implements NumberedGraph { } else { Integer x = instructionIndices.get(s); if (x == null) { - Assertions.UNREACHABLE(s.toString() + "\nnot found in map of\n" + node.getIR()); + Assertions.UNREACHABLE(s.toString() + "\nnot found in map of\n" + ir); } return new NormalStatement(node, x.intValue()); } @@ -783,11 +792,8 @@ public class PDG implements NumberedGraph { /** * Create all nodes in this PDG. Each node is a Statement. - * - * @param dOptions */ - private void createNodes(Map> ref, ControlDependenceOptions cOptions) { - IR ir = node.getIR(); + private void createNodes(Map> ref, ControlDependenceOptions cOptions, IR ir) { if (ir != null) { Collection visited = createNormalStatements(ir, ref); @@ -900,7 +906,7 @@ public class PDG implements NumberedGraph { visited.add(s); } if (s instanceof SSAAbstractInvokeInstruction) { - addParamPassingStatements(i, ref); + addParamPassingStatements(i, ref, ir); } } return visited; @@ -909,9 +915,8 @@ public class PDG implements NumberedGraph { /** * Create nodes in the graph corresponding to in/out parameter passing for a call instruction */ - private void addParamPassingStatements(int callIndex, Map> ref) { - - SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) node.getIR().getInstructions()[callIndex]; + private void addParamPassingStatements(int callIndex, Map> ref, IR ir) { + SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) ir.getInstructions()[callIndex]; Collection params = MapUtil.findOrCreateSet(callerParamStatements, call.getCallSite()); Collection rets = MapUtil.findOrCreateSet(callerReturnStatements, call.getCallSite()); for (int j = 0; j < call.getNumberOfUses(); j++) {