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]
>
>
>

Reply via email to