Hi bruno. We wrote something along these lines for the execution path watermark implemented in sandmark. Unfortunately, that code is only in cvs, but maybe someone on the sandmark mailing list ( [EMAIL PROTECTED]) can hook you up somehow. My recollection is that we collected a trace of what basic blocks were executed (from which a full instruction trace can be extracted) by adding something like to following code to each block.
BasicBlockLog.log(blockNum) where each block was instrumented to pass a different number as blockNum and BasicBlockLog was a class that we inserted into the instrumented app that had a thread local block trace (i.e., a List<Integer>) to which BasicBlockLog.log would add. I think BasicBlockLog would also start up a thread that would write logs to disk when they got too big. By instrumenting in this way, instrumented apps could actually run in reasonable times and the logs were small enough to be processed in very reasonable times. Your code below is a good start but has a couple problems. First, i don't think your trace will be correct if any kind of branches occur because the branch will target the same instruction it did before you instrumented, thus skipping your println code. You need to redirect branch targets to the instrumentation code to make this work. This is in fact a PITA. For example, if your original code is: goto nop nop and you instrument it like this (which is how you're currently doing it i think): System.out.println("executing goto nop"); goto nop System.out.println("executing nop"); nop your trace will look like: executing goto nop so you have to make it look like this: System.out.println("executing goto nop"); goto System.out.println("executing nop"); System.out.println("executing nop"); nop You can use the InstructionHandle.getTargeters method and the InstructionTargeter interface to make this work. but watch out for exceptions: don't move the endPC of an exception to the first instrumentation instruction, because then the last instruction the handler was meant to catch will no longer be in the range. it also appears that you're having some problems with constructors. i can't immediately see exactly what that would be so if you continue to have problems in that area, please describe what you're seeing. one thing i noticed was that you tried skipping instrumentation of the first instruction in a constructor. i guess that was meant to skip the super(), though i can't figure out why you need to do so. as you probably found out, super() is not always the first instruction of the constructor. you can try a little harder by watching for invokespecial SuperClass.<init>, and not instrumenting until after that, but watch out for this case: class A { A(A a1,A a2) {}} class B extends A { B() { super(new A(),new A()); } then the superclass constructor gets called 3 times and only one of them is the one you're looking for. you'll need to use at least stack depth analysis (which handles everything generated by javac) and even better data flow analysis (which catches cases generated by other tools that might, for the example above, evaluate new A() before loading this onto the stack, then using swap) to reliably find super(). good luck. On 11/9/05, Bruno Silveira Neves <[EMAIL PROTECTED]> wrote: > > Hi! > > My name is Bruno Neves, I am a Phd. Student at Federal University Of Rio > Grande. > I need build a instrumenter using BCEL to generate a instrucion > (bytecode) trace file of some applications. So, I'd like to know if > someone have already contructed this kind of tool using BCEL and can > give me the code or some (suggestion) to help me fix my code (attached > file). > > I have interest in see more small examples of using BCEL too. > > Tank you of any help! > > regards, > > Bruno. > > > ________________ > > import java.io.*; > import java.util.Iterator; > import org.apache.bcel.classfile.*; > import org.apache.bcel.generic.*; > import org.apache.bcel.Repository; > import org.apache.bcel.util.InstructionFinder; > > public class MakeTrace { > > static ClassParser p; > static JavaClass jc; > static ClassGen cg; > static MethodGen mg; > static Method method; > static ConstantPoolGen cp; > > public static void main(String[] args) { > String path = "C:\\a\\i\\"; > File in_dir = new File(path); > String filelist[] = in_dir.list(); > int numClassFiles = 0; > for (int i = 0; i < filelist.length; i++) { // > String filename = filelist[i]; > if (filename.endsWith(".class") && > !filename.equals("MyCounter.class")) { > numClassFiles++; > } > } > String filesToInstrument[] = new String[numClassFiles]; > int counter = 0; > for (int i = 0; i < filelist.length; i++) { // > String filename = filelist[i]; > if (filename.endsWith(".class") && > !filename.equals("MyCounter.class")) { > int pos = filename.indexOf("."); > String nameClass = filename.substring(0, pos); > filesToInstrument[counter] = nameClass; > counter++; > Instrument("C:\\a\\i\\", "C:\\a\\o\\", filename); > } > } > } > > public static void Instrument(String pathIn, String pathOut, String > classFile) { > try{ > //........READING CLASSFILE > p = new ClassParser(classFile); > jc = p.parse(); > cg = new ClassGen(jc); > cp = new ConstantPoolGen(jc.getConstantPool()); > //........INSTRUMMENTING CLASSFILE > //instrMet(cg, cp, jc); > instrMet(); > //........FINISHING AND SAVING NEW CLASSFILE > JavaClass jc1 = cg.getJavaClass(); > jc1.setConstantPool(cp.getFinalConstantPool()); > jc1.dump(pathOut + classFile); //PODE DAR ERRO (MESMO > CLASSFILE DA ABERTURA) > System.out.println(classFile + " instrumented!"); > }catch (IOException o){ > System.out.println("Erro I/O lendo: " + classFile); > } > } > > public static void instrMet() { > Method[] methods = jc.getMethods(); > for(int i=0; i < methods.length; i++) { > method = cg.containsMethod(methods[i].getName(), > methods[i].getSignature()); > System.out.println("metName: " + method.getName()); > mg = new MethodGen(method, jc.getClassName(), cp); > if (method.getName().equals("<init>")){ > //instrInstr(true); > continue; > }else{ > instrInstr(false); > } > //instrInstr(mg, cg); > } > } > > public static void instrInstr(boolean isConstructor) { > InstructionList il = mg.getInstructionList(); > InstructionHandle[] ihs = il.getInstructionHandles(); > for(int i=0; i < ihs.length; i++) { > InstructionHandle ih = ihs[i]; > Instruction instr = ih.getInstruction(); > InstructionFactory f = new InstructionFactory(cg, cp); > if (isConstructor){ > if (i >= 2){ > il.insert(instr, f.createPrintln("instrName: " + > instr.getName() + " Opcode: " + instr.getOpcode())); > > }else{ > il.append(f.createPrintln("instrName: " + > instr.getName() + " Opcode: " + instr.getOpcode())); > } > }else{ > il.insert(instr, f.createPrintln("instrName: " + > instr.getName() + " Opcode: " + instr.getOpcode())); > //il.append(f.createPrintln("Inseriu instrução!!!")); > } > System.out.println("instrName: " + instr.getName() + " > Opcode: " + instr.getOpcode()); > } > mg.setInstructionList(il); > // mg. > cg.removeMethod(method); > cg.addMethod(mg.getMethod()); > } > > > > > > > > > > > } > > > > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > >