Fixes in the UnknownTarget model.
Before the model went by the wrong Name, it failed if no app-internal implementations of the targetType existed. Also tidied up the code.
This commit is contained in:
parent
bd8f793135
commit
c4eb253721
|
@ -220,6 +220,10 @@ public class AndroidModel /* makes SummarizedMethod */
|
||||||
return TypeReference.VoidName;
|
return TypeReference.VoidName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Descriptor getDescriptor() throws CancelException {
|
||||||
|
return getMethod().getDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the SummarizedMethod for the model (in this.model).
|
* Generate the SummarizedMethod for the model (in this.model).
|
||||||
*
|
*
|
||||||
|
@ -301,8 +305,8 @@ public class AndroidModel /* makes SummarizedMethod */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return tRef;
|
||||||
throw new IllegalStateException("Error looking up " + tRef);
|
//throw new IllegalStateException("Error looking up " + tRef);
|
||||||
} else {
|
} else {
|
||||||
return tRef;
|
return tRef;
|
||||||
}
|
}
|
||||||
|
@ -954,4 +958,9 @@ public class AndroidModel /* makes SummarizedMethod */
|
||||||
public IClassHierarchy getClassHierarchy() {
|
public IClassHierarchy getClassHierarchy() {
|
||||||
return this.cha;
|
return this.cha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "<" + this.getClass() + " name=" + this.name + " />";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,16 @@ public class MiniModel extends AndroidModel {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
protected boolean selectEntryPoint(AndroidEntryPoint ep) {
|
protected boolean selectEntryPoint(AndroidEntryPoint ep) {
|
||||||
return ep.belongsTo(forCompo);
|
if (ep.belongsTo(forCompo)) {
|
||||||
|
logger.debug("MiniModel calls: {}", ep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public Descriptor getDescriptor() throws CancelException {
|
||||||
|
final Descriptor descr = super.getDescriptor();
|
||||||
|
logger.info("MiniModel: {}", descr);
|
||||||
|
return descr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiniModel(final IClassHierarchy cha, final AnalysisOptions options, final AnalysisCache cache,
|
public MiniModel(final IClassHierarchy cha, final AnalysisOptions options, final AnalysisCache cache,
|
||||||
|
@ -155,6 +164,11 @@ public class MiniModel extends AndroidModel {
|
||||||
mClass.addMethod(super.model);
|
mClass.addMethod(super.model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "<" + this.getClass() + " name=" + this.name + " for=" + forCompo + " />";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ public class ExternalModel extends AndroidModel {
|
||||||
private SummarizedMethod activityModel;
|
private SummarizedMethod activityModel;
|
||||||
private final AndroidComponent target;
|
private final AndroidComponent target;
|
||||||
// uses AndroidModel.cha;
|
// uses AndroidModel.cha;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do not call any EntryPoint.
|
* Do not call any EntryPoint.
|
||||||
*
|
*
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
*/
|
*/
|
||||||
package com.ibm.wala.dalvik.ipa.callgraph.androidModel.stubs;
|
package com.ibm.wala.dalvik.ipa.callgraph.androidModel.stubs;
|
||||||
|
|
||||||
|
import com.ibm.wala.dalvik.util.AndroidEntryPointManager;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
import com.ibm.wala.types.Descriptor;
|
import com.ibm.wala.types.Descriptor;
|
||||||
import com.ibm.wala.types.MethodReference;
|
import com.ibm.wala.types.MethodReference;
|
||||||
|
@ -121,13 +122,25 @@ public class UnknownTargetModel extends AndroidModel {
|
||||||
private static Logger logger = LoggerFactory.getLogger(UnknownTargetModel.class);
|
private static Logger logger = LoggerFactory.getLogger(UnknownTargetModel.class);
|
||||||
|
|
||||||
public final Atom name;
|
public final Atom name;
|
||||||
|
private boolean doMini = true;
|
||||||
|
private MiniModel miniModel = null;
|
||||||
|
private ExternalModel externalModel = null;
|
||||||
private final AndroidComponent target;
|
private final AndroidComponent target;
|
||||||
// uses AndroidModel.cha;
|
// uses AndroidModel.cha;
|
||||||
private final MiniModel allInternal;
|
|
||||||
private final ExternalModel external;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param target Component Type, may be null
|
* The UnknownTargetModel does not call any entrypoints on it's own.
|
||||||
|
*
|
||||||
|
* Instead it first creates a restricted AndroidModel and an ExternalModel.
|
||||||
|
* These are actually called.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean selectEntryPoint(AndroidEntryPoint ep) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param target Component Type, may be null: No restrictions are imposed on AndroidModel then
|
||||||
*/
|
*/
|
||||||
public UnknownTargetModel(final IClassHierarchy cha, final AnalysisOptions options, final AnalysisCache cache,
|
public UnknownTargetModel(final IClassHierarchy cha, final AnalysisOptions options, final AnalysisCache cache,
|
||||||
AndroidComponent target) throws CancelException {
|
AndroidComponent target) throws CancelException {
|
||||||
|
@ -136,11 +149,13 @@ public class UnknownTargetModel extends AndroidModel {
|
||||||
if (target == null) { // TODO: Enable
|
if (target == null) { // TODO: Enable
|
||||||
throw new IllegalArgumentException("The component type requested to create an UnknownTargetModel for was null");
|
throw new IllegalArgumentException("The component type requested to create an UnknownTargetModel for was null");
|
||||||
}
|
}
|
||||||
this.name = Atom.findOrCreateAsciiAtom("startUnknown" + target.toString());
|
String sName = target.toString();
|
||||||
|
String cName = Character.toUpperCase(sName.charAt(0)) + sName.substring(1).toLowerCase();
|
||||||
|
this.name = Atom.findOrCreateAsciiAtom("startUnknown" + cName);
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
|
||||||
this.allInternal = new MiniModel(cha, options, cache, target);
|
//this.allInternal = new MiniModel(cha, options, cache, target);
|
||||||
this.external = new ExternalModel(cha, options, cache, target);
|
//this.external = new ExternalModel(cha, options, cache, target);
|
||||||
|
|
||||||
logger.debug("Will be known as {}/{}", AndroidModelClass.ANDROID_MODEL_CLASS.getName(), this.name);
|
logger.debug("Will be known as {}/{}", AndroidModelClass.ANDROID_MODEL_CLASS.getName(), this.name);
|
||||||
}
|
}
|
||||||
|
@ -164,74 +179,68 @@ public class UnknownTargetModel extends AndroidModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean selectEntryPoint(AndroidEntryPoint ep) {
|
|
||||||
try {
|
|
||||||
if (! (ep.getMethod().equals(this.allInternal.getMethod()) || ep.getMethod().equals(this.external.getMethod()))) {
|
|
||||||
// logger.error("Asked for unexpected EP: " + ep); - is ok
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (CancelException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void build(Atom name, Collection<? extends AndroidEntryPoint> entrypoints) throws CancelException {
|
protected void build(Atom name, Collection<? extends AndroidEntryPoint> entrypoints) throws CancelException {
|
||||||
// Start evil hack(TM)
|
assert ((entrypoints == null) || (! entrypoints.iterator().hasNext()));
|
||||||
final AndroidEntryPoint internalAsEp = new AndroidEntryPoint(new ExecutionOrder(1), this.allInternal.getMethod(), this.cha);
|
|
||||||
final AndroidEntryPoint externalAsEp = new AndroidEntryPoint(new ExecutionOrder(2), this.external.getMethod(), this.cha);
|
{ // Check if this Application has components, that implement target. If not we don't
|
||||||
List<AndroidEntryPoint> pseudoEps = new ArrayList<AndroidEntryPoint>(2);
|
// have to build a MiniModel.
|
||||||
pseudoEps.add(internalAsEp);
|
doMini = false;
|
||||||
pseudoEps.add(externalAsEp);
|
for (final AndroidEntryPoint ep : AndroidEntryPointManager.ENTRIES) {
|
||||||
super.build(name, pseudoEps);
|
if (ep.belongsTo(this.target)) {
|
||||||
|
doMini = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
@Override
|
|
||||||
protected void build(Atom name, Iterable<? extends Entrypoint> entrypoints) throws CancelException {
|
|
||||||
|
|
||||||
final IMethod allInternalMethod = allInternal.getMethod();
|
|
||||||
final int allIntenalParamCount = allInternalMethod.getNumberOfParameters();
|
|
||||||
final IMethod externalMethod = external.getMethod();
|
|
||||||
final int externalParamcount = externalMethod.getNumberOfParameters();
|
|
||||||
|
|
||||||
final List<TypeName> myParams = new ArrayList<TypeName>(allIntenalParamCount);
|
|
||||||
|
|
||||||
for (int i = 0 ; i < allIntenalParamCount; ++i) {
|
|
||||||
myParams.add(allInternalMethod.getParameterType(i).getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0 ; i < externalParamcount; ++i) {
|
|
||||||
final TypeName param = externalMethod.getParameterType(i).getName();
|
|
||||||
if (!(myParams.contains(param))) {
|
|
||||||
myParams.add(param);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeName[] aMyParams = new TypeName[myParams.size()];
|
if (doMini) {
|
||||||
aMyParams = myParams.toArray(aMyParams);
|
miniModel = new MiniModel(this.cha, this.options, this.cache, this.target);
|
||||||
|
}
|
||||||
|
externalModel = new ExternalModel(this.cha, this.options, this.cache, this.target);
|
||||||
|
|
||||||
this.descr = Descriptor.findOrCreate(aMyParams, TypeReference.VoidName);
|
final Descriptor descr;
|
||||||
this.mRef = MethodReference.findOrCreate(AndroidModelClass.ANDROID_MODEL_CLASS, name, this.descr);
|
final Selector selector;
|
||||||
final Selector selector = this.mRef.getSelector();
|
{
|
||||||
|
if (doMini) {
|
||||||
|
final TypeName[] othersA = miniModel.getDescriptor().getParameters();
|
||||||
|
final Set<TypeName> others;
|
||||||
|
if (othersA != null) {
|
||||||
|
others = new HashSet<TypeName>(Arrays.asList(othersA));
|
||||||
|
} else {
|
||||||
|
logger.error("{} has no paramteres!", miniModel);
|
||||||
|
others = new HashSet<TypeName>();
|
||||||
|
}
|
||||||
|
doMini = others.size() > 0;
|
||||||
|
others.addAll(Arrays.asList(externalModel.getDescriptor().getParameters()));
|
||||||
|
descr = Descriptor.findOrCreate(others.toArray(new TypeName[] {}), TypeReference.VoidName); // Return the intent of external? TODO
|
||||||
|
} else {
|
||||||
|
descr = Descriptor.findOrCreate(externalModel.getDescriptor().getParameters(), TypeReference.VoidName);
|
||||||
|
}
|
||||||
|
selector = new Selector(name, descr);
|
||||||
|
}
|
||||||
|
|
||||||
// Assert not registered yet
|
/*{ // Skip construction if there already exists a model wit this name. This should
|
||||||
|
// not happen.
|
||||||
final AndroidModelClass mClass = AndroidModelClass.getInstance(this.cha);
|
final AndroidModelClass mClass = AndroidModelClass.getInstance(this.cha);
|
||||||
this.klass = mClass;
|
|
||||||
if (mClass.containsMethod(selector)) {
|
if (mClass.containsMethod(selector)) {
|
||||||
|
logger.error("There is already an Android-Model with name {}!", selector);
|
||||||
|
this.built = true;
|
||||||
this.model = (SummarizedMethod) mClass.getMethod(selector);
|
this.model = (SummarizedMethod) mClass.getMethod(selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} // */
|
||||||
|
|
||||||
|
{ // Set some properties of the later method
|
||||||
|
this.klass = AndroidModelClass.getInstance(this.cha);
|
||||||
|
this.mRef = MethodReference.findOrCreate(AndroidModelClass.ANDROID_MODEL_CLASS, name, descr);
|
||||||
this.body = new VolatileMethodSummary(new MethodSummary(this.mRef));
|
this.body = new VolatileMethodSummary(new MethodSummary(this.mRef));
|
||||||
this.body.setStatic(true);
|
this.body.setStatic(true);
|
||||||
|
}
|
||||||
|
|
||||||
logger.debug("The Selector of the method will be " + selector);
|
{ // Start building
|
||||||
populate(null);
|
populate(null);
|
||||||
|
|
||||||
this.model = new SummarizedMethod(this.mRef, this.body.getMethodSummary(), this.klass) {
|
this.model = new SummarizedMethod(this.mRef, this.body.getMethodSummary(), this.klass) {
|
||||||
@Override
|
@Override
|
||||||
public TypeReference getParameterType (int i) {
|
public TypeReference getParameterType (int i) {
|
||||||
|
@ -254,10 +263,11 @@ public class UnknownTargetModel extends AndroidModel {
|
||||||
return tRef;
|
return tRef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}; // of this.model
|
||||||
|
}
|
||||||
|
|
||||||
this.built = true;
|
this.built = true;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the model with instructions.
|
* Fill the model with instructions.
|
||||||
|
@ -266,11 +276,47 @@ public class UnknownTargetModel extends AndroidModel {
|
||||||
*/
|
*/
|
||||||
//@Override
|
//@Override
|
||||||
private void populate(Iterable<? extends AndroidEntryPoint> entrypoints) throws CancelException {
|
private void populate(Iterable<? extends AndroidEntryPoint> entrypoints) throws CancelException {
|
||||||
|
assert ((entrypoints == null) || (! entrypoints.iterator().hasNext()));
|
||||||
assert (! built) : "You can only build once";
|
assert (! built) : "You can only build once";
|
||||||
|
|
||||||
|
final TypeSafeInstructionFactory instructionFactory = new TypeSafeInstructionFactory(this.cha);
|
||||||
|
final ParameterAccessor pAcc = new ParameterAccessor(this.mRef, /* hasImplicitThis */ false);
|
||||||
|
final SSAValueManager pm = new SSAValueManager(pAcc);
|
||||||
|
final Instantiator instantiator = new Instantiator(this.body, instructionFactory, pm, this.cha, this.mRef, this.scope);
|
||||||
|
|
||||||
|
if (doMini) { // Call a MiniModel
|
||||||
|
//final MiniModel miniModel = new MiniModel(this.cha, this.options, this.cache, this.target);
|
||||||
|
final IMethod mini = miniModel.getMethod();
|
||||||
|
final ParameterAccessor miniAcc = new ParameterAccessor(mini);
|
||||||
|
final List<SSAValue> params = pAcc.connectThrough(miniAcc, null, null, this.cha, instantiator, false, null, null);
|
||||||
|
final SSAValue excpetion = pm.getException();
|
||||||
|
final int pc = this.body.getNextProgramCounter();
|
||||||
|
final CallSiteReference site = CallSiteReference.make(pc, mini.getReference(), IInvokeInstruction.Dispatch.STATIC);
|
||||||
|
final SSAInstruction invokation = instructionFactory.InvokeInstruction(pc, params, excpetion, site);
|
||||||
|
this.body.addStatement(invokation);
|
||||||
|
}
|
||||||
|
|
||||||
|
final SSAValue extRet;
|
||||||
|
{ // Call the externalTarget Model
|
||||||
|
//final ExternalModel externalModel = new ExternalModel(this.cha, this.options, this.cache, this.target);
|
||||||
|
final IMethod external = externalModel.getMethod();
|
||||||
|
final ParameterAccessor externalAcc = new ParameterAccessor(external);
|
||||||
|
final List<SSAValue> params = pAcc.connectThrough(externalAcc, null, null, this.cha, instantiator, false, null, null);
|
||||||
|
final SSAValue excpetion = pm.getException();
|
||||||
|
extRet = pm.getUnmanaged(external.getReturnType() , "extRet");
|
||||||
|
final int pc = this.body.getNextProgramCounter();
|
||||||
|
final CallSiteReference site = CallSiteReference.make(pc, external.getReference(), IInvokeInstruction.Dispatch.STATIC);
|
||||||
|
final SSAInstruction invokation = instructionFactory.InvokeInstruction(pc, extRet, params, excpetion, site);
|
||||||
|
this.body.addStatement(invokation);
|
||||||
|
}
|
||||||
|
// TODO: Do somethig with extRet?
|
||||||
|
|
||||||
|
this.body.setLocalNames(pm.makeLocalNames());
|
||||||
|
}
|
||||||
|
/*
|
||||||
final ParameterAccessor internalAcc = new ParameterAccessor(this.allInternal.getMethod());
|
final ParameterAccessor internalAcc = new ParameterAccessor(this.allInternal.getMethod());
|
||||||
final ParameterAccessor externalAcc = new ParameterAccessor(this.external.getMethod());
|
final ParameterAccessor externalAcc = new ParameterAccessor(this.external.getMethod());
|
||||||
final ParameterAccessor thisAcc = new ParameterAccessor(this.mRef, /* hasImplicitThis */ false);
|
final ParameterAccessor thisAcc = new ParameterAccessor(this.mRef, false);
|
||||||
final SSAValueManager pm = new SSAValueManager(thisAcc);
|
final SSAValueManager pm = new SSAValueManager(thisAcc);
|
||||||
final JavaInstructionFactory instructionFactory = new JavaInstructionFactory(); // TODO: Use a typesafe factory?
|
final JavaInstructionFactory instructionFactory = new JavaInstructionFactory(); // TODO: Use a typesafe factory?
|
||||||
final Instantiator instantiator = new Instantiator(this.body, new TypeSafeInstructionFactory(getClassHierarchy()),
|
final Instantiator instantiator = new Instantiator(this.body, new TypeSafeInstructionFactory(getClassHierarchy()),
|
||||||
|
@ -301,7 +347,7 @@ public class UnknownTargetModel extends AndroidModel {
|
||||||
|
|
||||||
final int externalReturnIntent = nextLocal++;
|
final int externalReturnIntent = nextLocal++;
|
||||||
{ // Call the external model
|
{ // Call the external model
|
||||||
final List<SSAValue> args = thisAcc.connectThrough(externalAcc, null, null /*internalArgs*/, getClassHierarchy(), instantiator,
|
final List<SSAValue> args = thisAcc.connectThrough(externalAcc, null, null , getClassHierarchy(), instantiator,
|
||||||
false, null, null);
|
false, null, null);
|
||||||
final IMethod externalMethod = this.external.getMethod();
|
final IMethod externalMethod = this.external.getMethod();
|
||||||
|
|
||||||
|
@ -318,7 +364,7 @@ public class UnknownTargetModel extends AndroidModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Phi-Together returnIntents and return it. Or at least handle external
|
// TODO: Phi-Together returnIntents and return it. Or at least handle external
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,9 @@ public class AndroidEntryPoint extends DexEntryPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean belongsTo(AndroidComponent compo) {
|
public boolean belongsTo(AndroidComponent compo) {
|
||||||
|
if ((compo == AndroidComponent.SERVICE) && (this.superType.equals(AndroidComponent.INTENT_SERVICE))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return (this.superType.equals(compo));
|
return (this.superType.equals(compo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue