support Method.invoke
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2625 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
52938ed6d8
commit
2c388b7744
|
@ -218,8 +218,7 @@ public class JavaLangClassContextInterpreter implements SSAContextInterpreter {
|
|||
*/
|
||||
private SSAInstruction[] getParticularMethodStatements(MethodReference ref, Collection<IMethod> returnValues, JavaTypeContext context, Map<Integer, ConstantValue> constants) {
|
||||
ArrayList<SSAInstruction> statements = new ArrayList<SSAInstruction>();
|
||||
int nextLocal = ref.getNumberOfParameters()+1;
|
||||
int retValue = nextLocal++;
|
||||
int nextLocal = ref.getNumberOfParameters()+2;
|
||||
IClass cls = context.getType().getType();
|
||||
if (cls != null) {
|
||||
for (IMethod m : returnValues) {
|
||||
|
@ -227,7 +226,6 @@ public class JavaLangClassContextInterpreter implements SSAContextInterpreter {
|
|||
constants.put(c, new ConstantValue(m));
|
||||
SSAReturnInstruction R = new SSAReturnInstruction(c, false);
|
||||
statements.add(R);
|
||||
retValue++;
|
||||
}
|
||||
} else {
|
||||
// SJF: This is incorrect. TODO: fix and enable.
|
||||
|
|
|
@ -32,7 +32,7 @@ public class ReflectionContextInterpreter extends DelegatingSSAContextInterprete
|
|||
|
||||
private ReflectionContextInterpreter(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache,
|
||||
ReflectionSpecification userSpec) {
|
||||
super(new ConstructorNewInstanceContextInterpreter(), new DelegatingSSAContextInterpreter(
|
||||
super(new ReflectiveInvocationInterpreter(), new DelegatingSSAContextInterpreter(
|
||||
new JavaLangClassContextInterpreter(), new DelegatingSSAContextInterpreter(new DelegatingSSAContextInterpreter(
|
||||
new ForNameContextInterpreter(), new ClassNewInstanceContextInterpreter(cha)), new FactoryBypassInterpreter(options,
|
||||
cache, userSpec))));
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ReflectionContextSelector extends DelegatingContextSelector {
|
|||
* First check "forName" logic, then factory logic.
|
||||
*/
|
||||
private ReflectionContextSelector(IClassHierarchy cha, MethodTargetSelector methodTargetSelector) {
|
||||
super(new ConstructorNewInstanceContextSelector(),
|
||||
super(new ReflectiveInvocationSelector(),
|
||||
new DelegatingContextSelector(new JavaLangClassContextSelector(),
|
||||
new DelegatingContextSelector(new DelegatingContextSelector(new ForNameContextSelector(), new ClassNewInstanceContextSelector()),
|
||||
new FactoryContextSelector(cha, methodTargetSelector))));
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.ibm.wala.ipa.callgraph.propagation.ReceiverInstanceContext;
|
|||
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
|
||||
import com.ibm.wala.ipa.summaries.SyntheticIR;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction.Dispatch;
|
||||
import com.ibm.wala.ssa.ConstantValue;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
|
@ -35,30 +36,31 @@ import com.ibm.wala.ssa.SSAInvokeInstruction;
|
|||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SSAReturnInstruction;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
/**
|
||||
* An {@link SSAContextInterpreter} specialized to interpret Constructor.newInstance in a {@link JavaTypeContext} which
|
||||
* represents the point-type of the class object created by the call.
|
||||
* An {@link SSAContextInterpreter} specialized to interpret reflective invocations such as Constructor.newInstance and
|
||||
* Method.invoke on an {@link IMethod} constant.
|
||||
*
|
||||
* @author pistoia
|
||||
* @author sjfink
|
||||
*/
|
||||
public class ConstructorNewInstanceContextInterpreter extends AbstractReflectionInterpreter {
|
||||
public class ReflectiveInvocationInterpreter extends AbstractReflectionInterpreter {
|
||||
|
||||
public final static Atom newInstanceAtom = Atom.findOrCreateUnicodeAtom("newInstance");
|
||||
public final static MethodReference CTOR_NEW_INSTANCE = MethodReference.findOrCreate(TypeReference.JavaLangReflectConstructor,
|
||||
"newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
|
||||
private final static Descriptor newInstanceDescriptor = Descriptor.findOrCreateUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
|
||||
public final static MethodReference NEW_INSTANCE_REF = MethodReference.findOrCreate(TypeReference.JavaLangReflectConstructor,
|
||||
newInstanceAtom, newInstanceDescriptor);
|
||||
public final static MethodReference METHOD_INVOKE = MethodReference.findOrCreate(TypeReference.JavaLangReflectMethod, "invoke",
|
||||
"(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter#getIR(com.ibm.wala.ipa.callgraph.CGNode)
|
||||
*/
|
||||
public IR getIR(CGNode node) {
|
||||
if (node == null) {
|
||||
throw new IllegalArgumentException("node is null");
|
||||
|
@ -66,13 +68,16 @@ public class ConstructorNewInstanceContextInterpreter extends AbstractReflection
|
|||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(understands(node));
|
||||
}
|
||||
ReceiverInstanceContext recv = (ReceiverInstanceContext)node.getContext();
|
||||
ReceiverInstanceContext recv = (ReceiverInstanceContext) node.getContext();
|
||||
ConstantKey c = (ConstantKey) recv.getReceiver();
|
||||
IMethod m = (IMethod) c.getValue();
|
||||
IR result = makeIR(node.getMethod(), m, recv);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter#getNumberOfStatements(com.ibm.wala.ipa.callgraph.CGNode)
|
||||
*/
|
||||
public int getNumberOfStatements(CGNode node) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(understands(node));
|
||||
|
@ -80,6 +85,9 @@ public class ConstructorNewInstanceContextInterpreter extends AbstractReflection
|
|||
return getIR(node).getInstructions().length;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#understands(com.ibm.wala.ipa.callgraph.CGNode)
|
||||
*/
|
||||
public boolean understands(CGNode node) {
|
||||
if (node == null) {
|
||||
throw new IllegalArgumentException("node is null");
|
||||
|
@ -87,9 +95,12 @@ public class ConstructorNewInstanceContextInterpreter extends AbstractReflection
|
|||
if (!(node.getContext() instanceof ReceiverInstanceContext)) {
|
||||
return false;
|
||||
}
|
||||
return node.getMethod().getReference().equals(NEW_INSTANCE_REF);
|
||||
return node.getMethod().getReference().equals(METHOD_INVOKE) || node.getMethod().getReference().equals(CTOR_NEW_INSTANCE);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#iterateNewSites(com.ibm.wala.ipa.callgraph.CGNode)
|
||||
*/
|
||||
public Iterator<NewSiteReference> iterateNewSites(CGNode node) {
|
||||
if (node == null) {
|
||||
throw new IllegalArgumentException("node is null");
|
||||
|
@ -100,6 +111,9 @@ public class ConstructorNewInstanceContextInterpreter extends AbstractReflection
|
|||
return getIR(node).iterateNewSites();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#iterateCallSites(com.ibm.wala.ipa.callgraph.CGNode)
|
||||
*/
|
||||
public Iterator<CallSiteReference> iterateCallSites(CGNode node) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(understands(node));
|
||||
|
@ -107,36 +121,62 @@ public class ConstructorNewInstanceContextInterpreter extends AbstractReflection
|
|||
return getIR(node).iterateCallSites();
|
||||
}
|
||||
|
||||
private IR makeIR(IMethod method, IMethod ctor, ReceiverInstanceContext context) {
|
||||
/**
|
||||
* TODO: clean this up.
|
||||
*/
|
||||
private IR makeIR(IMethod method, IMethod target, ReceiverInstanceContext context) {
|
||||
SpecializedMethod m = new SpecializedMethod(method, method.getDeclaringClass(), method.isStatic(), false);
|
||||
|
||||
Map<Integer, ConstantValue> constants = HashMapFactory.make();
|
||||
|
||||
int nextLocal = method.getNumberOfParameters() + 1;
|
||||
|
||||
int nargs = ctor.getNumberOfParameters();
|
||||
int nargs = target.getNumberOfParameters();
|
||||
int args[] = new int[nargs];
|
||||
int i = 0;
|
||||
int pc = 0;
|
||||
int parametersVn = -1;
|
||||
|
||||
TypeReference allocatedType = ctor.getDeclaringClass().getReference();
|
||||
if (method.getReference().equals(CTOR_NEW_INSTANCE)) {
|
||||
// allocate the new object constructed
|
||||
TypeReference allocatedType = target.getDeclaringClass().getReference();
|
||||
m.addInstruction(allocatedType, new SSANewInstruction(args[i++] = nextLocal++, NewSiteReference.make(pc++, allocatedType)),
|
||||
true);
|
||||
parametersVn = 2;
|
||||
} else {
|
||||
// set up args[0] == v2, the receiver for method.invoke.
|
||||
args[i++] = 2;
|
||||
parametersVn = 3;
|
||||
}
|
||||
|
||||
// load each of the parameters into a local variable, args[something]
|
||||
for (int j = 1; j < nargs; j++) {
|
||||
int indexConst = nextLocal++;
|
||||
m.addInstruction(null, new SSAArrayLoadInstruction(args[i++] = nextLocal++, 2, indexConst, TypeReference.JavaLangObject),
|
||||
false);
|
||||
m.addInstruction(null, new SSAArrayLoadInstruction(args[i++] = nextLocal++, parametersVn, indexConst,
|
||||
TypeReference.JavaLangObject), false);
|
||||
constants.put(new Integer(indexConst), new ConstantValue(j - 1));
|
||||
pc++;
|
||||
}
|
||||
|
||||
int exceptions = nextLocal++;
|
||||
int result = -1;
|
||||
|
||||
m.addInstruction(null, new SSAInvokeInstruction(args, exceptions, CallSiteReference.make(pc++, ctor.getReference(),
|
||||
// emit the dispatch and return instructions
|
||||
if (method.getReference().equals(CTOR_NEW_INSTANCE)) {
|
||||
m.addInstruction(null, new SSAInvokeInstruction(args, exceptions, CallSiteReference.make(pc++, target.getReference(),
|
||||
IInvokeInstruction.Dispatch.SPECIAL)), false);
|
||||
|
||||
m.addInstruction(null, new SSAReturnInstruction(args[0], false), false);
|
||||
} else {
|
||||
Dispatch d = target.isStatic() ? Dispatch.STATIC : Dispatch.VIRTUAL;
|
||||
if (target.getReturnType().equals(TypeReference.Void)) {
|
||||
m.addInstruction(null, new SSAInvokeInstruction(args, exceptions, CallSiteReference.make(pc++, target.getReference(), d)),
|
||||
false);
|
||||
} else {
|
||||
result = nextLocal++;
|
||||
m.addInstruction(null, new SSAInvokeInstruction(result, args, exceptions, CallSiteReference.make(pc++, target
|
||||
.getReference(), d)), false);
|
||||
m.addInstruction(null, new SSAReturnInstruction(result, false), false);
|
||||
}
|
||||
}
|
||||
|
||||
SSAInstruction[] instrs = new SSAInstruction[m.allInstructions.size()];
|
||||
m.allInstructions.<SSAInstruction> toArray(instrs);
|
|
@ -21,13 +21,15 @@ import com.ibm.wala.ipa.callgraph.propagation.ReceiverInstanceContext;
|
|||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
* A {@link ContextSelector} to intercept calls to Constructor.newInstance()
|
||||
* A {@link ContextSelector} to intercept calls to reflective method invocations such as
|
||||
* Constructor.newInstance and Method.invoke
|
||||
*
|
||||
* @author pistoia
|
||||
* @author sjfink
|
||||
*/
|
||||
class ConstructorNewInstanceContextSelector implements ContextSelector {
|
||||
class ReflectiveInvocationSelector implements ContextSelector {
|
||||
|
||||
public ConstructorNewInstanceContextSelector() {
|
||||
public ReflectiveInvocationSelector() {
|
||||
}
|
||||
|
||||
public boolean allSitesDispatchIdentically(CGNode node, CallSiteReference site) {
|
||||
|
@ -38,7 +40,6 @@ class ConstructorNewInstanceContextSelector implements ContextSelector {
|
|||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) {
|
||||
if (mayUnderstand(caller, site, callee, receiver)) {
|
||||
return new ReceiverInstanceContext(receiver);
|
||||
|
@ -50,7 +51,7 @@ class ConstructorNewInstanceContextSelector implements ContextSelector {
|
|||
* This object may understand a dispatch to Constructor.newInstance().
|
||||
*/
|
||||
public boolean mayUnderstand(CGNode caller, CallSiteReference site, IMethod targetMethod, InstanceKey instance) {
|
||||
if (targetMethod.getReference().equals(ConstructorNewInstanceContextInterpreter.NEW_INSTANCE_REF) && isConstructorConstant(instance)) {
|
||||
if (targetMethod.getReference().equals(ReflectiveInvocationInterpreter.METHOD_INVOKE) || isConstructorConstant(instance)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
|
@ -269,7 +269,7 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
|
|||
}
|
||||
|
||||
private boolean isReflectiveType(TypeReference type) {
|
||||
return type.equals(TypeReference.JavaLangReflectConstructor);
|
||||
return type.equals(TypeReference.JavaLangReflectConstructor) || type.equals(TypeReference.JavaLangReflectMethod);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue