My goal is to instrument a small amount of code at the beginning of every basic block of some Java bytecode. The purpose is to record the execution path through basic blocks. Currently, I am using Javassist to instrument some code at the beginning and at the end of methods, but I've run into a wall with the Javassist API in instrumenting finer bytecode locations.
Javassist provides me with a Block[] that represents all of the basic blocks within a method. The basic blocks can report their bytecode locations, so I know where my instrumentation needs to go. Javassist's instrumentation that I wanted to use was CtMethod.insertAt(int sourceCodeLineNumber,String newSourceCode), however this uses the source code line number rather than the bytecode line number, which causes the problems illustrated in this question (I'm fairly certain there's no fix to that problem by this point).
The Question: How can I assign values to variables within a method using instrumentation when the variables themselves are from Javassist instrumentation. I'd preferably not have to use other tools, but I'm taking any help that I can get by this point.
Variables are declared like this using Javassist:
//m is a CtMethod
try { m.addLocalVariable("someVar", ClassPool.getDefault().get("SomePackage.SomeClass")); }
catch (NotFoundException e) { e.printStackTrace(); }
My worst case scenario is somehow extrapolate the stack variable that javassist instruments and insert the bytecode with an iterator that goes through the entire method/class, but that'd be really nasty. My method only has an integer input (the block ID) and void output, so the Java bytecode would look like this at the beginning of every basic block:
ALOAD 6 //6 is my new Javassist variable ID, however I don't think I can get Javassist to actually tell it to me
ICONST_1 //My parameters, which is an int. I'd have to switch statement between ICONST, SIPUSH, and ALOAD depending on basic block's index size
INVOKEVIRTUAL SomePackage/SomeClass.SomeMethod(I)V