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>
|
||||||
<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"
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue