The best way that I found to get the variable ID from the ConstPool table is testing the max size after inserting your variable
try { m.addLocalVariable(mse, ClassPool.getDefault().get("org.javadynamicanalyzer.MethodStackEntry")); }
catch (NotFoundException e) { e.printStackTrace(); }
int mseCSindex=m.getMethodInfo().getCodeAttribute().getMaxLocals()-1;
Next, I needed the invokevirtual index from the table. This was slightly suckier to find. The code below searches the ConstPool table for the function that I'm looking for. The function I'm searching for is in org.javadyanmicanalyzer.MethodStackEntry.setBlockID(int)
.
int virtFunIndex=-1;
boolean found=false;
while(found==false){
++virtFunIndex;
try{
int id=cp.isMember("org.javadynamicanalyzer.MethodStackEntry", "setBlockIndex", virtFunIndex);
if(id!=0){
found=true;
}
}
catch(NullPointerException | ClassCastException e){}
}
Finally, I needed to instrument the beginning of each Block:
int len=new ControlFlow(m).basicBlocks().length;
for(int i=0; i<len; ++i){
Block thisbb=new ControlFlow(m).basicBlocks()[i]; //we have to re-evaluate the control flow every time we add new code
CodeIterator itr=m.getMethodInfo().getCodeAttribute().iterator();
int pos=thisbb.position();
byte[] newCode=new byte[]{Bytecode.ALOAD, //loads the mse class
mseCSindex, //my mse local variable
Bytecode.ICONST_0, //the input to the virtual function
Bytecode.INVOKEVIRTUAL, //execute the virtual function
(byte) virtFunIndex>>8, //virtual function's address
(byte) virtFunIndex && 0xFF};
int n = itr.insertAt(pos, newCode);
}
It's messy and has the potential to completely destroy itself, but it worked!