To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit 9bd94326 authored by john's avatar john
Browse files

changed the generation of the instrument change to be automatic

parent 978e993e
package org.dacapo.instrument;
import java.util.LinkedList;
import java.util.Vector;
public final class Agent {
public static boolean firstReportSinceForceGC = false;
......@@ -13,13 +10,10 @@ public final class Agent {
private static long agentIntervalTime = 0; // the number of milliseconds the
// agent should act on
private static boolean callChainEnable = false;
private static Object waiter = new Object();
private static AgentThread agentThread = null;
private static ThreadLocal<DelayAllocReport> delayAllocReport = new ThreadLocal<DelayAllocReport>();
// private static final String LOG_PREFIX_CLASS_INITIALIZATION = "CI";
private static class AgentThread extends Thread {
boolean agentThreadStarted = false;
boolean logon = false;
......@@ -88,7 +82,7 @@ public final class Agent {
// wait what ever time required
if (sleepTime > 0)
try {
this.sleep(sleepTime);
Thread.sleep(sleepTime);
} catch (Exception e) {
}
}
......@@ -362,11 +356,11 @@ public final class Agent {
delayAllocReport.get().putfield(after, obj, before);
}
@SuppressWarnings("unchecked")
public static void logStaticPointerChange(Object after, Class klass,
Object before) {
if (delayAllocReport.get() == null)
delayAllocReport.set(new DelayAllocReport());
// delayAllocReport.get().putfield(after, obj, before);
internalLogStaticPointerChange(Thread.currentThread(), after, klass,
before);
}
......@@ -448,8 +442,8 @@ public final class Agent {
private static native void internalStop();
private static native void internalAllocReport(Thread thread, Object obj,
Class klass);
@SuppressWarnings("unchecked")
private static native void internalAllocReport(Thread thread, Object obj, Class klass);
private static synchronized void reportHeapAfterForceGCSync() {
if (firstReportSinceForceGC) {
......
......@@ -4,14 +4,23 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import org.dacapo.instrument.instrumenters.AllocateInstrument;
import org.dacapo.instrument.instrumenters.CallChainInstrument;
import org.dacapo.instrument.instrumenters.ClinitInstrument;
import org.dacapo.instrument.instrumenters.Instrumenter;
import org.dacapo.instrument.instrumenters.InstrumenterFactory;
import org.dacapo.instrument.instrumenters.LogInstrument;
import org.dacapo.instrument.instrumenters.MethodInstrument;
import org.dacapo.instrument.instrumenters.MonitorInstrument;
......@@ -41,7 +50,6 @@ public class Instrument extends Instrumenter {
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
if (args.length < 4) System.exit(1);
String infile = args[0];
......@@ -82,28 +90,30 @@ public class Instrument extends Instrumenter {
Properties state = new Properties();
readProperties(state, new File(agentDir, STATE_FILE_NAME));
// always change the version of the class to allow SomeClass.class constants
cv = VersionChanger.make(cv, methodToLargestLocal, options, state);
// Unable to
// cv = new SystemInstrument(cv, methodToLargestLocal);
cv = RuntimeInstrument.make(cv, methodToLargestLocal, options, state);
cv = MonitorInstrument.make(cv, methodToLargestLocal, options, state);
cv = ClinitInstrument.make(cv, methodToLargestLocal, options, state);
cv = AllocateInstrument.make(cv, methodToLargestLocal, options, state);
cv = CallChainInstrument.make(cv, methodToLargestLocal, options, state);
// The MethodInstrument is left out as there are a number of issues with
// instrumenting the bootclasses that I have not been able to resolve.
//
cv = MethodInstrument.make(cv, methodToLargestLocal, options, state);
cv = LogInstrument.make(cv, methodToLargestLocal, options, state);
cv = InstrumenterFactory.makeTransformChain(cv, methodToLargestLocal, options, state);
// // always change the version of the class to allow SomeClass.class constants
// cv = VersionChanger.make(cv, methodToLargestLocal, options, state);
//
// // Unable to
// // cv = new SystemInstrument(cv, methodToLargestLocal);
//
// cv = RuntimeInstrument.make(cv, methodToLargestLocal, options, state);
//
// cv = MonitorInstrument.make(cv, methodToLargestLocal, options, state);
//
// cv = ClinitInstrument.make(cv, methodToLargestLocal, options, state);
//
// cv = AllocateInstrument.make(cv, methodToLargestLocal, options, state);
//
// cv = CallChainInstrument.make(cv, methodToLargestLocal, options, state);
//
// // The MethodInstrument is left out as there are a number of issues with
// // instrumenting the bootclasses that I have not been able to resolve.
// //
// cv = MethodInstrument.make(cv, methodToLargestLocal, options, state);
//
// cv = LogInstrument.make(cv, methodToLargestLocal, options, state);
reader.accept(cv,ClassReader.EXPAND_FRAMES);
......@@ -232,5 +242,4 @@ public class Instrument extends Instrumenter {
return false;
}
}
}
......@@ -5,9 +5,6 @@ import java.util.Properties;
import java.util.TreeMap;
import java.util.TreeSet;
import org.dacapo.instrument.Agent;
import org.dacapo.instrument.Instrument;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
......@@ -18,11 +15,12 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.commons.AdviceAdapter;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.LocalVariablesSorter;
import org.objectweb.asm.commons.Method;
public class AllocateInstrument extends Instrumenter {
public static final Class[] DEPENDENCIES = new Class[] { ClinitInstrument.class };
// we need to instrument a call to alloc in the constructor, after the super
// class init but before the other code. This should call the reportAlloc
// if the type of this class is the same as the class containing the
......@@ -51,17 +49,17 @@ public class AllocateInstrument extends Instrumenter {
private static final String LOG_POINTER_CHANGE = "logPointerChange";
private static final String LOG_STATIC_POINTER_CHANGE = "logStaticPointerChange";
private static final String LOG_INTERNAL_ALLOC_INC = INTERNAL_PREFIX
private static final String LOG_INTERNAL_ALLOC_INC = INTERNAL_LOG_PREFIX
+ LOG_ALLOC_INC;
private static final String LOG_INTERNAL_ALLOC_DEC = INTERNAL_PREFIX
private static final String LOG_INTERNAL_ALLOC_DEC = INTERNAL_LOG_PREFIX
+ LOG_ALLOC_DEC;
private static final String LOG_INTERNAL_ALLOC_DONE = INTERNAL_PREFIX
private static final String LOG_INTERNAL_ALLOC_DONE = INTERNAL_LOG_PREFIX
+ LOG_ALLOC_DONE;
private static final String LOG_INTERNAL_ALLOC_REPORT = INTERNAL_PREFIX
private static final String LOG_INTERNAL_ALLOC_REPORT = INTERNAL_LOG_PREFIX
+ LOG_ALLOC_REPORT;
private static final String LOG_INTERNAL_POINTER_CHANGE = INTERNAL_PREFIX
private static final String LOG_INTERNAL_POINTER_CHANGE = INTERNAL_LOG_PREFIX
+ LOG_POINTER_CHANGE;
private static final String LOG_INTERNAL_STATIC_POINTER_CHANGE = INTERNAL_PREFIX
private static final String LOG_INTERNAL_STATIC_POINTER_CHANGE = INTERNAL_LOG_PREFIX
+ LOG_STATIC_POINTER_CHANGE;
private static final String VOID_SIGNATURE = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]); // "()V";
......@@ -156,7 +154,7 @@ public class AllocateInstrument extends Instrumenter {
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
if (!done && instrument() && instrument(access)) {
if (!done && instrument() && !isGenerated(name) && instrument(access)) {
// CountLocals locals = new CountLocals(access,
// super.visitMethod(access,name,desc,signature,exceptions));
// int nextLocal = 0; // locals.getMaxLocals()+1;
......
package org.dacapo.instrument.instrumenters;
import org.dacapo.instrument.Agent;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
......@@ -15,10 +12,11 @@ import org.objectweb.asm.commons.Method;
import java.util.Properties;
import java.util.TreeMap;
import java.util.Set;
public class CallChainInstrument extends Instrumenter {
public static final Class[] DEPENDENCIES = new Class[] { AllocateInstrument.class };
public static final String CALL_CHAIN = "call_chain";
private static final String LOG_METHOD_NAME = "logCallChain";
......@@ -27,7 +25,6 @@ public class CallChainInstrument extends Instrumenter {
private static final String LOG_INTERNAL_METHOD = "$$" + LOG_METHOD_NAME;
private int access = 0;
private ClassVisitor cv = null;
private String className = null;
private boolean done = false;
private boolean found = false;
......@@ -42,7 +39,6 @@ public class CallChainInstrument extends Instrumenter {
protected CallChainInstrument(ClassVisitor cv, TreeMap<String,Integer> methodToLargestLocal,
Properties options, Properties state) {
super(cv, methodToLargestLocal, options, state);
this.cv = cv;
}
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
......@@ -52,13 +48,14 @@ public class CallChainInstrument extends Instrumenter {
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (!done && instrument() && instrument(name,access)) {
if (!done && instrument() && !isGenerated(name) && instrument(name,access)) {
return new CallChainInstrumentMethod(access, name, desc, signature, exceptions, super.visitMethod(access,name,desc,signature,exceptions));
} else {
return super.visitMethod(access,name,desc,signature,exceptions);
}
}
@SuppressWarnings("unchecked")
public void visitEnd() {
if (!done && found) {
done = true;
......
......@@ -4,11 +4,8 @@ import java.util.LinkedList;
import java.util.Properties;
import java.util.TreeMap;
import org.dacapo.instrument.Agent;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
......@@ -19,20 +16,18 @@ import org.objectweb.asm.commons.Method;
public class ClinitInstrument extends Instrumenter {
public static final Class[] DEPENDENCIES = new Class[] { MonitorInstrument.class };
public static final String CLASSES_INITIALIZATION = "clinit";
private static final int CLINIT_ACCESS = Opcodes.ACC_STATIC;
private static final String CLINIT_NAME = "<clinit>";
private static final String CLINIT_DESCRIPTION = null;
private static final String CLINIT_SIGNATURE = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]);
private static final String[] CLINIT_EXCEPTIONS = { };
private static final String LOG_METHOD_NAME = "reportClass";
private static final String LOG_METHOD_SIGNATURE = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { JAVA_LANG_STRING_TYPE });
private boolean foundClinit = false;
private int access = 0;
private ClassVisitor cv = null;
private String className = null;
private LinkedList<String> excludePackages = new LinkedList<String>();
......@@ -47,7 +42,6 @@ public class ClinitInstrument extends Instrumenter {
protected ClinitInstrument(ClassVisitor cv, TreeMap<String,Integer> methodToLargestLocal,
Properties options, Properties state, String excludeList) {
super(cv, methodToLargestLocal, options, state);
this.cv = cv;
excludePackages.add(INSTRUMENT_PACKAGE);
if (excludeList!=null) {
......@@ -75,6 +69,7 @@ public class ClinitInstrument extends Instrumenter {
}
}
@SuppressWarnings("unchecked")
public void visitEnd() {
if (!foundClinit && instrument()) {
// didn't find <clinit> so lets make one
......
package org.dacapo.instrument.instrumenters;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.LinkedList;
import java.util.Properties;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.JarInputStream;
import java.util.jar.JarEntry;
import org.dacapo.instrument.Agent;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.AdviceAdapter;
public class Instrumenter extends ClassAdapter {
public static final String INSTRUMENT_PACKAGE = "org/dacapo/instrument/";
......@@ -27,6 +30,7 @@ public class Instrumenter extends ClassAdapter {
@SuppressWarnings("unchecked")
public static final Class LOG_INTERNAL_CLASS = Agent.class;
public static final Class INSTRUMENTER_CLASS = Instrumenter.class;
public static final Type JAVA_LANG_OBJECT_TYPE = Type.getType(Object.class);
public static final Type JAVA_LANG_CLASS_TYPE = Type.getType(Class.class);
......@@ -42,8 +46,16 @@ public class Instrumenter extends ClassAdapter {
public static final String JAVA_LANG_THROWABLE = JAVA_LANG_THROWABLE_TYPE.getInternalName();
public static final String LOG_INTERNAL = LOG_INTERNAL_TYPE.getInternalName();
public static final String INTERNAL_PREFIX = "$$";
public static final String INTERNAL_LOG_PREFIX = "$$";
public static final String INTERNAL_FIELD_PREFIX = "$$F$";
public static final String INTERNAL_METHOD_PREFIX = "$$M$";
public static final String INSTRUMENTER = INSTRUMENTER_CLASS.getName().replace('.','/');
public static final String INSTRUMENTER_PACKAGE = INSTRUMENTER_CLASS.getPackage().getName().replace('.', '/');
public static final String INSTRUMENTER_BASE = INSTRUMENTER.substring(INSTRUMENTER_PACKAGE.length() + 1);
public static final String CLASS_SUFFIX = ".class";
protected TreeMap<String,Integer> methodToLargestLocal;
protected Properties options = null;
protected Properties state = null;
......@@ -67,6 +79,7 @@ public class Instrumenter extends ClassAdapter {
}
protected static boolean isGenerated(String method) {
return method.startsWith(INTERNAL_PREFIX);
return method.startsWith(INTERNAL_LOG_PREFIX);
}
}
\ No newline at end of file
}
package org.dacapo.instrument.instrumenters;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import org.objectweb.asm.ClassVisitor;
public final class InstrumenterFactory {
public static String FRAMEWORK = "yo";
private static final String DEPENDENCIES_FIELD = "DEPENDENCIES";
private static final String MAKE_TRANSFORM = "make";
private static LinkedList<Method> orderedTransforms = new LinkedList<Method>();
static {
initFramework();
}
public static ClassVisitor makeTransformChain(ClassVisitor cv, TreeMap<String,Integer> methodToLargestLocal, Properties options, Properties state) {
try {
for(Method functor: orderedTransforms) {
cv = (ClassVisitor)(functor.invoke(null, cv, methodToLargestLocal, options, state));
}
return cv;
} catch (Throwable t) {
t.printStackTrace();
return null;
}
}
private static void initFramework() {
TreeSet<String> classNameSet = getInstrumenters();
TreeMap<String, Class> nameToClass = new TreeMap<String, Class>();
TreeMap<String, TreeSet<String>> graph = new TreeMap<String, TreeSet<String>>();
TreeMap<String, Method> functors = new TreeMap<String, Method>();
LinkedList<String> instrumenters = new LinkedList<String>();
if (classNameSet != null) {
for(String klassName: classNameSet) {
try {
Class klass = Instrumenter.class.getClassLoader().loadClass(klassName);
Method method = klass.getDeclaredMethod(MAKE_TRANSFORM, ClassVisitor.class, TreeMap.class, Properties.class, Properties.class);
Field field = klass.getDeclaredField(DEPENDENCIES_FIELD);
functors.put(klassName, method);
Class[] fromList = (Class[])(klass.getField(DEPENDENCIES_FIELD).get(null));
if (! graph.containsKey(klassName)) {
graph.put(klassName, new TreeSet<String>());
}
for(Class from: fromList) {
graph.get(klassName).add(from.getName());
}
} catch (Throwable t) {
// this is a non-compliant so we do not include it in the transform chain
}
}
}
while (! graph.isEmpty()) {
LinkedList<String> noDependencies = new LinkedList<String>();
for(String klass: graph.keySet()) {
if (graph.get(klass).isEmpty()) {
noDependencies.add(klass);
}
}
for(String klass: noDependencies) {
graph.remove(klass);
}
if (noDependencies.isEmpty()) {
System.err.println("Circular dependencies on transform sets:");
for(String klass: graph.keySet()) {
boolean first = true;
System.err.print(klass+" <- ");
for(String from: graph.get(klass)) {
if (first) first = false;
else {
System.err.print(", ");
}
System.err.print(from);
System.err.println();
}
}
System.exit(10);
}
for(String klass: noDependencies) {
for(String target: graph.keySet())
graph.get(target).remove(klass);
}
instrumenters.addAll(noDependencies);
}
for(String klass: instrumenters) {
orderedTransforms.addLast(functors.get(klass));
}
}
private static TreeSet<String> getInstrumenters() {
ClassLoader cl = Instrumenter.INSTRUMENTER_CLASS.getClassLoader();
try {
URL u = cl.getResource(Instrumenter.INSTRUMENTER_PACKAGE);
if (u != null) {
if ("file".equals(u.getProtocol())) {
return getSetFromFileSystem(new File(u.getPath()));
} else if ("jar".equals(u.getProtocol())) {
return getSetFromJar(new URL(u.getPath()));
}
}
} catch (Throwable t) { }
return null;
}
private static TreeSet<String> getSetFromFileSystem(File dir) {
TreeSet<String> instrumenters = new TreeSet<String>();
if (dir.isDirectory()) {
for(File f: dir.listFiles()) {
String name = f.getName();
if (f.isFile() &&
name.indexOf('$')==-1 &&
name.toLowerCase().endsWith(Instrumenter.CLASS_SUFFIX)) {
name = (Instrumenter.INSTRUMENTER_PACKAGE + "/" + name.substring(0,name.length()-Instrumenter.CLASS_SUFFIX.length())).replace('/','.');
instrumenters.add(name);
}
}
}
return instrumenters;
}
private static TreeSet<String> getSetFromJar(URL url) {
TreeSet<String> instrumenters = new TreeSet<String>();
try {
if (url.toExternalForm().indexOf('!')!=-1) {
url = new URL(url.toExternalForm().substring(0,url.toExternalForm().indexOf('!')));
}
InputStream is = url.openStream();
if (is != null) {
try {
JarInputStream jis = new JarInputStream(is);
JarEntry entry;
while ((entry = jis.getNextJarEntry()) != null) {
String name = entry.getName();
if (!entry.isDirectory() &&
name.startsWith(Instrumenter.INSTRUMENTER_PACKAGE) &&
name.indexOf('$')==-1 &&
name.endsWith(Instrumenter.CLASS_SUFFIX)) {
name = name.substring(0,name.length()-Instrumenter.CLASS_SUFFIX.length()).replace('/', '.');
instrumenters.add(name);
}
}
} finally {
is.close();
}
}
} catch (Throwable t) {
}
return instrumenters;
}
}
......@@ -3,10 +3,8 @@ package org.dacapo.instrument.instrumenters;
import java.util.Properties;
import java.util.TreeMap;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
......@@ -15,10 +13,10 @@ import org.objectweb.asm.commons.AdviceAdapter;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;