reflection support for java.lang.ClassLoader.loadClass
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3015 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
ec663911fe
commit
45f74284a7
|
@ -272,7 +272,9 @@
|
|||
</method>
|
||||
<method name="findLoadedClass"
|
||||
descriptor="(Ljava/lang/String;)Ljava/lang/Class;">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<call type="static" name="forName"
|
||||
class="Ljava/lang/Class" descriptor="(Ljava/lang/String;)Ljava/lang/Class;"
|
||||
arg0="arg0" def="x" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getCallerClassLoader"
|
||||
|
|
|
@ -30,29 +30,17 @@ import com.ibm.wala.ssa.SSALoadClassInstruction;
|
|||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SSAReturnInstruction;
|
||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||
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.NonNullSingletonIterator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
/**
|
||||
* An {@link SSAContextInterpreter} specialized to interpret Class.forName in a {@link JavaTypeContext} which
|
||||
* represents the point-type of the class object created by the call.
|
||||
*
|
||||
* @author pistoia
|
||||
* An {@link SSAContextInterpreter} specialized to interpret reflective class factories (e.g. Class.forName()) in a
|
||||
* {@link JavaTypeContext} which represents the point-type of the class object created by the call.
|
||||
*/
|
||||
public class ForNameContextInterpreter implements SSAContextInterpreter {
|
||||
|
||||
public final static Atom forNameAtom = Atom.findOrCreateUnicodeAtom("forName");
|
||||
|
||||
private final static Descriptor forNameDescriptor = Descriptor.findOrCreateUTF8("(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
|
||||
public final static MethodReference FOR_NAME_REF = MethodReference.findOrCreate(TypeReference.JavaLangClass, forNameAtom,
|
||||
forNameDescriptor);
|
||||
public class ClassFactoryContextInterpreter implements SSAContextInterpreter {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
|
@ -77,15 +65,22 @@ public class ForNameContextInterpreter implements SSAContextInterpreter {
|
|||
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");
|
||||
}
|
||||
if (!(node.getContext() instanceof JavaTypeContext))
|
||||
if (!(node.getContext() instanceof JavaTypeContext)) {
|
||||
return false;
|
||||
return node.getMethod().getReference().equals(FOR_NAME_REF);
|
||||
}
|
||||
return ClassFactoryContextSelector.isClassFactory(node.getMethod());
|
||||
}
|
||||
|
||||
/*
|
||||
* @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");
|
||||
|
@ -101,6 +96,9 @@ public class ForNameContextInterpreter implements SSAContextInterpreter {
|
|||
return EmptyIterator.instance();
|
||||
}
|
||||
|
||||
/*
|
||||
* @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));
|
||||
|
@ -108,6 +106,7 @@ public class ForNameContextInterpreter implements SSAContextInterpreter {
|
|||
return EmptyIterator.instance();
|
||||
}
|
||||
|
||||
|
||||
private SSAInstruction[] makeStatements(JavaTypeContext context) {
|
||||
ArrayList<SSAInstruction> statements = new ArrayList<SSAInstruction>();
|
||||
// vn1 is the string parameter
|
|
@ -22,36 +22,74 @@ import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
import com.ibm.wala.util.strings.StringStuff;
|
||||
|
||||
/**
|
||||
* A {@link ContextSelector} to intercept calls to Class.forName() when the parameter is a string constant
|
||||
*
|
||||
* @author pistoia
|
||||
* A {@link ContextSelector} to intercept calls to reflective class factories (e.g. Class.forName()) when the parameter is a string
|
||||
* constant
|
||||
*/
|
||||
class ForNameContextSelector implements ContextSelector {
|
||||
class ClassFactoryContextSelector implements ContextSelector {
|
||||
|
||||
public ForNameContextSelector() {
|
||||
public final static Atom forNameAtom = Atom.findOrCreateUnicodeAtom("forName");
|
||||
|
||||
private final static Descriptor forNameDescriptor = Descriptor.findOrCreateUTF8("(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
|
||||
public final static MethodReference FOR_NAME_REF = MethodReference.findOrCreate(TypeReference.JavaLangClass, forNameAtom,
|
||||
forNameDescriptor);
|
||||
|
||||
public final static Atom loadClassAtom = Atom.findOrCreateUnicodeAtom("loadClass");
|
||||
|
||||
private final static Descriptor loadClassDescriptor = Descriptor.findOrCreateUTF8("(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
|
||||
private final static TypeReference CLASSLOADER = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
|
||||
"Ljava/lang/ClassLoader");
|
||||
|
||||
public final static MethodReference LOAD_CLASS_REF = MethodReference
|
||||
.findOrCreate(CLASSLOADER, loadClassAtom, loadClassDescriptor);
|
||||
|
||||
public ClassFactoryContextSelector() {
|
||||
}
|
||||
|
||||
public static boolean isClassFactory(IMethod m) {
|
||||
if (m.getReference().equals(FOR_NAME_REF)) {
|
||||
return true;
|
||||
}
|
||||
if (m.getReference().equals(LOAD_CLASS_REF)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getUseOfStringParameter(SSAAbstractInvokeInstruction call) {
|
||||
if (call.isStatic()) {
|
||||
return call.getUse(0);
|
||||
} else {
|
||||
return call.getUse(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@link CallSiteReference} invokes Class.forName(s) and s is a string constant, return a
|
||||
* {@link JavaTypeContext} representing the type named by s, if we can resolve it in the {@link IClassHierarchy}.
|
||||
* If the {@link CallSiteReference} invokes Class.forName(s) and s is a string constant, return a {@link JavaTypeContext}
|
||||
* representing the type named by s, if we can resolve it in the {@link IClassHierarchy}.
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.ContextSelector#getCalleeTarget(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.classLoader.CallSiteReference, com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.wala.ipa.callgraph.propagation.InstanceKey)
|
||||
*/
|
||||
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) {
|
||||
if (callee.getReference().equals(ForNameContextInterpreter.FOR_NAME_REF)) {
|
||||
if (isClassFactory(callee)) {
|
||||
IR ir = caller.getIR();
|
||||
SymbolTable symbolTable = ir.getSymbolTable();
|
||||
SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site);
|
||||
if (invokeInstructions.length != 1) {
|
||||
return null;
|
||||
}
|
||||
int use = invokeInstructions[0].getUse(0);
|
||||
int use = getUseOfStringParameter(invokeInstructions[0]);
|
||||
if (symbolTable.isStringConstant(use)) {
|
||||
String className = StringStuff.deployment2CanonicalTypeString(symbolTable.getStringValue(use));
|
||||
TypeReference t = TypeReference.findOrCreate(caller.getMethod().getDeclaringClass().getClassLoader().getReference(),
|
||||
|
@ -69,14 +107,14 @@ 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.getReference().equals(ForNameContextInterpreter.FOR_NAME_REF)) {
|
||||
if (isClassFactory(targetMethod)) {
|
||||
IR ir = caller.getIR();
|
||||
SymbolTable symbolTable = ir.getSymbolTable();
|
||||
SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site);
|
||||
if (invokeInstructions.length != 1) {
|
||||
return false;
|
||||
}
|
||||
int use = invokeInstructions[0].getUse(0);
|
||||
int use = getUseOfStringParameter(invokeInstructions[0]);
|
||||
if (symbolTable.isStringConstant(use)) {
|
||||
return true;
|
||||
}
|
|
@ -34,7 +34,7 @@ public class ReflectionContextInterpreter extends DelegatingSSAContextInterprete
|
|||
ReflectionSpecification userSpec) {
|
||||
super(new ReflectiveInvocationInterpreter(), new DelegatingSSAContextInterpreter(new DelegatingSSAContextInterpreter(
|
||||
new GetClassContextInterpeter(), new JavaLangClassContextInterpreter()), new DelegatingSSAContextInterpreter(
|
||||
new DelegatingSSAContextInterpreter(new ForNameContextInterpreter(), new ClassNewInstanceContextInterpreter(cha)),
|
||||
new DelegatingSSAContextInterpreter(new ClassFactoryContextInterpreter(), new ClassNewInstanceContextInterpreter(cha)),
|
||||
new FactoryBypassInterpreter(options, cache, userSpec))));
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ReflectionContextSelector extends DelegatingContextSelector {
|
|||
*/
|
||||
private ReflectionContextSelector() {
|
||||
super(new ReflectiveInvocationSelector(), new DelegatingContextSelector(new JavaLangClassContextSelector(),
|
||||
new DelegatingContextSelector(new DelegatingContextSelector(new DelegatingContextSelector(new ForNameContextSelector(),
|
||||
new DelegatingContextSelector(new DelegatingContextSelector(new DelegatingContextSelector(new ClassFactoryContextSelector(),
|
||||
new GetClassContextSelector()), new ClassNewInstanceContextSelector()), new FactoryContextSelector())));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue