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:
sjfink 2008-09-02 14:57:36 +00:00
parent ec663911fe
commit 45f74284a7
5 changed files with 70 additions and 31 deletions

View File

@ -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"

View File

@ -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

View File

@ -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;
}

View File

@ -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))));
}

View File

@ -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())));
}