Build coarse Android Environment
Governed by AndroidEntryPointManager.setDoBootSequence generate some coarse Android-environment before starting the LiveCycle-Model. Some action is taken to attach the Android-Context to Components - much is still missing there though. Thin context is mainly useful when starting Intents of an external App.
This commit is contained in:
parent
0543761699
commit
9c7a2eb975
|
@ -82,8 +82,10 @@ import com.ibm.wala.util.ssa.IInstantiator;
|
|||
import com.ibm.wala.dalvik.ipa.callgraph.androidModel.parameters.IInstantiationBehavior;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.androidModel.parameters.IInstantiationBehavior.InstanceBehavior;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.androidModel.structure.AbstractAndroidModel;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.androidModel.stubs.AndroidBoot;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.androidModel.stubs.AndroidStartComponentTool;
|
||||
|
||||
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
import com.ibm.wala.dalvik.util.AndroidTypes;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.propagation.cfa.IntentStarters;
|
||||
|
@ -159,6 +161,11 @@ public class AndroidModel /* makes SummarizedMethod */
|
|||
|
||||
private IProgressMonitor monitor;
|
||||
private int maxProgress;
|
||||
|
||||
/*
|
||||
* static: "boot" only once. How to assert done by the right one?
|
||||
*/
|
||||
protected static boolean doBoot = true;
|
||||
|
||||
protected IClass klass;
|
||||
protected boolean built;
|
||||
|
@ -258,6 +265,8 @@ public class AndroidModel /* makes SummarizedMethod */
|
|||
this.monitor = AndroidEntryPointManager.MANAGER.getProgressMonitor();
|
||||
this.maxProgress = entrypoints.size();
|
||||
|
||||
this.doBoot &= AndroidEntryPointManager.MANAGER.getDoBootSequence();
|
||||
|
||||
// BUILD
|
||||
this.monitor.beginTask("Building " + name, this.maxProgress);
|
||||
populate(entrypoints);
|
||||
|
@ -350,6 +359,52 @@ public class AndroidModel /* makes SummarizedMethod */
|
|||
|
||||
final TypeSafeInstructionFactory tsif = new TypeSafeInstructionFactory(this.cha);
|
||||
final Instantiator instantiator = new Instantiator (this.body, tsif, this.paramManager, this.cha, this.mRef, this.scope);
|
||||
|
||||
//
|
||||
// Add preparing code to the model
|
||||
//
|
||||
if (this.doBoot) {
|
||||
final Set<Parameter> allActivities = new HashSet(modelAcc.allExtend(AndroidTypes.ActivityName, getClassHierarchy()));
|
||||
//assert(allActivities.size() > 0) : "There are no Activities in the Model"; // XXX
|
||||
final IntentStarters.StartInfo toolInfo = IntentStarters.StartInfo.makeContextFree(null);
|
||||
final AndroidStartComponentTool tool = new AndroidStartComponentTool(this.cha, this.mRef, toolInfo.getFlags(),
|
||||
/* caller */ null, tsif, modelAcc, this.paramManager, this.body, /* self */ null, toolInfo, /* callerNd */ null);
|
||||
final SSAValue application;
|
||||
{
|
||||
final SSAValue tmpApp = modelAcc.firstExtends(AndroidTypes.ApplicationName, this.cha);
|
||||
if (tmpApp != null) {
|
||||
application = tmpApp;
|
||||
} else {
|
||||
// Generate a real one?
|
||||
logger.warn("I didn't get an application");
|
||||
application = paramManager.getUnmanaged(AndroidTypes.Application, "app");
|
||||
this.body.addConstant(application.getNumber(), new ConstantValue(null));
|
||||
application.setAssigned();
|
||||
}
|
||||
}
|
||||
final SSAValue nullIntent;
|
||||
{
|
||||
nullIntent = paramManager.getUnmanaged(AndroidTypes.Intent, "nullIntent");
|
||||
this.body.addConstant(nullIntent.getNumber(), new ConstantValue(null));
|
||||
nullIntent.setAssigned();
|
||||
}
|
||||
final SSAValue nullBinder;
|
||||
{
|
||||
nullBinder = paramManager.getUnmanaged(AndroidTypes.IBinder, "nullBinder");
|
||||
this.body.addConstant(nullBinder.getNumber(), new ConstantValue(null));
|
||||
nullBinder.setAssigned();
|
||||
}
|
||||
|
||||
logger.info("Adding Boot-Code to the Android model");
|
||||
{
|
||||
final AndroidBoot boot = new AndroidBoot(null);
|
||||
boot.addBootCode(tsif, null, paramManager, this.body);
|
||||
tool.attachActivities(allActivities, application, boot.getMainThread(), /* Should be application context TODO */
|
||||
boot.getPackageContext(), nullBinder, nullIntent);
|
||||
}
|
||||
|
||||
// TODO: Assign context to the other components
|
||||
}
|
||||
|
||||
logger.info("Populating the AndroidModel with {} entryPoints", this.maxProgress);
|
||||
|
||||
|
@ -623,11 +678,19 @@ public class AndroidModel /* makes SummarizedMethod */
|
|||
final AndroidStartComponentTool tool = new AndroidStartComponentTool(getClassHierarchy(), asMethod, flags, caller, instructionFactory,
|
||||
acc, pm, redirect, self, info, callerNd);
|
||||
|
||||
final AndroidTypes.AndroidContextType contextType;
|
||||
final SSAValue androidContext; // of AndroidTypes.Context: The callers android-context
|
||||
|
||||
androidContext = tool.fetchCallerContext();
|
||||
contextType = tool.typeOfCallerContext();
|
||||
|
||||
try { // Add additional Info if Exception occurs...
|
||||
|
||||
// TODO: Check, that caller is an activity where necessary!
|
||||
|
||||
// TODO: Call Activity.setIntent
|
||||
final SSAValue iBinder = tool.fetchIBinder(androidContext);
|
||||
tool.assignIBinder(iBinder, allActivities);
|
||||
|
||||
// Call the model
|
||||
{
|
||||
|
@ -735,6 +798,8 @@ public class AndroidModel /* makes SummarizedMethod */
|
|||
|
||||
//final List<Parameter> modelsActivities = modelAcc.allExtend(AndroidTypes.ActivityName, getClassHierarchy()); // are in models scope
|
||||
//final List<SSAValue> allActivities = new ArrayList<SSAValue>(modelsActivities.size()); // create instances in this scope
|
||||
System.err.println("\tcontextType=\t" + contextType);
|
||||
System.err.println("\tandroidContetx=\t" + androidContext);
|
||||
System.err.println("\tasMethod=\t" + asMethod);
|
||||
System.err.println("\tcaller=\t" + caller);
|
||||
System.err.println("\tinfo=\t" + info);
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright (c) 2013,
|
||||
* Tobias Blaschke <code@tobiasblaschke.de>
|
||||
* All rights reserved.
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The names of the contributors may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.ibm.wala.dalvik.ipa.callgraph.androidModel.stubs;
|
||||
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.dalvik.util.AndroidTypes;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.ipa.summaries.MethodSummary;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.NewSiteReference;
|
||||
import com.ibm.wala.ssa.ConstantValue;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
|
||||
import com.ibm.wala.util.ssa.TypeSafeInstructionFactory;
|
||||
import com.ibm.wala.util.ssa.ParameterAccessor;
|
||||
import com.ibm.wala.util.ssa.SSAValue;
|
||||
import com.ibm.wala.ipa.summaries.VolatileMethodSummary;
|
||||
import com.ibm.wala.util.ssa.SSAValueManager;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Create some Android-Environment.
|
||||
*
|
||||
* Used by the AndroidModel to assign some fields in the analyzed Application if the
|
||||
* settings instruct it to do so.
|
||||
*
|
||||
* @see com.ibm.wala.dalvik.ipa.callgraph.androidModel.AndroidModel
|
||||
* @see com.ibm.wala.dalvik.util.AndroidEntryPointManager
|
||||
*
|
||||
* @author Tobias Blaschke <code@tobiasblaschke.de>
|
||||
* @since 2013-10-23
|
||||
*/
|
||||
public class AndroidBoot {
|
||||
private static Logger logger = LoggerFactory.getLogger(AndroidBoot.class);
|
||||
|
||||
public static enum BootAction {
|
||||
/**
|
||||
* Create an instance of android.app.ContextImpl for the system.
|
||||
*/
|
||||
CREATE_SYSTEM_CONTEXT,
|
||||
/**
|
||||
* Crate an instance of android.app.ContextImpl for the apk.
|
||||
*/
|
||||
CREATE_APK_CONTEXT,
|
||||
}
|
||||
//public static Set<BootAction> BOOT_ALL = EnumSet.allOf(BootAction);
|
||||
|
||||
private final MethodReference scope;
|
||||
private TypeSafeInstructionFactory instructionFactory;
|
||||
private ParameterAccessor acc;
|
||||
private SSAValueManager pm;
|
||||
private VolatileMethodSummary body;
|
||||
|
||||
|
||||
public AndroidBoot(Set<BootAction> whatToDo) {
|
||||
this.scope = null; // Place something here?
|
||||
}
|
||||
|
||||
private SSAValue mainThread = null;
|
||||
private SSAValue systemContext = null;
|
||||
private SSAValue packageContext = null;
|
||||
|
||||
public void addBootCode(final TypeSafeInstructionFactory instructionFactory, final ParameterAccessor acc,
|
||||
final SSAValueManager pm, final VolatileMethodSummary body) {
|
||||
this.instructionFactory = instructionFactory;
|
||||
this.acc = acc;
|
||||
this.pm = pm;
|
||||
this.body = body;
|
||||
|
||||
mainThread = createMainThred();
|
||||
systemContext = createSystemContext(mainThread);
|
||||
packageContext = createPackageContext(mainThread, systemContext);
|
||||
}
|
||||
|
||||
public SSAValue getSystemContext() {
|
||||
if (systemContext == null) {
|
||||
throw new IllegalStateException("No value for systemContext - was addBootCode called?");
|
||||
}
|
||||
return systemContext;
|
||||
}
|
||||
|
||||
public SSAValue getPackageContext() {
|
||||
if (packageContext == null) {
|
||||
throw new IllegalStateException("No value for packageContext - was addBootCode called?");
|
||||
}
|
||||
return packageContext;
|
||||
}
|
||||
|
||||
|
||||
public SSAValue getMainThread() {
|
||||
if (mainThread == null) {
|
||||
throw new IllegalStateException("No value for mainThread - was addBootCode called?");
|
||||
}
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the main-thread as activity-thread.
|
||||
*/
|
||||
private SSAValue createMainThred() {
|
||||
final SSAValue mainThread = this.pm.getUnmanaged(AndroidTypes.ActivityThread, "mMainThred");
|
||||
{ // New-Site
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final NewSiteReference nRef = NewSiteReference.make(pc, AndroidTypes.ActivityThread);
|
||||
final SSAInstruction newInstr = this.instructionFactory.NewInstruction(pc, mainThread, nRef);
|
||||
body.addStatement(newInstr);
|
||||
}
|
||||
/*{ // clinit
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ActivityThread, MethodReference.clinitSelector);
|
||||
final SSAValue exception = new SSAValue(this.pm.getUnmanaged(), TypeReference.JavaLangException, this.scope, "ctor_exc" );
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(mainThread);
|
||||
final SSAInstruction ctorCall = instructionFactory.InvokeInstruction(pc, params, exception, site);
|
||||
body.addStatement(ctorCall);
|
||||
}*/
|
||||
{ // CTor-Call
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ActivityThread, MethodReference.initSelector);
|
||||
final SSAValue exception = this.pm.getUnmanaged(TypeReference.JavaLangException, "ctor_exc" );
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(mainThread);
|
||||
final SSAInstruction ctorCall = instructionFactory.InvokeInstruction(pc, params, exception, site);
|
||||
body.addStatement(ctorCall);
|
||||
}
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of android.app.ContextImpl for the system.
|
||||
*
|
||||
* @see android.app.ContextImpl.createPackageContextAsUser
|
||||
*/
|
||||
private SSAValue createSystemContext(SSAValue mainThread) {
|
||||
final SSAValue systemContext = this.pm.getUnmanaged(AndroidTypes.ContextImpl, "systemContextImpl");
|
||||
{ // Call ContextImpl.getSystemContext()
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final Descriptor desc = Descriptor.findOrCreate(new TypeName[0], AndroidTypes.ContextImplName);
|
||||
final Selector mSel = new Selector(Atom.findOrCreateAsciiAtom("getSystemContext"), desc);
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ActivityThread, mSel);
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
final SSAValue exception = this.pm.getException();
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(mainThread);
|
||||
final SSAInstruction call = instructionFactory.InvokeInstruction(pc, systemContext, params, exception, site);
|
||||
body.addStatement(call);
|
||||
}
|
||||
{ // putting mRestricted = false
|
||||
final SSAValue falseConst = this.pm.getUnmanaged(TypeReference.Boolean, "falseConst");
|
||||
this.body.addConstant(falseConst.getNumber(), new ConstantValue(false));
|
||||
falseConst.setAssigned();
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final FieldReference mRestricted = FieldReference.findOrCreate(AndroidTypes.ContextImpl, Atom.findOrCreateAsciiAtom("mRestricted"),
|
||||
TypeReference.Boolean);
|
||||
final SSAInstruction putInst = instructionFactory.PutInstruction(pc, systemContext, falseConst, mRestricted);
|
||||
body.addStatement(putInst);
|
||||
}
|
||||
return systemContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of android.app.ContextImpl for the apk.
|
||||
*
|
||||
* @see android.app.ContextImpl.createPackageContextAsUser
|
||||
*/
|
||||
private SSAValue createPackageContext(final SSAValue mainThread, final SSAValue systemContext) {
|
||||
final SSAValue packageContext = this.pm.getUnmanaged(AndroidTypes.ContextImpl, "packageContextImpl");
|
||||
{ // New-Site
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final NewSiteReference nRef = NewSiteReference.make(pc, AndroidTypes.ContextImpl);
|
||||
final SSAInstruction newInstr = this.instructionFactory.NewInstruction(pc, packageContext, nRef);
|
||||
body.addStatement(newInstr);
|
||||
}
|
||||
/*{ // clnint
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ContextImpl, MethodReference.clinitSelector);
|
||||
final SSAValue exception = new SSAValue(this.pm.getUnmanaged(), TypeReference.JavaLangException, this.scope, "ctor_exc" );
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(packageContext);
|
||||
final SSAInstruction ctorCall = instructionFactory.InvokeInstruction(pc, params, exception, site);
|
||||
body.addStatement(ctorCall);
|
||||
}*/
|
||||
{ // CTor-Call
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ContextImpl, MethodReference.initSelector);
|
||||
final SSAValue exception = this.pm.getUnmanaged(TypeReference.JavaLangException, "ctor_exc" );
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(packageContext);
|
||||
final SSAInstruction ctorCall = instructionFactory.InvokeInstruction(pc, params, exception, site);
|
||||
body.addStatement(ctorCall);
|
||||
}
|
||||
{ // putting mRestricted = false
|
||||
final SSAValue falseConst = this.pm.getUnmanaged(TypeReference.Boolean, "falseConst");
|
||||
this.body.addConstant(falseConst.getNumber(), new ConstantValue(false));
|
||||
falseConst.setAssigned();
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final FieldReference mRestricted = FieldReference.findOrCreate(AndroidTypes.ContextImpl, Atom.findOrCreateAsciiAtom("mRestricted"),
|
||||
TypeReference.Boolean);
|
||||
final SSAInstruction putInst = instructionFactory.PutInstruction(pc, packageContext, falseConst, mRestricted);
|
||||
body.addStatement(putInst);
|
||||
}
|
||||
final SSAValue packageName;
|
||||
{ // Generating pacakge name
|
||||
packageName = this.pm.getUnmanaged(TypeReference.JavaLangString, "packageName");
|
||||
this.body.addConstant(packageName.getNumber(), new ConstantValue("foo")); // TODO: Fetch name
|
||||
packageName.setAssigned();
|
||||
}
|
||||
final SSAValue uid = this.pm.getUnmanaged(AndroidTypes.UserHandle, "uid");
|
||||
{ // New UserHandle
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final NewSiteReference nRef = NewSiteReference.make(pc, AndroidTypes.UserHandle);
|
||||
final SSAInstruction newInstr = this.instructionFactory.NewInstruction(pc, uid, nRef);
|
||||
body.addStatement(newInstr);
|
||||
}
|
||||
/*{ // UserHandle(1000) // TODO: seems android-subs do not contain this
|
||||
final SSAValue nrUid = new SSAValue(this.pm.getUnmanaged(), TypeReference.Int, this.scope, "nrUid");
|
||||
this.body.addConstant(nrUid.getNumber(), new ConstantValue(1000)); // First regular linux user
|
||||
nrUid.setAssigned();
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final Descriptor descr = Descriptor.findOrCreate(new TypeName[] { TypeReference.IntName }, TypeReference.VoidName);
|
||||
final Selector mSel = new Selector(MethodReference.initAtom, descr);
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.UserHandle, mSel);
|
||||
final SSAValue exception = new SSAValue(this.pm.getUnmanaged(), TypeReference.JavaLangException, this.scope, "ctor_exc" );
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(2);
|
||||
params.add(uid);
|
||||
params.add(nrUid);
|
||||
final SSAInstruction ctorCall = instructionFactory.InvokeInstruction(pc, params, exception, site);
|
||||
body.addStatement(ctorCall);
|
||||
} // */
|
||||
/*{ // packageContext.init(pi = null, null, mMainThread, mResources = null, mBasePackageName, user); TODO: Not in android stubs
|
||||
final SSAValue nullApk = new SSAValue(this.pm.getUnmanaged(), AndroidTypes.LoadedApk, this.scope, "nullApk"); // TODO
|
||||
this.body.addConstant(nullApk.getNumber(), new ConstantValue(null));
|
||||
nullApk.setAssigned();
|
||||
|
||||
final SSAValue nullIBinder = new SSAValue(this.pm.getUnmanaged(), AndroidTypes.IBinder, this.scope, "nullBinder");
|
||||
this.body.addConstant(nullIBinder.getNumber(), new ConstantValue(null));
|
||||
nullIBinder.setAssigned();
|
||||
|
||||
final SSAValue nullResources = new SSAValue(this.pm.getUnmanaged(), AndroidTypes.Resources, this.scope, "nullResources"); // TODO
|
||||
this.body.addConstant(nullResources.getNumber(), new ConstantValue(null));
|
||||
nullResources.setAssigned();
|
||||
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final Descriptor desc = Descriptor.findOrCreate(new TypeName[] {
|
||||
AndroidTypes.LoadedApkName,
|
||||
AndroidTypes.IBinderName,
|
||||
AndroidTypes.ActivityThreadName,
|
||||
AndroidTypes.ResourcesName,
|
||||
TypeName.string2TypeName("Ljava/lang/String"), // Private?! TypeReference.JavaLangStringName,
|
||||
AndroidTypes.UserHandleName}, TypeReference.VoidName);
|
||||
final Selector mSel = new Selector(Atom.findOrCreateAsciiAtom("init"), desc); // the name of the function is actually init
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ContextImpl, mSel);
|
||||
final SSAValue exception = new SSAValue(this.pm.getUnmanaged(), TypeReference.JavaLangException, this.scope, "init_exc" );
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(7);
|
||||
params.add(packageContext);
|
||||
params.add(nullApk); // TODO: This would contain a Context too?
|
||||
params.add(nullIBinder); // OK: is null in Android-Sources too
|
||||
params.add(mainThread);
|
||||
params.add(nullResources); // TODO
|
||||
params.add(packageName);
|
||||
params.add(uid);
|
||||
final SSAInstruction call = instructionFactory.InvokeInstruction(pc, params, exception, site);
|
||||
body.addStatement(call);
|
||||
} // */
|
||||
{ // XXX: ALTERNATIVE FROM THE ABOVE, THAT IS IN STUBS!!
|
||||
// init(Landroid/app/LoadedApk;Landroid/os/IBinder;Landroid/app/ActivityThread;)V
|
||||
final SSAValue nullApk = this.pm.getUnmanaged(AndroidTypes.LoadedApk, "nullApk"); // TODO
|
||||
this.body.addConstant(nullApk.getNumber(), new ConstantValue(null));
|
||||
nullApk.setAssigned();
|
||||
|
||||
final SSAValue nullIBinder = this.pm.getUnmanaged(AndroidTypes.IBinder, "nullBinder");
|
||||
this.body.addConstant(nullIBinder.getNumber(), new ConstantValue(null));
|
||||
nullIBinder.setAssigned();
|
||||
|
||||
final int pc = this.body.getNextProgramCounter();
|
||||
final Descriptor desc = Descriptor.findOrCreate(new TypeName[] {
|
||||
AndroidTypes.LoadedApkName,
|
||||
AndroidTypes.IBinderName,
|
||||
AndroidTypes.ActivityThreadName,
|
||||
}, TypeReference.VoidName);
|
||||
final Selector mSel = new Selector(Atom.findOrCreateAsciiAtom("init"), desc); // the name of the function is actually init
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ContextImpl, mSel);
|
||||
final SSAValue exception = this.pm.getException();
|
||||
final CallSiteReference site = CallSiteReference.make(pc, mRef, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(7);
|
||||
params.add(packageContext);
|
||||
params.add(nullApk); // TODO: This would contain a Context too?
|
||||
params.add(nullIBinder); // OK: is null in Android-Sources too
|
||||
params.add(mainThread);
|
||||
final SSAInstruction call = instructionFactory.InvokeInstruction(pc, params, exception, site);
|
||||
body.addStatement(call);
|
||||
}
|
||||
return packageContext;
|
||||
}
|
||||
|
||||
private SSAValue createApplicationContext(final SSAValue mainThread, final SSAValue systemContext) {
|
||||
return null; // TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -147,6 +147,290 @@ public class AndroidStartComponentTool {
|
|||
this.callerNd = callerNd;
|
||||
}
|
||||
|
||||
public void attachActivities(Set<? extends SSAValue> activities, SSAValue application, SSAValue thread, SSAValue context,
|
||||
SSAValue iBinderToken, SSAValue intent) {
|
||||
// call: final void Activity.attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
|
||||
// Application application, Intent intent, ActivityInfo info, CharSequence title,
|
||||
// Activity parent, String id, Object lastNonConfigurationInstance,
|
||||
// Configuration config)
|
||||
|
||||
final SSAValue nullInstrumentation;
|
||||
{
|
||||
nullInstrumentation = pm.getUnmanaged(AndroidTypes.Instrumentation, "nullInstrumentation");
|
||||
this.redirect.addConstant(nullInstrumentation.getNumber(), new ConstantValue(null));
|
||||
nullInstrumentation.setAssigned();
|
||||
}
|
||||
final SSAValue nullInfo;
|
||||
{
|
||||
nullInfo = pm.getUnmanaged(AndroidTypes.ActivityInfo, "nullInfo");
|
||||
this.redirect.addConstant(nullInfo.getNumber(), new ConstantValue(null));
|
||||
nullInfo.setAssigned();
|
||||
}
|
||||
final SSAValue title;
|
||||
{
|
||||
title = pm.getUnmanaged(TypeReference.JavaLangString, "title"); // XXX CharSequence
|
||||
this.redirect.addConstant(title.getNumber(), new ConstantValue("title"));
|
||||
title.setAssigned();
|
||||
}
|
||||
final SSAValue nullParent;
|
||||
{
|
||||
nullParent = pm.getUnmanaged(AndroidTypes.Activity, "nullParent");
|
||||
this.redirect.addConstant(nullParent.getNumber(), new ConstantValue(null));
|
||||
nullParent.setAssigned();
|
||||
}
|
||||
final SSAValue nullConfigInstance;
|
||||
{
|
||||
final TypeName cName = TypeName.string2TypeName("Landroid/app/Activity$NonConfigurationInstances");
|
||||
final TypeReference type = TypeReference.findOrCreate(com.ibm.wala.types.ClassLoaderReference.Primordial, cName);
|
||||
nullConfigInstance = pm.getUnmanaged(type, "noState");
|
||||
this.redirect.addConstant(nullConfigInstance.getNumber(), new ConstantValue(null));
|
||||
nullConfigInstance.setAssigned();
|
||||
}
|
||||
final SSAValue nullConfiguration;
|
||||
{
|
||||
nullConfiguration = pm.getUnmanaged(AndroidTypes.Configuration, "nullConfig");
|
||||
this.redirect.addConstant(nullConfiguration.getNumber(), new ConstantValue(null));
|
||||
nullConfiguration.setAssigned();
|
||||
}
|
||||
|
||||
final Descriptor desc = Descriptor.findOrCreate(new TypeName[] {
|
||||
AndroidTypes.ContextName,
|
||||
AndroidTypes.ActivityThreadName,
|
||||
AndroidTypes.InstrumentationName,
|
||||
AndroidTypes.IBinderName,
|
||||
AndroidTypes.ApplicationName,
|
||||
AndroidTypes.IntentName,
|
||||
AndroidTypes.ActivityInfoName,
|
||||
TypeName.string2TypeName("Ljava/lang/CharSequence"),
|
||||
AndroidTypes.ActivityName,
|
||||
TypeReference.JavaLangString.getName(),
|
||||
TypeName.string2TypeName("Landroid/app/Activity$NonConfigurationInstances"),
|
||||
AndroidTypes.ConfigurationName }, TypeReference.VoidName);
|
||||
final Selector mSel = new Selector(Atom.findOrCreateAsciiAtom("attach"), desc);
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.Activity, mSel);
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(13);
|
||||
params.add(null); // activity
|
||||
params.add(context);
|
||||
params.add(thread);
|
||||
params.add(nullInstrumentation);
|
||||
params.add(iBinderToken);
|
||||
params.add(application);
|
||||
params.add(intent);
|
||||
params.add(nullInfo);
|
||||
params.add(title);
|
||||
params.add(nullParent);
|
||||
params.add(title);
|
||||
params.add(nullConfigInstance);
|
||||
params.add(nullConfiguration);
|
||||
|
||||
for (final SSAValue activity: activities) {
|
||||
final int callPC = redirect.getNextProgramCounter();
|
||||
final CallSiteReference site = CallSiteReference.make(callPC, mRef, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
final SSAValue exception = pm.getException();
|
||||
params.set(0, activity);
|
||||
final SSAInstruction invokation = instructionFactory.InvokeInstruction(callPC, params, exception, site);
|
||||
redirect.addStatement(invokation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AndroidTypes.AndroidContextType typeOfCallerContext() {
|
||||
return this.callerContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the context of the caller.
|
||||
*
|
||||
* @return A new SSAValue representing the androidContext (may be null!). // XXX
|
||||
*/
|
||||
public SSAValue fetchCallerContext() {
|
||||
/*if (flags.contains(StarterFlags.CONTEXT_FREE)) {
|
||||
logger.warn("Asking for context when Context-Free");
|
||||
return null; // XXX: Return a synthetic null?
|
||||
}*/
|
||||
|
||||
logger.debug("Fetching caller context...");
|
||||
final SSAValue androidContext;
|
||||
if (caller.getName().equals(AndroidTypes.ContextWrapperName)) {
|
||||
{ // Fetch ContextWrapperName.mBase => androidContext
|
||||
androidContext = pm.getUnmanaged(AndroidTypes.Context, "callerContext");
|
||||
logger.debug("Fetching ContextWrapperName.mBase");
|
||||
|
||||
final FieldReference mBaseRef = FieldReference.findOrCreate(AndroidTypes.ContextWrapper, Atom.findOrCreateAsciiAtom("mBase"),
|
||||
AndroidTypes.Context);
|
||||
final int instPC = redirect.getNextProgramCounter();
|
||||
final SSAInstruction getInst = instructionFactory.GetInstruction(instPC, androidContext, self, mBaseRef);
|
||||
redirect.addStatement(getInst);
|
||||
|
||||
// TODO: somehow dispatch on type of mBase?
|
||||
this.callerContext = AndroidTypes.AndroidContextType.CONTEXT_IMPL;
|
||||
logger.info("Caller has android-context type: ContextWrapper(ContextImpl)");
|
||||
return androidContext;
|
||||
}
|
||||
} else if (caller.getName().equals(AndroidTypes.ContextImplName)) {
|
||||
{ // self is already the right context
|
||||
androidContext = self;
|
||||
this.callerContext = AndroidTypes.AndroidContextType.CONTEXT_IMPL;
|
||||
logger.info("Caller has android-context type: ContextImpl");
|
||||
return androidContext;
|
||||
}
|
||||
} else if (caller.getName().equals(AndroidTypes.ActivityName)) {
|
||||
// We don't need it for now - TODO grab anyway
|
||||
androidContext = null;
|
||||
this.callerContext = AndroidTypes.AndroidContextType.ACTIVITY;
|
||||
logger.info("Caller has android-context type: Activity");
|
||||
return androidContext;
|
||||
} else if (caller.equals(AndroidModelClass.ANDROID_MODEL_CLASS)) {
|
||||
// TODO: Return something useful
|
||||
this.callerContext = AndroidTypes.AndroidContextType.USELESS;
|
||||
return null;
|
||||
} else if (caller.getName().equals(AndroidTypes.BridgeContextName)) {
|
||||
// XXX ???
|
||||
androidContext = self;
|
||||
this.callerContext = AndroidTypes.AndroidContextType.CONTEXT_BRIDGE;
|
||||
logger.info("Caller has android-context type: BridgeContext");
|
||||
return androidContext;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Can not handle the callers android-context of " + caller);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the permissions to start the component with.
|
||||
*
|
||||
* Fetching depends on StarterFlags.QUENCH_PERMISSIONS, XXX
|
||||
*
|
||||
* @return an iBinder
|
||||
* @throws UnsupportedOperationException when fetching is not supported with the current settings
|
||||
*/
|
||||
public SSAValue fetchIBinder(SSAValue androidContext) {
|
||||
logger.debug("Fetching context to use for call...");
|
||||
final SSAValue iBinder = pm.getUnmanaged(AndroidTypes.IBinder, "foreignIBinder");
|
||||
|
||||
if (flags.contains(StarterFlags.CONTEXT_FREE)) {
|
||||
// TODO: Can we do somethig?
|
||||
return null;
|
||||
} else if (flags.contains(StarterFlags.QUENCH_PERMISSIONS)) {
|
||||
// If this flag is set the given asMethod has a IntentSender-Parameter
|
||||
|
||||
final Parameter intentSender = acc.firstOf(AndroidTypes.IntentSenderName);
|
||||
assert (intentSender != null) : "Unable to look up the IntentSender-Object";
|
||||
assert (intentSender.getNumber() == 2) : "The IntentSender-Object was not located at SSA-Number 2. This may be entirely " +
|
||||
"ok! I left this assertion to ashure the ParameterAccessor does its job right.";
|
||||
|
||||
// retreive the IBinder: IIntentSender.asBinder()
|
||||
final SSAValue iIntentSender = pm.getUnmanaged(AndroidTypes.IIntentSender, "iIntentSender");
|
||||
{ // call IIntentSender IntentSender.getTarget()
|
||||
final int callPC = redirect.getNextProgramCounter();
|
||||
final Selector mSel = Selector.make("getTarget()Landroid/content/IIntentSender;");
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.IntentSender, mSel);
|
||||
final CallSiteReference site = CallSiteReference.make(callPC, mRef, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
final SSAValue exception = pm.getException();
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(intentSender);
|
||||
final SSAInstruction invokation = instructionFactory.InvokeInstruction(callPC, iIntentSender, params, exception, site);
|
||||
redirect.addStatement(invokation);
|
||||
}
|
||||
|
||||
{ // call IBinder IIntentSender.asBinder()
|
||||
final int callPC = redirect.getNextProgramCounter();
|
||||
final Selector mSel = Selector.make("asBinder()Landroid/os/IBinder;");
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.IntentSender, mSel);
|
||||
final CallSiteReference site = CallSiteReference.make(callPC, mRef, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
final SSAValue exception = pm.getException();
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(iIntentSender);
|
||||
final SSAInstruction invokation = instructionFactory.InvokeInstruction(callPC, iBinder, params, exception, site);
|
||||
redirect.addStatement(invokation);
|
||||
}
|
||||
|
||||
logger.info("The context to use for the call is from an IBinder");
|
||||
return iBinder;
|
||||
} else if (caller.getName().equals(AndroidTypes.ActivityName)) {
|
||||
|
||||
// The IBinder is Activity.mMainThread.getApplicationThread() // TODO: Verify
|
||||
final SSAValue mMainThread = pm.getUnmanaged(AndroidTypes.ActivityThread, "callersMainThred");
|
||||
{ // Fetch mMainthred
|
||||
final int instPC = redirect.getNextProgramCounter();
|
||||
final FieldReference mMainThreadRef = FieldReference.findOrCreate(AndroidTypes.Activity, Atom.findOrCreateAsciiAtom("mMainThread"),
|
||||
AndroidTypes.ActivityThread);
|
||||
final SSAInstruction getInst = instructionFactory.GetInstruction(instPC, mMainThread, self, mMainThreadRef);
|
||||
redirect.addStatement(getInst);
|
||||
}
|
||||
|
||||
/*{ // DEBUG
|
||||
final com.ibm.wala.classLoader.IClass activityThread = cha.lookupClass(AndroidTypes.ActivityThread);
|
||||
assert (activityThread != null);
|
||||
for (com.ibm.wala.classLoader.IMethod m : activityThread.getDeclaredMethods()) {
|
||||
System.out.println(m);
|
||||
}
|
||||
} // */
|
||||
|
||||
{ // Call getApplicationThread() on it
|
||||
final int callPC = redirect.getNextProgramCounter();
|
||||
final Selector mSel = Selector.make("getApplicationThread()Landroid/app/ActivityThread$ApplicationThread;");
|
||||
final MethodReference mRef = MethodReference.findOrCreate(AndroidTypes.ActivityThread, mSel);
|
||||
final CallSiteReference site = CallSiteReference.make(callPC, mRef, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
final SSAValue exception = pm.getException();
|
||||
final List<SSAValue> params = new ArrayList<SSAValue>(1);
|
||||
params.add(mMainThread);
|
||||
final SSAInstruction invokation = instructionFactory.InvokeInstruction(callPC, iBinder, params, exception, site);
|
||||
redirect.addStatement(invokation);
|
||||
} // */
|
||||
|
||||
logger.info("The context (IBinder) to use for the call is the one from the calling activity");
|
||||
return iBinder;
|
||||
} else if (this.callerContext == AndroidTypes.AndroidContextType.CONTEXT_IMPL) {
|
||||
// For bindService its mActivityToken - TODO: For the rest?
|
||||
// startActivity uses mMainThread.getApplicationThread()
|
||||
|
||||
{ // read mActivityToken -> iBinder
|
||||
logger.debug("Fetching ContextImpl.mActivityToken to iBinder");
|
||||
|
||||
final FieldReference mActivityTokenRef = FieldReference.findOrCreate(AndroidTypes.ContextImpl,
|
||||
Atom.findOrCreateAsciiAtom("mActivityToken"), AndroidTypes.IBinder);
|
||||
final int instPC = redirect.getNextProgramCounter();
|
||||
final SSAInstruction getInst = instructionFactory.GetInstruction(instPC, iBinder, androidContext, mActivityTokenRef);
|
||||
redirect.addStatement(getInst);
|
||||
}
|
||||
|
||||
logger.info("The context (IBinder) to use for the call is the one from the caller");
|
||||
return iBinder;
|
||||
} else if (this.callerContext == AndroidTypes.AndroidContextType.CONTEXT_BRIDGE) {
|
||||
// TODO: Return something useful
|
||||
logger.error("Not Implemented: Fetch an IBinder from a BridgeContext.");
|
||||
return null;
|
||||
} else if (caller.equals(AndroidModelClass.ANDROID_MODEL_CLASS)) {
|
||||
// TODO: Return something useful
|
||||
return null;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("No implementation on how to extract an iBinder from a " + caller);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the iBinder in the callee.
|
||||
*/
|
||||
public void assignIBinder(SSAValue iBinder, List<? extends SSAValue> allActivities) {
|
||||
if (iBinder == null) {
|
||||
// TODO: Some day we may throe here...
|
||||
return;
|
||||
}
|
||||
logger.info("Assigning the iBinder");
|
||||
// TODO: Use Phi?
|
||||
for (SSAValue activity : allActivities) {
|
||||
logger.debug("\tto: {}", activity);
|
||||
//final int callPC = redirect.getNextProgramCounter();
|
||||
|
||||
final FieldReference mTokenRef = FieldReference.findOrCreate(AndroidTypes.Activity, Atom.findOrCreateAsciiAtom("mToken"),
|
||||
AndroidTypes.IBinder);
|
||||
final int instPC = redirect.getNextProgramCounter();
|
||||
final SSAInstruction putInst = instructionFactory.PutInstruction(instPC, activity, iBinder, mTokenRef);
|
||||
redirect.addStatement(putInst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Grab mResultCode and mResultData.
|
||||
|
|
|
@ -157,6 +157,31 @@ public final /* singleton */ class AndroidEntryPointManager implements Serializa
|
|||
return prev;
|
||||
}
|
||||
|
||||
private boolean doBootSequence = true;
|
||||
/**
|
||||
* Whether to generate a global android environment.
|
||||
*
|
||||
* It's possible to analyze android-applications without creating these structures and save
|
||||
* some memory. In this case some calls to the OS (like getting the Activity-manager or so)
|
||||
* will not be able to be resolved.
|
||||
*/
|
||||
public boolean getDoBootSequence() {
|
||||
return this.doBootSequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to generate a global android environment.
|
||||
*
|
||||
* See the {@link #getDoBootSequence()} documentation.
|
||||
*
|
||||
* @return the previous setting of doBootSequence
|
||||
*/
|
||||
public boolean setDoBootSequence(boolean doBootSequence) {
|
||||
boolean prev = this.doBootSequence;
|
||||
this.doBootSequence = doBootSequence;
|
||||
return prev;
|
||||
}
|
||||
|
||||
private Class abstractAndroidModel = LoopAndroidModel.class;
|
||||
/**
|
||||
* What special handling to insert into the model.
|
||||
|
|
Loading…
Reference in New Issue