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>
<method name="findLoadedClass" <method name="findLoadedClass"
descriptor="(Ljava/lang/String;)Ljava/lang/Class;"> 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" /> <return value="x" />
</method> </method>
<method name="getCallerClassLoader" <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.SSAOptions;
import com.ibm.wala.ssa.SSAReturnInstruction; import com.ibm.wala.ssa.SSAReturnInstruction;
import com.ibm.wala.ssa.SSAThrowInstruction; import com.ibm.wala.ssa.SSAThrowInstruction;
import com.ibm.wala.types.Descriptor;
import com.ibm.wala.types.FieldReference; import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference; import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.EmptyIterator; import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator; import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.debug.Assertions; 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 * An {@link SSAContextInterpreter} specialized to interpret reflective class factories (e.g. Class.forName()) in a
* represents the point-type of the class object created by the call. * {@link JavaTypeContext} which represents the point-type of the class object created by the call.
*
* @author pistoia
*/ */
public class ForNameContextInterpreter implements SSAContextInterpreter { public class ClassFactoryContextInterpreter 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);
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@ -77,15 +65,22 @@ public class ForNameContextInterpreter implements SSAContextInterpreter {
return getIR(node).getInstructions().length; 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) { public boolean understands(CGNode node) {
if (node == null) { if (node == null) {
throw new IllegalArgumentException("node is null"); throw new IllegalArgumentException("node is null");
} }
if (!(node.getContext() instanceof JavaTypeContext)) if (!(node.getContext() instanceof JavaTypeContext)) {
return false; 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) { public Iterator<NewSiteReference> iterateNewSites(CGNode node) {
if (node == null) { if (node == null) {
throw new IllegalArgumentException("node is null"); throw new IllegalArgumentException("node is null");
@ -101,6 +96,9 @@ public class ForNameContextInterpreter implements SSAContextInterpreter {
return EmptyIterator.instance(); 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) { public Iterator<CallSiteReference> iterateCallSites(CGNode node) {
if (Assertions.verifyAssertions) { if (Assertions.verifyAssertions) {
Assertions._assert(understands(node)); Assertions._assert(understands(node));
@ -108,6 +106,7 @@ public class ForNameContextInterpreter implements SSAContextInterpreter {
return EmptyIterator.instance(); return EmptyIterator.instance();
} }
private SSAInstruction[] makeStatements(JavaTypeContext context) { private SSAInstruction[] makeStatements(JavaTypeContext context) {
ArrayList<SSAInstruction> statements = new ArrayList<SSAInstruction>(); ArrayList<SSAInstruction> statements = new ArrayList<SSAInstruction>();
// vn1 is the string parameter // 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.IR;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SymbolTable; 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.types.TypeReference;
import com.ibm.wala.util.strings.Atom;
import com.ibm.wala.util.strings.StringStuff; import com.ibm.wala.util.strings.StringStuff;
/** /**
* A {@link ContextSelector} to intercept calls to Class.forName() when the parameter is a string constant * A {@link ContextSelector} to intercept calls to reflective class factories (e.g. Class.forName()) when the parameter is a string
* * constant
* @author pistoia
*/ */
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 * If the {@link CallSiteReference} invokes Class.forName(s) and s is a string constant, return a {@link JavaTypeContext}
* {@link JavaTypeContext} representing the type named by s, if we can resolve it in the {@link IClassHierarchy}. * 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, * @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.classLoader.CallSiteReference, com.ibm.wala.classLoader.IMethod,
* com.ibm.wala.ipa.callgraph.propagation.InstanceKey) * com.ibm.wala.ipa.callgraph.propagation.InstanceKey)
*/ */
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) { 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(); IR ir = caller.getIR();
SymbolTable symbolTable = ir.getSymbolTable(); SymbolTable symbolTable = ir.getSymbolTable();
SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site); SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site);
if (invokeInstructions.length != 1) { if (invokeInstructions.length != 1) {
return null; return null;
} }
int use = invokeInstructions[0].getUse(0); int use = getUseOfStringParameter(invokeInstructions[0]);
if (symbolTable.isStringConstant(use)) { if (symbolTable.isStringConstant(use)) {
String className = StringStuff.deployment2CanonicalTypeString(symbolTable.getStringValue(use)); String className = StringStuff.deployment2CanonicalTypeString(symbolTable.getStringValue(use));
TypeReference t = TypeReference.findOrCreate(caller.getMethod().getDeclaringClass().getClassLoader().getReference(), 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. * 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) { 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(); IR ir = caller.getIR();
SymbolTable symbolTable = ir.getSymbolTable(); SymbolTable symbolTable = ir.getSymbolTable();
SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site); SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site);
if (invokeInstructions.length != 1) { if (invokeInstructions.length != 1) {
return false; return false;
} }
int use = invokeInstructions[0].getUse(0); int use = getUseOfStringParameter(invokeInstructions[0]);
if (symbolTable.isStringConstant(use)) { if (symbolTable.isStringConstant(use)) {
return true; return true;
} }

View File

@ -34,7 +34,7 @@ public class ReflectionContextInterpreter extends DelegatingSSAContextInterprete
ReflectionSpecification userSpec) { ReflectionSpecification userSpec) {
super(new ReflectiveInvocationInterpreter(), new DelegatingSSAContextInterpreter(new DelegatingSSAContextInterpreter( super(new ReflectiveInvocationInterpreter(), new DelegatingSSAContextInterpreter(new DelegatingSSAContextInterpreter(
new GetClassContextInterpeter(), new JavaLangClassContextInterpreter()), 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)))); new FactoryBypassInterpreter(options, cache, userSpec))));
} }

View File

@ -31,7 +31,7 @@ public class ReflectionContextSelector extends DelegatingContextSelector {
*/ */
private ReflectionContextSelector() { private ReflectionContextSelector() {
super(new ReflectiveInvocationSelector(), new DelegatingContextSelector(new JavaLangClassContextSelector(), 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()))); new GetClassContextSelector()), new ClassNewInstanceContextSelector()), new FactoryContextSelector())));
} }