Commit 35d34d35 authored by Lukáš Marek's avatar Lukáš Marek

Added custom transformer support

parent 7a3b1658
......@@ -19,14 +19,18 @@ import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.cbloader.ClassByteLoader;
import ch.usi.dag.disl.cbloader.ManifestHelper;
import ch.usi.dag.disl.cbloader.ManifestHelper.ManifestInfo;
import ch.usi.dag.disl.classparser.ClassParser;
import ch.usi.dag.disl.exception.DiSLException;
import ch.usi.dag.disl.exception.DiSLIOException;
import ch.usi.dag.disl.exception.DynamicInfoException;
import ch.usi.dag.disl.exception.InitException;
import ch.usi.dag.disl.exception.ManifestInfoException;
import ch.usi.dag.disl.exception.ProcessorException;
import ch.usi.dag.disl.exception.ReflectionException;
import ch.usi.dag.disl.exception.StaticContextGenException;
import ch.usi.dag.disl.exception.TransformerException;
import ch.usi.dag.disl.exclusion.ExclusionSet;
import ch.usi.dag.disl.guard.GuardHelper;
import ch.usi.dag.disl.localvar.SyntheticLocalVar;
......@@ -40,6 +44,7 @@ import ch.usi.dag.disl.scope.Scope;
import ch.usi.dag.disl.snippet.Shadow;
import ch.usi.dag.disl.snippet.Snippet;
import ch.usi.dag.disl.staticcontext.generator.SCGenerator;
import ch.usi.dag.disl.transformer.Transformer;
import ch.usi.dag.disl.util.Constants;
import ch.usi.dag.disl.utilinstr.codemerger.CodeMerger;
import ch.usi.dag.disl.utilinstr.tlvinserter.TLVInserter;
......@@ -62,6 +67,8 @@ public class DiSL {
Boolean.getBoolean(PROP_SPLIT_LONG_METHODS);
private final boolean useDynamicBypass;
private final Transformer transformer;
private final Set<Scope> exclusionSet;
......@@ -75,6 +82,13 @@ public class DiSL {
// report DiSL exception within our code
try {
// *** resolve transformer ***
transformer = resolveTransformer();
// *** prepare exclusion set ***
exclusionSet = ExclusionSet.prepare();
// *** load disl classes ***
List<InputStream> dislClasses = ClassByteLoader.loadDiSLClasses();
if(dislClasses == null) {
......@@ -84,9 +98,6 @@ public class DiSL {
+ " and proper manifest");
}
// prepare exclusion set
exclusionSet = ExclusionSet.prepare();
// *** parse disl classes ***
// - create snippets
// - create static context methods
......@@ -133,6 +144,44 @@ public class DiSL {
}
}
private Transformer resolveTransformer() throws ManifestInfoException,
ReflectionException {
ManifestInfo mi = ManifestHelper.getDiSLManifestInfo();
if(mi == null) {
return null;
}
String transformerClsName = mi.getDislTransformer();
if(transformerClsName == null) {
return null;
}
try {
Class<?> transformerCls = Class.forName(transformerClsName);
return (Transformer) transformerCls.newInstance();
}
catch (ClassNotFoundException e) {
throw new ReflectionException("DiSL transformer "
+ transformerClsName + " cannot be resolved", e);
}
catch (InstantiationException e) {
throw new ReflectionException("DiSL transformer "
+ transformerClsName + " cannot be instantiated", e);
}
catch (IllegalAccessException e) {
throw new ReflectionException("DiSL transformer "
+ transformerClsName + " cannot be instantiated", e);
}
catch (ClassCastException e) {
throw new ReflectionException("DiSL transformer "
+ transformerClsName
+ " does not implement Transformer interface", e);
}
}
private void reportError(DiSLException e) {
// error report for user (input) errors
......@@ -409,6 +458,16 @@ public class DiSL {
throw new DiSLIOException(e);
}
// apply transformer first
if(transformer != null) {
try {
classAsBytes = transformer.transform(classAsBytes);
}
catch (Exception e) {
throw new TransformerException("Transformer error", e);
}
}
// create class reader
ClassReader classReader = new ClassReader(classAsBytes);
......
......@@ -13,14 +13,17 @@ public class ManifestHelper {
private static final String MANIFEST = "META-INF/MANIFEST.MF";
public static final String ATTR_DISL_CLASSES = "DiSL-Classes";
public static final String ATTR_DISL_TRANSFORMER = "DiSL-Transformer";
public static class ManifestInfo {
private URL resource;
private Manifest manifest;
private String dislClasses;
private String dislTransformer;
public ManifestInfo(URL resource, Manifest manifest, String dislClasses) {
public ManifestInfo(URL resource, Manifest manifest, String dislClasses,
String dislTransformer) {
super();
this.resource = resource;
this.manifest = manifest;
......@@ -38,11 +41,32 @@ public class ManifestHelper {
public String getDislClasses() {
return dislClasses;
}
public String getDislTransformer() {
return dislTransformer;
}
}
private static ManifestInfo cachedMI = null;
private static boolean cacheValid = false;
// caching layer
public static ManifestInfo getDiSLManifestInfo()
throws ManifestInfoException {
// resolve manifest info
if(! cacheValid) {
cachedMI = resolveDiSLManifestInfo();
cacheValid = true;
}
// return manifest info
return cachedMI;
}
private static ManifestInfo resolveDiSLManifestInfo()
throws ManifestInfoException {
try {
ClassLoader cl = ManifestInfo.class.getClassLoader();
......@@ -63,9 +87,11 @@ public class ManifestHelper {
if(attrs != null) {
String dislClasses = attrs.getValue(ATTR_DISL_CLASSES);
String dislTrans = attrs.getValue(ATTR_DISL_TRANSFORMER);
if(dislClasses != null) {
return new ManifestInfo(resource, manifest, dislClasses);
return new ManifestInfo(resource, manifest,
dislClasses, dislTrans);
}
}
}
......
package ch.usi.dag.disl.exception;
public class TransformerException extends DiSLException {
private static final long serialVersionUID = 8899006117334791742L;
public TransformerException() {
}
public TransformerException(String message, Throwable cause) {
super(message, cause);
}
public TransformerException(String message) {
super(message);
}
public TransformerException(Throwable cause) {
super(cause);
}
}
package ch.usi.dag.disl.transformer;
public interface Transformer {
byte[] transform(byte[] classfileBuffer) throws Exception;
}
......@@ -98,11 +98,14 @@ public abstract class CodeMerger {
if(splitLongMethods) {
// return originally instrumented code back to the instrMN
origMN.instructions = splitCopy.getInstructions();
origMN.tryCatchBlocks = splitCopy.getTryCatchBlocks();
instrMN.instructions = splitCopy.getInstructions();
instrMN.tryCatchBlocks = splitCopy.getTryCatchBlocks();
// split methods
splitLongMethods(origMN, instrMN);
splitLongMethods(instrumentedCN, origMN, instrMN);
// next method
continue;
}
// insert original code into the instrumented method node
......@@ -123,11 +126,17 @@ public abstract class CodeMerger {
return instrumentedCN;
}
private static void splitLongMethods(MethodNode origMN, MethodNode instrMN) {
private static void splitLongMethods(ClassNode instrumentedCN,
MethodNode origMN, MethodNode instrMN) {
// TODO jb ! add splitting for to long methods
// - ignore clinit - output warning
// - output warning if splitted is to large and ignore
// check the code size of the instrumented method
// add if to the original method that jumps to the renamed instrumented method
// add original method to the instrumented code
// rename instrumented method
}
private static MethodNode getMethodNode(ClassNode cnToSearch,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment