[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
inserting instructions with Baf
Hi,
I am trying to insert artificial INVOKESTATIC's right before other
method calls in a classfile, using Soot.
I can get it to work in Jimple, except that sometimes there are
intervening bytecodes:
INVOKESTATIC
possible intervening bytecodes
INVOKE<X>
I tried using Baf, since it works at the instruction level, but I can't
seem to get a (Patching)Chain of Units that can be cast to Inst ... it
only works for Stmt. Another alternative would be some trick in Jimple
that always put the INVOKESTATIC right before the INVOKE<X>, but I can't
think of a way to do it.
Attached is some code showing what I've tried.
Thanks for any help,
Chris
import soot.baf.*;
import soot.baf.internal.*;
import soot.baf.toolkits.base.*;
import soot.jimple.*;
import soot.jimple.internal.*;
import soot.jimple.toolkits.scalar.*;
import soot.util.*;
import java.io.*;
import java.util.*;
public class EnableSpmt {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println(
"Syntax: java EnableSpmt [soot options] classfile");
System.exit(0);
}
PackManager.v().getPack("jtp").add(
new Transform("jtp.spmt", SpmtTransformer.v()));
soot.Main.main(args);
}
}
class SpmtTransformer extends BodyTransformer {
private static SpmtTransformer instance = new SpmtTransformer();
private SpmtTransformer() {}
public static SpmtTransformer v() { return instance; }
protected void internalTransform(Body body,
String phaseName,
Map options) {
PatchingChain units = body.getUnits();
boolean isMainMethod = body.getMethod().getSubSignature().equals(
"void main(java.lang.String[])");
Iterator stmtIt = units.snapshotIterator();
synchronized(this) {
/* check that there is a main method */
if (!Scene.v().getMainClass().
declaresMethod("void main(java.lang.String[])"))
throw new RuntimeException(
"couldn't find main() in mainClass");
/* insert InvokeStmt's -- this works, except sometimes
you end up with extra instructions in the bytecode
between the invokestatic <Spmt.fork()> and the
invoke<x> ... that's why I tried using Baf.
*/
while(stmtIt.hasNext()) {
Stmt s = (Stmt) stmtIt.next();
SootMethod m;
SootClass c;
/* insert forks before every method call
note: I'm not sure about whether or not we need to create
multiple SootClass objects, for now I am doing that.
*/
if (s instanceof InvokeStmt) {
m = new SootMethod("fork",
new LinkedList(),
VoidType.v());
c = new SootClass("Spmt");
c.addMethod(m);
InvokeStmt toAdd1 = Jimple.v().newInvokeStmt(
Jimple.v().newStaticInvokeExpr(m));
units.insertBefore(toAdd1, s);
}
}
/* insert <X>InvokeInst's -- this code won't get executed
as is (we are at the end of stmtIt),
it's just here to show you what doesn't work (the cast
fails; if i check every object with instanceof then
none of them make it past the test).
*/
while(stmtIt.hasNext()) {
Inst i = (Inst) stmtIt.next();
SootMethod m;
SootClass c;
if (i instanceof InterfaceInvokeInst ||
i instanceof SpecialInvokeInst ||
i instanceof StaticInvokeInst ||
i instanceof VirtualInvokeInst)
{
m = new SootMethod("fork",
new LinkedList(),
VoidType.v());
c = new SootClass("Spmt");
c.addMethod(m);
StaticInvokeInst toAdd1 =
Baf.v().newStaticInvokeInst(m);
units.insertBefore(toAdd1, i);
}
}
}
}
}