Hello Jan, thank you.
I am trying to instrument APK applications using a well know sample taken from Soot tutorials.
PackManager.v().getPack("jtp").add(new Transform("jtp.myInstrumenter", new BodyTransformer() {
@Override
protected void internalTransform(final Body b, String phaseName,
@SuppressWarnings("rawtypes") Map options) {
final PatchingChain<Unit> units = b.getUnits();
// important to use snapshotIterator here
for (Iterator<Unit> iter = units.snapshotIterator(); iter.hasNext();) {
final Unit u = iter.next();
u.apply(new AbstractStmtSwitch() {
public void caseInvokeStmt(InvokeStmt stmt) {
InvokeExpr invokeExpr = stmt.getInvokeExpr();
String methodSignature = invokeExpr.getMethodRef().getSignature();
String instrumentation = checkCallType(methodSignature);
Local tmpRef = addTmpRef(b);
Local tmpString = addTmpString(b);
// insert "tmpRef = java.lang.System.out;"
units.insertBefore(
Jimple.v().newAssignStmt(tmpRef, Jimple.v().newStaticFieldRef(Scene.v()
.getField("<java.lang.System: java.io.PrintStream out>").makeRef())),
u);
// insert "tmpLong = instrumentation"
LOGGER.debug("--> INSTRUMENTATION " + instrumentation);
units.insertBefore(
Jimple.v().newAssignStmt(tmpString, StringConstant.v(instrumentation)), u);
// insert "tmpRef.println(tmpString);"
SootMethod toCall = Scene.v().getSootClass("java.io.PrintStream")
.getMethod("void println(java.lang.String)");
units.insertBefore(
Jimple.v().newInvokeStmt(
Jimple.v().newVirtualInvokeExpr(tmpRef, toCall.makeRef(), tmpString)),
u);
// check Jimple code
b.validate();
}
});
}
}
}));
soot.Main.main(args);
It works quite well on most of public APK files, but sometimes crashes on specific scenarios. For example, if APK is multi dex, it may stop working with the following exception:
[Thread-17] ERROR heros.solver.CountingThreadPoolExecutor - Worker thread execution failed: Dex file overflow. Splitting not support for pre Lollipop Android (Api 22).
java.lang.RuntimeException: Dex file overflow. Splitting not support for pre Lollipop Android (Api 22).
at soot.toDex.MultiDexBuilder.hasOverflowed(MultiDexBuilder.java:62)
at soot.toDex.MultiDexBuilder.internClass(MultiDexBuilder.java:37)
at soot.toDex.DexPrinter.addAsClassDefItem(DexPrinter.java:586)
at soot.toDex.DexPrinter.add(DexPrinter.java:1490)
at soot.PackManager.writeClass(PackManager.java:1060)
at soot.PackManager.access$100(PackManager.java:112)
at soot.PackManager$2.run(PackManager.java:664)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
I already asked on a different thread regarding this specific issue, but now the question is: how I can catch this exception from my program ? It seems to be thrown by PackManager, but I am not able to catch it (I think it depends on threads nature).