3

I am trying to write an instrumentation module for Java programs. One particular instrumentation I am looking to add is collecting all the objects in a method's argument list and do some processing on them.

Currently, to get the list of object arguments, I pop all the method args from stack, and then push them in one by one, adding my instrumentation call in between. While this mostly works, I see some

java.lang.VerifyError, [1] (****) Incompatible argument to function

type errors in large programs. Does popping and then pushing an object back to stack change its type somehow? Alternatively, is there a better solution for duplicating 'N' arguments from the stack without popping?

arunxls
  • 124
  • 1
  • 9
  • The jvm stack instructions are typed too, that is you cannot push 2 floats and call a method with a double. A mistake would be to forget the `this` parameter. In every case it seems you either call the wrong method signature or have wrong stack arguments. – Joop Eggen Mar 30 '15 at 10:48
  • I ensured the primitive types get called correctly. I see this error only for objects. What happens when I have a cast and I pop-push the object? Are there any other corner cases I would have missed? – arunxls Mar 30 '15 at 10:55
  • I would know of nothing but a wrong function call, parameters, object, result, to be responsible - as the error message says. Try to restart with the original class and apply patches till the error happens. – Joop Eggen Mar 30 '15 at 11:16
  • Could you post the actual bytecode? There's not much that can be done without it. Otherwise, I second Joop Eggen's advice. Also, are you using inference or stackmap verification? – Antimony Mar 30 '15 at 14:49
  • 2
    Your initial premise sounds wrong as method arguments are passed in local variables, not on the stack so you can’t pop them in the first place. So it would be good if you try to explain what you are really doing using the correct terms, or even better, post actual code. – Holger Mar 31 '15 at 13:17

1 Answers1

1

Where are you popping your arguments to? You need to store them in the local variable array, I assume? It is perfectly possible that you override variables that are stored there already but which are accessed later. In this case, you might have changed the types of the stored variables which yields an error during verification.

As verification is a determinisitic process: Simply compare the byte code of a failing method to the verifiers complaint and make sure that the types match.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • Sorry I forgot to update this. You are right - I had a bug somewhere that resulted in me overwriting the last element of the existing local variable array. I found [ASM's class verifier](http://asm.ow2.org/doc/faq.html#Q4) very helpful in debugging this. Thanks! – arunxls Jul 23 '15 at 20:07