final ClassGen cg = new ClassGen(new ClassParser(new ByteArrayInputStream(b), "<generated>").parse());
final String className = cg.getClassName();
final Method[] methods = cg.getMethods();
final ConstantPoolGen cpg = cg.getConstantPool();
final InstructionFactory factory = new InstructionFactory(cg);
// for all methods, look for caller side "this.define0" calls
for (int i = 0; i < methods.length; i++) {
final MethodGen mg = new MethodGen(methods[i], className, cpg);
final InstructionList il = mg.getInstructionList();
if (il == null) continue;
InstructionHandle ih = il.getStart();
String methodName = methods[i].getName();
while (ih != null) {
final Instruction ins = ih.getInstruction();
if (ins instanceof INVOKESPECIAL
|| ins instanceof INVOKESTATIC
|| ins instanceof INVOKEVIRTUAL) {
final InvokeInstruction invokeInst = (InvokeInstruction)ins;
final String callerSideMethodClassName = invokeInst.getClassName(cpg);
final String callerSideMethodName = invokeInst.getMethodName(cpg);
if ("java.lang.ClassLoader".equals(callerSideMethodClassName)
&& "defineClass0".equals(callerSideMethodName)) {
//assert compliant JRE
Type args[] = invokeInst.getArgumentTypes(cpg);
assertSupported(args);
// store former method args in local vars
InstructionHandle ihc = null;
if (args.length > 5) {
// IBM like JRE with extra args
ihc = il.append(ih.getPrev(), factory.createStore(args[args.length - 1], 2100 + args.length - 1));
for (int index = args.length - 2; index >= 5; index--) {
ihc = il.append(ihc, InstructionFactory.createStore(args[index], 2100 + index));
}
ihc = il.append(ihc, factory.createStore(Type.OBJECT, 2016));//protection domain
}
else {
// SUN regular JRE
ihc = il.append(ih.getPrev(), factory.createStore(Type.OBJECT, 2016));//protection domain
}
ihc = il.append(ihc, factory.createStore(Type.INT, 2015));//length
ihc = il.append(ihc, factory.createStore(Type.INT, 2014));//index
ihc = il.append(ihc, factory.createStore(Type.OBJECT, 2013));//bytes
ihc = il.append(ihc, factory.createStore(Type.OBJECT, 2012));//name
// prepare method call stack
ihc = il.append(ihc, factory.createLoad(Type.OBJECT, 2012));
ihc = il.append(ihc, factory.createLoad(Type.OBJECT, 2013));
ihc = il.append(ihc, factory.createInvoke(
"com.lambda.Debugger.InstrumentorForCL",
"debugify",
new ArrayType(Type.BYTE, 1),
new Type[]{
Type.STRING,
new ArrayType(Type.BYTE, 1),
},
Constants.INVOKESTATIC));
ihc = il.append(ihc, factory.createStore(Type.OBJECT, 3018));//result bytes
// rebuild former method call stack
ihc = il.append(ihc, factory.createLoad(Type.OBJECT, 2012));//name
ihc = il.append(ihc, factory.createLoad(Type.OBJECT, 3018));//bytes
ihc = il.append(ihc, new PUSH(cpg, 0));
ihc = il.append(ihc, factory.createLoad(Type.OBJECT, 3018));//bytes
ihc = il.append(ihc, InstructionConstants.ARRAYLENGTH);//.length
ihc = il.append(ihc, factory.createLoad(Type.OBJECT, 2016));//protection domain
// extra args for IBM like JRE
if (args.length > 5) {
for (int index = 5; index < args.length; index++) {
ihc = il.append(ihc, factory.createLoad(args[index], 2100 + index));
}
}
}
}
ih = ih.getNext();