use of soot.PrimType 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