[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);
		    }
	    }
	}
    }
}