use of soot.FastHierarchy in project soot by Sable.
the class VirtualCalls method resolveLibrarySignature.
protected void resolveLibrarySignature(Type declaredType, Type sigType, NumberedString subSig, SootMethod container, ChunkedQueue<SootMethod> targets, boolean appOnly, RefType base) {
FastHierarchy fastHierachy = Scene.v().getOrMakeFastHierarchy();
assert (declaredType instanceof RefType);
Pair<Type, NumberedString> pair = new Pair<Type, NumberedString>(base, subSig);
{
Set<Pair<Type, NumberedString>> types = baseToPossibleSubTypes.get(pair);
// just retrieve the previous result.
if (types != null) {
for (Pair<Type, NumberedString> tuple : types) {
Type st = tuple.getO1();
if (!fastHierachy.canStoreType(st, declaredType)) {
resolve(st, st, sigType, subSig, container, targets, appOnly);
} else {
resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
}
}
return;
}
}
Set<Pair<Type, NumberedString>> types = new HashSet<Pair<Type, NumberedString>>();
// get return type; method name; parameter types
String[] split = subSig.getString().replaceAll("(.*) (.*)\\((.*)\\)", "$1;$2;$3").split(";");
Type declaredReturnType = Scene.v().getType(split[0]);
String declaredName = split[1];
List<Type> declaredParamTypes = new ArrayList<Type>();
// separate the parameter types
if (split.length == 3) {
for (String type : split[2].split(",")) {
declaredParamTypes.add(Scene.v().getType(type));
}
}
Chain<SootClass> classes = Scene.v().getClasses();
for (SootClass sc : classes) {
for (SootMethod sm : sc.getMethods()) {
if (sm.isConcrete() || sm.isNative()) {
// method name has to match
if (!sm.getName().equals(declaredName))
continue;
// type or a sub type of it
if (!fastHierachy.canStoreType(sm.getReturnType(), declaredReturnType))
continue;
List<Type> paramTypes = sm.getParameterTypes();
// ones (same type or super type).
if (declaredParamTypes.size() != paramTypes.size())
continue;
boolean check = true;
for (int i = 0; i < paramTypes.size(); i++) {
if (!fastHierachy.canStoreType(declaredParamTypes.get(i), paramTypes.get(i))) {
check = false;
break;
}
}
if (check) {
Type st = sc.getType();
if (!fastHierachy.canStoreType(st, declaredType)) {
// therefore not used in library client
if (!sc.isFinal()) {
NumberedString newSubSig = sm.getNumberedSubSignature();
resolve(st, st, sigType, newSubSig, container, targets, appOnly);
types.add(new Pair<Type, NumberedString>(st, newSubSig));
}
} else {
resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
types.add(new Pair<Type, NumberedString>(st, subSig));
}
}
}
}
}
baseToPossibleSubTypes.putAll(pair, types);
}
use of soot.FastHierarchy in project soot by Sable.
the class OnFlyCallGraphBuilder method addType.
public void addType(Local receiver, Context srcContext, Type type, Context typeContext) {
FastHierarchy fh = Scene.v().getOrMakeFastHierarchy();
if (receiverToSites.get(receiver) != null) {
for (Iterator<VirtualCallSite> siteIt = receiverToSites.get(receiver).iterator(); siteIt.hasNext(); ) {
final VirtualCallSite site = siteIt.next();
if (site.kind() == Kind.THREAD && !fh.canStoreType(type, clRunnable))
continue;
if (site.kind() == Kind.EXECUTOR && !fh.canStoreType(type, clRunnable))
continue;
if (site.kind() == Kind.ASYNCTASK && !fh.canStoreType(type, clAsyncTask))
continue;
if (site.kind() == Kind.HANDLER && !fh.canStoreType(type, clHandler))
continue;
if (site.iie() instanceof SpecialInvokeExpr && site.kind != Kind.THREAD && site.kind != Kind.EXECUTOR && site.kind != Kind.ASYNCTASK) {
SootMethod target = VirtualCalls.v().resolveSpecial((SpecialInvokeExpr) site.iie(), site.subSig(), site.container(), appOnly);
// simply do not add the target in that case
if (target != null) {
targetsQueue.add(target);
}
} else {
VirtualCalls.v().resolve(type, receiver.getType(), site.subSig(), site.container(), targetsQueue, appOnly);
}
while (targets.hasNext()) {
SootMethod target = targets.next();
cm.addVirtualEdge(MethodContext.v(site.container(), srcContext), site.stmt(), target, site.kind(), typeContext);
}
}
}
if (baseToInvokeSite.get(receiver) != null) {
addBaseType(receiver, srcContext, type);
}
}
use of soot.FastHierarchy in project soot by Sable.
the class VirtualCalls method resolveAnySubType.
protected void resolveAnySubType(Type declaredType, Type sigType, NumberedString subSig, SootMethod container, ChunkedQueue<SootMethod> targets, boolean appOnly, RefType base) {
FastHierarchy fastHierachy = Scene.v().getOrMakeFastHierarchy();
{
Set<Type> subTypes = baseToSubTypes.get(base);
if (subTypes != null && !subTypes.isEmpty()) {
for (final Type st : subTypes) {
resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
}
return;
}
}
Set<Type> newSubTypes = new HashSet<>();
newSubTypes.add(base);
LinkedList<SootClass> worklist = new LinkedList<SootClass>();
HashSet<SootClass> workset = new HashSet<SootClass>();
FastHierarchy fh = fastHierachy;
SootClass cl = base.getSootClass();
if (workset.add(cl))
worklist.add(cl);
while (!worklist.isEmpty()) {
cl = worklist.removeFirst();
if (cl.isInterface()) {
for (Iterator<SootClass> cIt = fh.getAllImplementersOfInterface(cl).iterator(); cIt.hasNext(); ) {
final SootClass c = cIt.next();
if (workset.add(c))
worklist.add(c);
}
} else {
if (cl.isConcrete()) {
resolve(cl.getType(), declaredType, sigType, subSig, container, targets, appOnly);
newSubTypes.add(cl.getType());
}
for (Iterator<SootClass> cIt = fh.getSubclassesOf(cl).iterator(); cIt.hasNext(); ) {
final SootClass c = cIt.next();
if (workset.add(c))
worklist.add(c);
}
}
}
baseToSubTypes.putAll(base, newSubTypes);
}
use of soot.FastHierarchy in project soot by Sable.
the class ThrowableSet method whichCatchableAs.
/**
* Partitions the exceptions in this <code>ThrowableSet</code> into those
* which would be caught by a handler with the passed <code>catch</code>
* parameter type and those which would not.
*
* @param catcher
* type of the handler parameter to be tested.
*
* @return a pair of <code>ThrowableSet</code>s, one containing the types in
* this <code>ThrowableSet</code> which would be be caught as
* <code>catcher</code> and the other containing the types in this
* <code>ThrowableSet</code> which would not be caught as
* <code>catcher</code>.
*/
public Pair whichCatchableAs(RefType catcher) {
if (INSTRUMENTING) {
Manager.v().removesOfAnySubType++;
}
FastHierarchy h = Scene.v().getOrMakeFastHierarchy();
Set<RefLikeType> caughtIncluded = null;
Set<AnySubType> caughtExcluded = null;
Set<RefLikeType> uncaughtIncluded = null;
Set<AnySubType> uncaughtExcluded = null;
if (INSTRUMENTING) {
Manager.v().removesFromSearch++;
}
for (AnySubType exclusion : exceptionsExcluded) {
RefType exclusionBase = exclusion.getBase();
// Is the current type explicitly excluded?
if (catcher.getSootClass().isPhantom() && exclusionBase.equals(catcher))
return new Pair(ThrowableSet.Manager.v().EMPTY, this);
if (h.canStoreType(catcher, exclusionBase)) {
// caught by catcher.
return new Pair(ThrowableSet.Manager.v().EMPTY, this);
} else if (h.canStoreType(exclusionBase, catcher)) {
// exclusion wouldn't be in exceptionsExcluded if one
// of its supertypes were not in exceptionsIncluded,
// so we know the next loop will add either that supertype
// or catcher to caughtIncluded. Thus:
caughtExcluded = addExceptionToSet(exclusion, caughtExcluded);
} else {
uncaughtExcluded = addExceptionToSet(exclusion, uncaughtExcluded);
}
}
for (RefLikeType inclusion : exceptionsIncluded) {
if (inclusion instanceof RefType) {
// only if it is in the inclusion list and ignore any hierarchy.
if (catcher.getSootClass().isPhantom()) {
if (inclusion.equals(catcher))
caughtIncluded = addExceptionToSet(inclusion, caughtIncluded);
else
uncaughtIncluded = addExceptionToSet(inclusion, uncaughtIncluded);
} else if (h.canStoreType(inclusion, catcher)) {
caughtIncluded = addExceptionToSet(inclusion, caughtIncluded);
} else {
uncaughtIncluded = addExceptionToSet(inclusion, uncaughtIncluded);
}
} else {
RefType base = ((AnySubType) inclusion).getBase();
// only if it is in the inclusion list and ignore any hierarchy.
if (catcher.getSootClass().isPhantom()) {
if (base.equals(catcher))
caughtIncluded = addExceptionToSet(inclusion, caughtIncluded);
else {
if (base.getClassName().equals("java.lang.Throwable"))
caughtIncluded = addExceptionToSet(catcher, caughtIncluded);
uncaughtIncluded = addExceptionToSet(inclusion, uncaughtIncluded);
}
} else if (h.canStoreType(base, catcher)) {
// All subtypes of base will be caught. Any exclusions
// will already have been copied to caughtExcluded by
// the preceding loop.
caughtIncluded = addExceptionToSet(inclusion, caughtIncluded);
} else if (h.canStoreType(catcher, base)) {
// Some subtypes of base will be caught, and
// we know that not all of those catchable subtypes
// are among exceptionsExcluded, since in that case we
// would already have returned from within the
// preceding loop. So, remove AnySubType(catcher)
// from the uncaught types.
uncaughtIncluded = addExceptionToSet(inclusion, uncaughtIncluded);
uncaughtExcluded = addExceptionToSet(AnySubType.v(catcher), uncaughtExcluded);
caughtIncluded = addExceptionToSet(AnySubType.v(catcher), caughtIncluded);
// Any already excluded subtypes of inclusion
// which are subtypes of catcher will have been
// added to caughtExcluded by the previous loop.
} else {
uncaughtIncluded = addExceptionToSet(inclusion, uncaughtIncluded);
}
}
}
ThrowableSet caughtSet = Manager.v().registerSetIfNew(caughtIncluded, caughtExcluded);
ThrowableSet uncaughtSet = Manager.v().registerSetIfNew(uncaughtIncluded, uncaughtExcluded);
return new Pair(caughtSet, uncaughtSet);
}
use of soot.FastHierarchy in project soot by Sable.
the class BuildIntermediateAppClasses method internalTransform.
protected void internalTransform(String phaseName, Map<String, String> options) {
if (output) {
out.println("Building Intermediate Classes...");
}
BodyBuilder.retrieveAllBodies();
// iterate through application classes, build intermediate classes
Iterator<SootClass> it = Scene.v().getApplicationClasses().snapshotIterator();
while (it.hasNext()) {
List<SootMethod> initMethodsToRewrite = new ArrayList<>();
Map<String, SootMethod> methodsToAdd = new HashMap<>();
SootClass sc = it.next();
SootClass originalSuperclass = sc.getSuperclass();
if (output) {
out.println("Processing " + sc.getName() + " with super " + originalSuperclass.getName());
}
Iterator<SootMethod> methodIterator = sc.methodIterator();
while (methodIterator.hasNext()) {
SootMethod method = methodIterator.next();
if (!method.isConcrete()) {
continue;
}
try {
method.getActiveBody();
} catch (Exception e) {
if (method.retrieveActiveBody() == null)
throw new RuntimeException(method.getSignature() + " has no body. This was not expected dude.");
}
String subSig = method.getSubSignature();
if (subSig.equals("void main(java.lang.String[])") && method.isPublic() && method.isStatic()) {
// skip the main method - it needs to be named 'main'
continue;
} else if (subSig.indexOf("init>(") > 0) {
if (subSig.startsWith("void <init>(")) {
initMethodsToRewrite.add(method);
}
// skip constructors, just add for rewriting at the end
continue;
} else {
Scene.v().releaseActiveHierarchy();
findAccessibleInSuperClassesBySubSig(sc, subSig).ifPresent(m -> methodsToAdd.put(subSig, m));
}
}
if (methodsToAdd.size() > 0) {
final String fullName = ClassRenamer.v().getNewName(ClassRenamer.getPackageName(sc.getName()), null);
if (output) {
out.println("\tBuilding " + fullName);
}
// make non-final soot class
SootClass mediatingClass = new SootClass(fullName, sc.getModifiers() & (~Modifier.FINAL));
Main.IntermediateAppClasses.add(mediatingClass);
mediatingClass.setSuperclass(originalSuperclass);
Scene.v().addClass(mediatingClass);
mediatingClass.setApplicationClass();
mediatingClass.setInScene(true);
ThisRef thisRef = new ThisRef(mediatingClass.getType());
for (String subSig : methodsToAdd.keySet()) {
SootMethod originalSuperclassMethod = methodsToAdd.get(subSig);
List<Type> paramTypes = originalSuperclassMethod.getParameterTypes();
Type returnType = originalSuperclassMethod.getReturnType();
List<SootClass> exceptions = originalSuperclassMethod.getExceptions();
int modifiers = originalSuperclassMethod.getModifiers() & ~Modifier.ABSTRACT & ~Modifier.NATIVE;
SootMethod newMethod;
{
// build new junk method to call original method
String newMethodName = MethodRenamer.v().getNewName();
newMethod = Scene.v().makeSootMethod(newMethodName, paramTypes, returnType, modifiers, exceptions);
mediatingClass.addMethod(newMethod);
Body body = Jimple.v().newBody(newMethod);
newMethod.setActiveBody(body);
Chain<Local> locals = body.getLocals();
PatchingChain<Unit> units = body.getUnits();
BodyBuilder.buildThisLocal(units, thisRef, locals);
BodyBuilder.buildParameterLocals(units, locals, paramTypes);
if (returnType instanceof VoidType) {
units.add(Jimple.v().newReturnVoidStmt());
} else if (returnType instanceof PrimType) {
units.add(Jimple.v().newReturnStmt(IntConstant.v(0)));
} else {
units.add(Jimple.v().newReturnStmt(NullConstant.v()));
}
newmethods++;
}
// end build new junk method to call original method
{
// build copy of old method
newMethod = Scene.v().makeSootMethod(originalSuperclassMethod.getName(), paramTypes, returnType, modifiers, exceptions);
mediatingClass.addMethod(newMethod);
Body body = Jimple.v().newBody(newMethod);
newMethod.setActiveBody(body);
Chain<Local> locals = body.getLocals();
PatchingChain<Unit> units = body.getUnits();
Local ths = BodyBuilder.buildThisLocal(units, thisRef, locals);
List<Local> args = BodyBuilder.buildParameterLocals(units, locals, paramTypes);
SootMethodRef superclassMethodRef = originalSuperclassMethod.makeRef();
if (returnType instanceof VoidType) {
units.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(ths, superclassMethodRef, args)));
units.add(Jimple.v().newReturnVoidStmt());
} else {
Local loc = Jimple.v().newLocal("retValue", returnType);
body.getLocals().add(loc);
units.add(Jimple.v().newAssignStmt(loc, Jimple.v().newSpecialInvokeExpr(ths, superclassMethodRef, args)));
units.add(Jimple.v().newReturnStmt(loc));
}
newmethods++;
}
// end build copy of old method
}
sc.setSuperclass(mediatingClass);
// rewrite class init methods to call the proper superclass inits
int i = initMethodsToRewrite.size();
while (i-- > 0) {
SootMethod im = initMethodsToRewrite.remove(i);
Body b = im.getActiveBody();
Local thisLocal = b.getThisLocal();
Iterator<Unit> uIt = b.getUnits().snapshotIterator();
while (uIt.hasNext()) {
for (ValueBox valueBox : uIt.next().getUseBoxes()) {
Value v = valueBox.getValue();
if (v instanceof SpecialInvokeExpr) {
SpecialInvokeExpr sie = (SpecialInvokeExpr) v;
SootMethodRef smr = sie.getMethodRef();
if (sie.getBase().equivTo(thisLocal) && smr.declaringClass().getName().equals(originalSuperclass.getName()) && smr.getSubSignature().getString().startsWith("void " + constructorName)) {
SootMethod newSuperInit;
if (!mediatingClass.declaresMethod(constructorName, smr.parameterTypes())) {
List<Type> paramTypes = smr.parameterTypes();
newSuperInit = Scene.v().makeSootMethod(constructorName, paramTypes, smr.returnType());
mediatingClass.addMethod(newSuperInit);
JimpleBody body = Jimple.v().newBody(newSuperInit);
newSuperInit.setActiveBody(body);
PatchingChain<Unit> initUnits = body.getUnits();
Collection<Local> locals = body.getLocals();
Local ths = BodyBuilder.buildThisLocal(initUnits, thisRef, locals);
List<Local> args = BodyBuilder.buildParameterLocals(initUnits, locals, paramTypes);
initUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(ths, smr, args)));
initUnits.add(Jimple.v().newReturnVoidStmt());
} else {
newSuperInit = mediatingClass.getMethod(constructorName, smr.parameterTypes());
}
sie.setMethodRef(newSuperInit.makeRef());
}
}
}
}
}
// end of rewrite class init methods to call the proper superclass inits
}
}
newclasses = Main.IntermediateAppClasses.size();
Scene.v().releaseActiveHierarchy();
Scene.v().getActiveHierarchy();
Scene.v().setFastHierarchy(new FastHierarchy());
}
Aggregations