package janala.instrument;
import janala.config.Config;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
public class SnoopInstructionTransformer implements ClassFileTransformer {
private boolean writeInstrumentedClasses = true;
private String instDir = "instrumented";
public SnoopInstructionTransformer() {
writeInstrumentedClasses = true;
instDir = "instrumented";
}
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new SnoopInstructionTransformer());
}
/** packages that should be exluded from the instrumentation */
private static boolean shouldExclude(String cname) {
String[] exclude = {"com/sun", "sun", "java", "jdk", "com/google/monitoring",
"janala", "dk/brics"};
for (String e : exclude) {
if (cname.startsWith(e)) {
return true;
}
}
return false;
}
@Override
public byte[] transform(ClassLoader loader, String cname, Class<?> classBeingRedefined,
ProtectionDomain d, byte[] cbuf)
throws IllegalClassFormatException {
if (classBeingRedefined != null) {
return cbuf;
}
boolean toInstrument = !shouldExclude(cname);
if (toInstrument) {
Coverage.read(Config.instance.coverage);
GlobalStateForInstrumentation.instance.setCid(Coverage.instance.getCid(cname));
ClassReader cr = new ClassReader(cbuf);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new SnoopInstructionClassAdapter(cw);
try {
cr.accept(cv, 0);
} catch (Exception e) {
e.printStackTrace();
}
byte[] ret = cw.toByteArray();
if (writeInstrumentedClasses) {
try {
File file = new File(instDir + "/" + cname + ".class");
File parent = new File(file.getParent());
parent.mkdirs();
FileOutputStream out = new FileOutputStream(file);
out.write(ret);
out.close();
} catch(Exception e) {
e.printStackTrace();
}
}
return ret;
} else {
return cbuf;
}
}
}