package Sequenic.T2ext.Instrumenter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.util.TraceClassVisitor; /** * A Class Instrumenter using ASM. * * The existing insturmenter: * -Did not instrument constructors and static initializers. * -Was very cluttered, requiring ugly hacks to add functionality necessary to generate labeled CFGs * -Required the instrumentee Class to be in the Classpath, * which caused conflicts when multiple versions of the same class needed instrumentation. * -Generated very long redundant paths for loops (see Examples.ExponentialLoop). * -Could not handle exceptional flow. * * Most of these could be fixed without resorting to the ASM library, * but BCEL is slow, not maintained and old, while ASM is newer, faster and being maintained. * And regarding exceptional flow, it seems as if BCEL does not expose enough information to handle it properly. * * Perhaps it is better and easier to just rewrite the Instrumenter using ASM than to hack the old Instrumenter. * * NOTE: this class is just a proposal. * * @author Jeiel Schalkwijk * */ public class ClassIntrumenter_ASM { private final int flags; public ClassIntrumenter_ASM(int flags) { this.flags = flags; } /** same as instrumenter(0). * * @return */ public static ClassIntrumenter_ASM instrumenter() { return new ClassIntrumenter_ASM(0); } public static ClassIntrumenter_ASM instrumenter(int flags) { return new ClassIntrumenter_ASM(flags); } /** If the filename is not yet instrumented, it will be instrumented. * If instrumented two additional files are created with the following extension: * .orgclass = the original (uninstrumented) version of the file, created by renaming the original file. * .cfgs = A CFGBunchFile containing the CFGs of the methods in the class. * * @param filename - name of the .class file * @return true if filename was not yet instrumented * @throws IOException * @throws FileNotFoundException */ public boolean instrument(String filename) throws FileNotFoundException, IOException { FileInputStream f = new FileInputStream(filename); ClassReader cr = new ClassReader(f); ClassWriter cw = new ClassWriter(cr,0); //flags: ClassWriter.COMPUTE_FRAMES + ClassWriter.COMPUTE_MAXS // ClassVisitor cv = new Injector(cw,Granularity.CLASS); TraceClassVisitor cv = new TraceClassVisitor(cw,new PrintWriter(System.out)); //print visitor. cr.accept(cv, 0);// flags: SKIP_FRAMES, SKIP_DEBUG, SKIP_CODE, EXPAND_FRAMES // byte[] instrumentedVersion = cw.toByteArray(); f.close(); return false; } public static void main(String[] args) { try { //Yes, classinv is also instrumented and CFGized // CFGBunchFile orig = CFGBunchFile.load("MyArrayList_mutated_versions/v0/java_1_4/util/MyArrayList.cfgs"); // for(CFG c : orig.cfgs) // System.out.println(c.methodName); //Print (un)instrumented class files: //instrumenter().instrument(new File("MyArrayList_mutated_versions/v0/java_1_4/util/MyArrayList.orgclass").getAbsolutePath()); //instrumenter().instrument("MyArrayList_mutated_versions/v0/java_1_4/util/MyArrayList.class"); }catch (Exception e) { e.printStackTrace(); } } }