[Soot-list] Generating invalid code

Marc Hull (Imperial College) mfh02 at doc.ic.ac.uk
Thu Feb 9 13:26:17 EST 2006


Hi,
I'm trying to use Soot to add code to the start of certain methods, but 
I keep generating bytecode that fails verifier checks when I run it. 
I've narrowed it down to the statement that ties the 'this' reference to 
a local:

SootClass sClass = Scene.v().loadClassAndSupport(a.getClass().getName());

... snip (obtain SootMethod for required method and store it in 
'method') ...

Local a0 = Jimple.v().newLocal("a0", RefType.v(method.getDeclaringClass()));
body.getLocals().add(a0);

units.add(
  Jimple.v().newIdentityStmt(
    a0,
    Jimple.v().newThisRef(
      RefType.v(method.getDeclaringClass())
    )
  )
);

Chain oldUnits = body.getUnits();
oldUnits.insertBefore(units, oldUnits.getFirst());

... snip ...

fileName = "C:/temp/A.class";
streamOut = new JasminOutputStream(new FileOutputStream(fileName));
writerOut = new PrintWriter(new OutputStreamWriter(streamOut));
JasminClass jasminClass = new soot.jimple.JasminClass(sClass);
jasminClass.print(writerOut);
writerOut.flush();
streamOut.close();

When I try to load the class, I get (where 'String getName()' is the 
altered method):

Exception in thread "main" java.lang.VerifyError: (class: test/A, 
method: getName signature: ()Ljava/lang/String;) Incompatible type for 
getting or setting field
    at uk.ac.ic.doc.cuXca.prototypes.soot.SootTest1.main(SootTest1.java:55)

Looking at the bytecode for the class reveals:

public java.lang.String getName();
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #12; //Field 
java/lang/System.out:Ljava/io/PrintStream;
   3:   astore_0
   4:   aload_0
   5:   ldc     #11; //String Called A.getName()
   7:   invokevirtual   #24; //Method 
java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   10:  aload_0
   11:  getfield        #25; //Field name:Ljava/lang/String;
   14:  astore_0
   15:  aload_0
   16:  areturn

The bytecode for the original, unaltered method is:

public java.lang.String getName();
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #23; //Field 
java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #25; //String Called A.getName()
   5:   invokevirtual   #31; //Method 
java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   8:   aload_0
   9:   getfield        #33; //Field name:Ljava/lang/String;
   12:  areturn

Am I right in thinking that astore_0 is overwriting the 'this' pointer 
and that's why the verify is failing? I've only ever seen astore_0 in 
static methods, but this is definitely an instance method. I can't work 
out why this would be inserted when I'm just trying to access the 'this' 
pointer, not set it.

Any help greatly appreciated,
Marc


More information about the Soot-list mailing list