further work on geberating stack maps
This commit is contained in:
parent
4e52c00a4b
commit
63232e4a02
|
@ -42,7 +42,7 @@ public class AddBytecodeDebug {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
for (int i = 0; i < 1; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
instrumenter = new OfflineInstrumenter();
|
instrumenter = new OfflineInstrumenter(true);
|
||||||
|
|
||||||
Writer w = new BufferedWriter(new FileWriter("report", false));
|
Writer w = new BufferedWriter(new FileWriter("report", false));
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@ public class Bench {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
for (int i = 0; i < 1; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
instrumenter = new OfflineInstrumenter();
|
|
||||||
|
|
||||||
Writer w = new BufferedWriter(new FileWriter("report", false));
|
Writer w = new BufferedWriter(new FileWriter("report", false));
|
||||||
|
|
||||||
|
@ -74,6 +73,7 @@ public class Bench {
|
||||||
doException = true;
|
doException = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
instrumenter = new OfflineInstrumenter(!doException);
|
||||||
instrumenter.setPassUnmodifiedClasses(true);
|
instrumenter.setPassUnmodifiedClasses(true);
|
||||||
instrumenter.beginTraversal();
|
instrumenter.beginTraversal();
|
||||||
ClassInstrumenter ci;
|
ClassInstrumenter ci;
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class InterfaceAnalyzer {
|
||||||
final static HashMap<String, TypeStats> typeStats = new HashMap<String, TypeStats>();
|
final static HashMap<String, TypeStats> typeStats = new HashMap<String, TypeStats>();
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
OfflineInstrumenter instrumenter = new OfflineInstrumenter();
|
OfflineInstrumenter instrumenter = new OfflineInstrumenter(true);
|
||||||
|
|
||||||
Writer w = new BufferedWriter(new OutputStreamWriter(System.out));
|
Writer w = new BufferedWriter(new OutputStreamWriter(System.out));
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class Mangler {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
for (int i = 0; i < 1; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
instrumenter = new OfflineInstrumenter();
|
instrumenter = new OfflineInstrumenter(true);
|
||||||
|
|
||||||
Writer w = new BufferedWriter(new FileWriter("report", false));
|
Writer w = new BufferedWriter(new FileWriter("report", false));
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class Statistics {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
for (int i = 0; i < 1; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
instrumenter = new OfflineInstrumenter();
|
instrumenter = new OfflineInstrumenter(true);
|
||||||
|
|
||||||
Writer w = new BufferedWriter(new FileWriter("report", false));
|
Writer w = new BufferedWriter(new FileWriter("report", false));
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ public class DynamicCallGraph {
|
||||||
private final static boolean disasm = true;
|
private final static boolean disasm = true;
|
||||||
private final static boolean verify = true;
|
private final static boolean verify = true;
|
||||||
|
|
||||||
|
private static boolean patchExits = true;
|
||||||
|
|
||||||
private static OfflineInstrumenter instrumenter;
|
private static OfflineInstrumenter instrumenter;
|
||||||
|
|
||||||
private static Class<?> runtime = Runtime.class;
|
private static Class<?> runtime = Runtime.class;
|
||||||
|
@ -72,24 +74,26 @@ public class DynamicCallGraph {
|
||||||
ClassInstrumenter ci;
|
ClassInstrumenter ci;
|
||||||
Writer w = new BufferedWriter(new FileWriter("report", false));
|
Writer w = new BufferedWriter(new FileWriter("report", false));
|
||||||
|
|
||||||
instrumenter = new OfflineInstrumenter();
|
for(int i = 0; i < args.length - 1; i++) {
|
||||||
args = instrumenter.parseStandardArgs(args);
|
if ("--runtime".equals(args[i])) {
|
||||||
|
runtime = Class.forName(args[i+1]);
|
||||||
for(int i = 0; i < args.length - 1; i++) {
|
} else if ("--exclusions".equals(args[i])) {
|
||||||
if ("--runtime".equals(args[i])) {
|
filter = new FileOfClasses(new FileInputStream(args[i+1]));
|
||||||
runtime = Class.forName(args[i+1]);
|
} else if ("--dont-patch-exits".equals(args[i])) {
|
||||||
} else if ("--exclusions".equals(args[i])) {
|
patchExits = false;
|
||||||
filter = new FileOfClasses(new FileInputStream(args[i+1]));
|
} else if ("--rt-jar".equals(args[i])) {
|
||||||
} else if ("--rt-jar".equals(args[i])) {
|
System.err.println("using " + args[i+1] + " as stdlib");
|
||||||
System.err.println("using " + args[i+1] + " as stdlib");
|
OfflineInstrumenter libReader = new OfflineInstrumenter(true);
|
||||||
OfflineInstrumenter libReader = new OfflineInstrumenter();
|
libReader.addInputJar(new File(args[i+1]));
|
||||||
libReader.addInputJar(new File(args[i+1]));
|
while ((ci = libReader.nextClass()) != null) {
|
||||||
while ((ci = libReader.nextClass()) != null) {
|
CTUtils.addClassToHierarchy(cha, ci.getReader());
|
||||||
CTUtils.addClassToHierarchy(cha, ci.getReader());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
instrumenter = new OfflineInstrumenter(!patchExits);
|
||||||
|
args = instrumenter.parseStandardArgs(args);
|
||||||
|
|
||||||
instrumenter.setPassUnmodifiedClasses(true);
|
instrumenter.setPassUnmodifiedClasses(true);
|
||||||
|
|
||||||
instrumenter.beginTraversal();
|
instrumenter.beginTraversal();
|
||||||
|
@ -137,7 +141,7 @@ public class DynamicCallGraph {
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
Verifier v = new Verifier(d);
|
Verifier v = new Verifier(d);
|
||||||
v.setClassHierarchy(cha);
|
// v.setClassHierarchy(cha);
|
||||||
v.verify();
|
v.verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,42 +167,44 @@ public class DynamicCallGraph {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
me.addMethodExceptionHandler(null, new MethodEditor.Patch() {
|
if (patchExits) {
|
||||||
@Override
|
me.addMethodExceptionHandler(null, new MethodEditor.Patch() {
|
||||||
public void emitTo(Output w) {
|
@Override
|
||||||
w.emit(ConstantInstruction.makeString(theClass));
|
public void emitTo(Output w) {
|
||||||
w.emit(ConstantInstruction.makeString(theMethod));
|
w.emit(ConstantInstruction.makeString(theClass));
|
||||||
//if (nonStatic)
|
w.emit(ConstantInstruction.makeString(theMethod));
|
||||||
// w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this
|
//if (nonStatic)
|
||||||
//else
|
// w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this
|
||||||
w.emit(Util.makeGet(runtime, "NULL_TAG"));
|
//else
|
||||||
// w.emit(ConstantInstruction.make(Constants.TYPE_null, null));
|
w.emit(Util.makeGet(runtime, "NULL_TAG"));
|
||||||
w.emit(ConstantInstruction.make(1)); // true
|
// w.emit(ConstantInstruction.make(Constants.TYPE_null, null));
|
||||||
w.emit(Util.makeInvoke(runtime, "termination", new Class[] {String.class, String.class, Object.class, boolean.class}));
|
w.emit(ConstantInstruction.make(1)); // true
|
||||||
w.emit(ThrowInstruction.make(false));
|
w.emit(Util.makeInvoke(runtime, "termination", new Class[] {String.class, String.class, Object.class, boolean.class}));
|
||||||
}
|
w.emit(ThrowInstruction.make(false));
|
||||||
});
|
}
|
||||||
|
});
|
||||||
me.visitInstructions(new MethodEditor.Visitor() {
|
|
||||||
@Override
|
me.visitInstructions(new MethodEditor.Visitor() {
|
||||||
public void visitReturn(ReturnInstruction instruction) {
|
@Override
|
||||||
insertBefore(new MethodEditor.Patch() {
|
public void visitReturn(ReturnInstruction instruction) {
|
||||||
@Override
|
insertBefore(new MethodEditor.Patch() {
|
||||||
public void emitTo(MethodEditor.Output w) {
|
@Override
|
||||||
w.emit(ConstantInstruction.makeString(theClass));
|
public void emitTo(MethodEditor.Output w) {
|
||||||
w.emit(ConstantInstruction.makeString(theMethod));
|
w.emit(ConstantInstruction.makeString(theClass));
|
||||||
if (nonStatic)
|
w.emit(ConstantInstruction.makeString(theMethod));
|
||||||
w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this
|
if (nonStatic)
|
||||||
else
|
w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this
|
||||||
w.emit(Util.makeGet(runtime, "NULL_TAG"));
|
else
|
||||||
// w.emit(ConstantInstruction.make(Constants.TYPE, null));
|
w.emit(Util.makeGet(runtime, "NULL_TAG"));
|
||||||
w.emit(ConstantInstruction.make(0)); // false
|
// w.emit(ConstantInstruction.make(Constants.TYPE, null));
|
||||||
w.emit(Util.makeInvoke(runtime, "termination", new Class[] {String.class, String.class, Object.class, boolean.class}));
|
w.emit(ConstantInstruction.make(0)); // false
|
||||||
}
|
w.emit(Util.makeInvoke(runtime, "termination", new Class[] {String.class, String.class, Object.class, boolean.class}));
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// this updates the data d
|
// this updates the data d
|
||||||
me.applyPatches();
|
me.applyPatches();
|
||||||
|
|
||||||
|
@ -210,7 +216,7 @@ public class DynamicCallGraph {
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
Verifier v = new Verifier(d);
|
Verifier v = new Verifier(d);
|
||||||
v.setClassHierarchy(cha);
|
// v.setClassHierarchy(cha);
|
||||||
v.verify();
|
v.verify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class CopyWriter {
|
||||||
|
|
||||||
final ArrayList<ZipEntry> entries = new ArrayList<ZipEntry>();
|
final ArrayList<ZipEntry> entries = new ArrayList<ZipEntry>();
|
||||||
|
|
||||||
instrumenter = new OfflineInstrumenter();
|
instrumenter = new OfflineInstrumenter(true);
|
||||||
instrumenter.setManifestBuilder(new OfflineInstrumenter.ManifestBuilder() {
|
instrumenter.setManifestBuilder(new OfflineInstrumenter.ManifestBuilder() {
|
||||||
@Override
|
@Override
|
||||||
public void addEntry(ZipEntry ze) {
|
public void addEntry(ZipEntry ze) {
|
||||||
|
|
|
@ -1681,7 +1681,7 @@ public abstract class Compiler implements Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeTypes() {
|
private void makeTypes() {
|
||||||
Verifier v = new Verifier(isConstructor, isStatic, classType, signature, instructions, handlers, instructionsToBytecodes);
|
Verifier v = new Verifier(isConstructor, isStatic, classType, signature, instructions, handlers, instructionsToBytecodes, null);
|
||||||
if (hierarchy != null) {
|
if (hierarchy != null) {
|
||||||
v.setClassHierarchy(hierarchy);
|
v.setClassHierarchy(hierarchy);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ package com.ibm.wala.shrikeBT.analysis;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -71,12 +72,14 @@ public class Analyzer {
|
||||||
protected int[][] backEdges;
|
protected int[][] backEdges;
|
||||||
|
|
||||||
protected int[] instToBC;
|
protected int[] instToBC;
|
||||||
|
|
||||||
|
protected String[][] varTypes;
|
||||||
|
|
||||||
protected final static String[] noStrings = new String[0];
|
protected final static String[] noStrings = new String[0];
|
||||||
|
|
||||||
protected final static int[] noEdges = new int[0];
|
protected final static int[] noEdges = new int[0];
|
||||||
|
|
||||||
public Analyzer(boolean isConstructor, boolean isStatic, String classType, String signature, IInstruction[] instructions, ExceptionHandler[][] handlers, int[] instToBC) {
|
public Analyzer(boolean isConstructor, boolean isStatic, String classType, String signature, IInstruction[] instructions, ExceptionHandler[][] handlers, int[] instToBC, String[][] vars) {
|
||||||
if (instructions == null) {
|
if (instructions == null) {
|
||||||
throw new IllegalArgumentException("null instructions");
|
throw new IllegalArgumentException("null instructions");
|
||||||
}
|
}
|
||||||
|
@ -95,6 +98,7 @@ public class Analyzer {
|
||||||
this.instructions = instructions;
|
this.instructions = instructions;
|
||||||
this.handlers = handlers;
|
this.handlers = handlers;
|
||||||
this.instToBC = instToBC;
|
this.instToBC = instToBC;
|
||||||
|
this.varTypes = vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,6 +207,15 @@ public class Analyzer {
|
||||||
return t1;
|
return t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (String.valueOf(t1).equals("L;") || String.valueOf(t2).equals("L;")) {
|
||||||
|
System.err.println("++ " + t1 + " -- " + t2 + " ++");
|
||||||
|
if (String.valueOf(t1).equals("L;")) {
|
||||||
|
return t2;
|
||||||
|
} else {
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (t1 == thisType || t2 == thisType || t1 == topType || t2 == topType) {
|
if (t1 == thisType || t2 == thisType || t1 == topType || t2 == topType) {
|
||||||
return topType;
|
return topType;
|
||||||
}
|
}
|
||||||
|
@ -213,7 +226,7 @@ public class Analyzer {
|
||||||
|
|
||||||
String x = ClassHierarchy.findCommonSupertype(hierarchy, patchType(t1), patchType(t2));
|
String x = ClassHierarchy.findCommonSupertype(hierarchy, patchType(t1), patchType(t2));
|
||||||
|
|
||||||
if ("L?;".equals(x) && ("J".equals(t1) || "J".equals(t2))) {
|
if ("L?;".equals(x)) {
|
||||||
System.err.println(t1 + " -- " + t2);
|
System.err.println(t1 + " -- " + t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -694,6 +707,28 @@ public class Analyzer {
|
||||||
instr.visit(localsUpdate); // visit localStore before popping
|
instr.visit(localsUpdate); // visit localStore before popping
|
||||||
System.arraycopy(curStack, popped, curStack, 0, curStackSize - popped);
|
System.arraycopy(curStack, popped, curStack, 0, curStackSize - popped);
|
||||||
curStackSize -= popped;
|
curStackSize -= popped;
|
||||||
|
|
||||||
|
if (varTypes != null) {
|
||||||
|
if (instr instanceof IStoreInstruction) {
|
||||||
|
int local = ((IStoreInstruction)instr).getVarIndex();
|
||||||
|
if (Constants.TYPE_null.equals(curLocals[local])) {
|
||||||
|
for(int idx : new int[]{i, i+1}) {
|
||||||
|
int bc = instToBC[idx];
|
||||||
|
if (bc == 667 && local == 16) {
|
||||||
|
System.err.println("got here");
|
||||||
|
}
|
||||||
|
if (bc != -1 && varTypes != null && varTypes.length > bc && varTypes[bc] != null) {
|
||||||
|
if (varTypes[bc].length > local && varTypes[bc][local] != null) {
|
||||||
|
String declaredType = varTypes[bc][local];
|
||||||
|
curLocals[local] = declaredType;
|
||||||
|
|
||||||
|
System.err.println("setting local " + local + " to " + declaredType + " at " + instToBC[i] + " in " + classType + " " + signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,8 +745,13 @@ public class Analyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//System.err.println(i + " -- " + Arrays.toString(curLocals) + " -- " + Arrays.toString(curStack));
|
||||||
|
|
||||||
int[] targets = instr.getBranchTargets();
|
int[] targets = instr.getBranchTargets();
|
||||||
for (int j = 0; j < targets.length; j++) {
|
for (int j = 0; j < targets.length; j++) {
|
||||||
|
if (targets[j] == 29 && classType.contains("MetaClassImpl;") && signature.contains("(Ljava/lang/String;Lorg/codehaus/groovy/reflection/CachedClass;)")) {
|
||||||
|
System.err.println("got here");
|
||||||
|
}
|
||||||
if (mergeTypes(targets[j], curStack, curStackSize, curLocals, curLocalsSize[0], path)) {
|
if (mergeTypes(targets[j], curStack, curStackSize, curLocals, curLocalsSize[0], path)) {
|
||||||
computeTypes(targets[j], visitor, makeTypesAt, path);
|
computeTypes(targets[j], visitor, makeTypesAt, path);
|
||||||
}
|
}
|
||||||
|
@ -830,11 +870,11 @@ public class Analyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Analyzer(MethodData info) {
|
protected Analyzer(MethodData info) {
|
||||||
this(info.getName().equals("<init>"), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), info.getInstructionsToBytecodes());
|
this(info.getName().equals("<init>"), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), info.getInstructionsToBytecodes(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Analyzer(MethodData info, int[] instToBC) {
|
protected Analyzer(MethodData info, int[] instToBC, String[][] vars) {
|
||||||
this(info.getName().equals("<init>"), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), instToBC);
|
this(info.getName().equals("<init>"), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), instToBC, vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Analyzer createAnalyzer(MethodData info) {
|
public static Analyzer createAnalyzer(MethodData info) {
|
||||||
|
|
|
@ -277,6 +277,11 @@ public final class ClassHierarchy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String findCommonSupertypeHierarchy(ClassHierarchyProvider hierarchy, String t1, String t2) {
|
private static String findCommonSupertypeHierarchy(ClassHierarchyProvider hierarchy, String t1, String t2) {
|
||||||
|
|
||||||
|
if (hierarchy != null && t1.contains("Reader") && t2.contains("Reader")) {
|
||||||
|
System.err.println("got here");
|
||||||
|
}
|
||||||
|
|
||||||
if (isSubtypeOf(hierarchy, t1, t2) == YES) {
|
if (isSubtypeOf(hierarchy, t1, t2) == YES) {
|
||||||
return t2;
|
return t2;
|
||||||
} else if (isSubtypeOf(hierarchy, t2, t1) == YES) {
|
} else if (isSubtypeOf(hierarchy, t2, t1) == YES) {
|
||||||
|
|
|
@ -287,8 +287,8 @@ public final class Verifier extends Analyzer {
|
||||||
/**
|
/**
|
||||||
* Initialize a verifier.
|
* Initialize a verifier.
|
||||||
*/
|
*/
|
||||||
public Verifier(boolean isConstructor, boolean isStatic, String classType, String signature, IInstruction[] instructions, ExceptionHandler[][] handlers, int[] instToBC) {
|
public Verifier(boolean isConstructor, boolean isStatic, String classType, String signature, IInstruction[] instructions, ExceptionHandler[][] handlers, int[] instToBC, String[][] vars) {
|
||||||
super(isConstructor, isStatic, classType, signature, instructions, handlers, instToBC);
|
super(isConstructor, isStatic, classType, signature, instructions, handlers, instToBC, vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -300,8 +300,8 @@ public final class Verifier extends Analyzer {
|
||||||
super(info);
|
super(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Verifier(MethodData info, int[] instToBC) throws NullPointerException {
|
public Verifier(MethodData info, int[] instToBC, String[][] vars) throws NullPointerException {
|
||||||
super(info, instToBC);
|
super(info, instToBC, vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,11 +63,13 @@ final public class ClassInstrumenter {
|
||||||
|
|
||||||
private final ClassHierarchyProvider cha;
|
private final ClassHierarchyProvider cha;
|
||||||
|
|
||||||
|
private final boolean reuseStackMaps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a class instrumenter from raw bytes.
|
* Create a class instrumenter from raw bytes.
|
||||||
*/
|
*/
|
||||||
public ClassInstrumenter(String inputName, byte[] bytes, ClassHierarchyProvider cha) throws InvalidClassFileException {
|
public ClassInstrumenter(String inputName, byte[] bytes, ClassHierarchyProvider cha, boolean reuseStackMaps) throws InvalidClassFileException {
|
||||||
this(inputName, new ClassReader(bytes), cha);
|
this(inputName, new ClassReader(bytes), cha, reuseStackMaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,12 +93,13 @@ final public class ClassInstrumenter {
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException if cr is null
|
* @throws IllegalArgumentException if cr is null
|
||||||
*/
|
*/
|
||||||
public ClassInstrumenter(String inputName, ClassReader cr, ClassHierarchyProvider cha) throws InvalidClassFileException {
|
public ClassInstrumenter(String inputName, ClassReader cr, ClassHierarchyProvider cha, boolean reuseStackMaps) throws InvalidClassFileException {
|
||||||
if (cr == null) {
|
if (cr == null) {
|
||||||
throw new IllegalArgumentException("cr is null");
|
throw new IllegalArgumentException("cr is null");
|
||||||
}
|
}
|
||||||
this.cr = cr;
|
this.cr = cr;
|
||||||
this.cha = cha;
|
this.cha = cha;
|
||||||
|
this.reuseStackMaps = reuseStackMaps;
|
||||||
methods = new MethodData[cr.getMethodCount()];
|
methods = new MethodData[cr.getMethodCount()];
|
||||||
oldCode = new CodeReader[methods.length];
|
oldCode = new CodeReader[methods.length];
|
||||||
cpr = CTDecoder.makeConstantPoolReader(cr);
|
cpr = CTDecoder.makeConstantPoolReader(cr);
|
||||||
|
@ -426,7 +429,23 @@ final public class ClassInstrumenter {
|
||||||
stacks = new StackMapTableWriter(w, sm, output.getNewBytecodesToOldBytecodes());
|
stacks = new StackMapTableWriter(w, sm, output.getNewBytecodesToOldBytecodes());
|
||||||
codeAttrCount++;
|
codeAttrCount++;
|
||||||
} else { */
|
} else { */
|
||||||
stacks = new StackMapTableWriter(w, md, output, cha);
|
String[][] varTypes = null;
|
||||||
|
int[] newToOld = output.getNewBytecodesToOldBytecodes();
|
||||||
|
int[][] vars = LocalVariableTableReader.makeVarMap(oldCode);
|
||||||
|
if (vars != null) {
|
||||||
|
varTypes = new String[newToOld.length][];
|
||||||
|
for(int i = 0; i < newToOld.length; i++) {
|
||||||
|
int idx = newToOld[i];
|
||||||
|
if (idx != -1 && vars[idx] != null) {
|
||||||
|
varTypes[i] = new String[vars[idx].length / 2];
|
||||||
|
for(int j = 1; j < vars[idx].length; j += 2) {
|
||||||
|
int type = vars[idx][j];
|
||||||
|
varTypes[i][j/2] = type==0? null: oldCode.getClassReader().getCP().getCPUtf8(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stacks = new StackMapTableWriter(w, md, output, cha, varTypes);
|
||||||
codeAttrCount++;
|
codeAttrCount++;
|
||||||
// }
|
// }
|
||||||
} catch (IOException | FailureException e) {
|
} catch (IOException | FailureException e) {
|
||||||
|
|
|
@ -25,11 +25,12 @@ import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||||
* specialization of OfflineInstrumenterBase to use the shrikeCT functionality.
|
* specialization of OfflineInstrumenterBase to use the shrikeCT functionality.
|
||||||
*/
|
*/
|
||||||
final public class OfflineInstrumenter extends OfflineInstrumenterBase {
|
final public class OfflineInstrumenter extends OfflineInstrumenterBase {
|
||||||
|
private final boolean reuseStackMaps;
|
||||||
/**
|
/**
|
||||||
* Create an empty collection of classes to instrument.
|
* Create an empty collection of classes to instrument.
|
||||||
*/
|
*/
|
||||||
public OfflineInstrumenter() {
|
public OfflineInstrumenter(boolean reuseStackMaps) {
|
||||||
|
this.reuseStackMaps = reuseStackMaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,7 +38,7 @@ final public class OfflineInstrumenter extends OfflineInstrumenterBase {
|
||||||
byte[] bytes = new byte[s.available()];
|
byte[] bytes = new byte[s.available()];
|
||||||
Util.readFully(s, bytes);
|
Util.readFully(s, bytes);
|
||||||
try {
|
try {
|
||||||
return new ClassInstrumenter(inputName, bytes, cha);
|
return new ClassInstrumenter(inputName, bytes, cha, reuseStackMaps);
|
||||||
} catch (InvalidClassFileException e) {
|
} catch (InvalidClassFileException e) {
|
||||||
throw new IOException("Class is invalid: " + e.getMessage());
|
throw new IOException("Class is invalid: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class BatchVerifier {
|
||||||
private static int errors = 0;
|
private static int errors = 0;
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
OfflineInstrumenter oi = new OfflineInstrumenter();
|
OfflineInstrumenter oi = new OfflineInstrumenter(true);
|
||||||
args = oi.parseStandardArgs(args);
|
args = oi.parseStandardArgs(args);
|
||||||
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class BootstrapDumper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
OfflineInstrumenter oi = new OfflineInstrumenter();
|
OfflineInstrumenter oi = new OfflineInstrumenter(true);
|
||||||
String[] classpathEntries = oi.parseStandardArgs(args);
|
String[] classpathEntries = oi.parseStandardArgs(args);
|
||||||
|
|
||||||
PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
|
PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class ClassPrinter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
OfflineInstrumenter oi = new OfflineInstrumenter();
|
OfflineInstrumenter oi = new OfflineInstrumenter(true);
|
||||||
args = oi.parseStandardArgs(args);
|
args = oi.parseStandardArgs(args);
|
||||||
|
|
||||||
PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
|
PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class ClassSearcher {
|
||||||
private static int scanned = 0;
|
private static int scanned = 0;
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
instrumenter = new OfflineInstrumenter();
|
instrumenter = new OfflineInstrumenter(true);
|
||||||
|
|
||||||
Writer w = new BufferedWriter(new FileWriter("report", true));
|
Writer w = new BufferedWriter(new FileWriter("report", true));
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class MethodTracer {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
for (int i = 0; i < 1; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
instrumenter = new OfflineInstrumenter();
|
instrumenter = new OfflineInstrumenter(true);
|
||||||
|
|
||||||
Writer w = new BufferedWriter(new FileWriter("report", false));
|
Writer w = new BufferedWriter(new FileWriter("report", false));
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.jar.JarOutputStream;
|
import java.util.jar.JarOutputStream;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipException;
|
||||||
|
|
||||||
import com.ibm.wala.shrikeBT.analysis.ClassHierarchyProvider;
|
import com.ibm.wala.shrikeBT.analysis.ClassHierarchyProvider;
|
||||||
|
|
||||||
|
|
|
@ -97,19 +97,9 @@ public final class LocalVariableTableReader extends AttributeReader {
|
||||||
+ " in LocalVariableTable");
|
+ " in LocalVariableTable");
|
||||||
}
|
}
|
||||||
|
|
||||||
int rangeStart = startPC;
|
for (int k = startPC; k < startPC + length; k++) {
|
||||||
while (rangeStart < startPC + length) {
|
int[] newVector = makeVarVector(r[k], varIndex, nameIndex, typeIndex);
|
||||||
int rangeLength = 1;
|
r[k] = newVector;
|
||||||
while (rangeStart + rangeLength < startPC + length && r[rangeStart + rangeLength] == r[rangeStart]) {
|
|
||||||
rangeLength++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int[] newVector = makeVarVector(r[rangeStart], varIndex, nameIndex, typeIndex);
|
|
||||||
for (int k = rangeStart; k < rangeStart + rangeLength; k++) {
|
|
||||||
r[k] = newVector;
|
|
||||||
}
|
|
||||||
|
|
||||||
rangeStart += rangeLength;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package com.ibm.wala.shrikeCT;
|
package com.ibm.wala.shrikeCT;
|
||||||
|
|
||||||
import static com.ibm.wala.shrikeBT.Constants.TYPE_double;
|
import static com.ibm.wala.shrikeBT.Constants.*;
|
||||||
import static com.ibm.wala.shrikeBT.Constants.TYPE_float;
|
|
||||||
import static com.ibm.wala.shrikeBT.Constants.TYPE_int;
|
|
||||||
import static com.ibm.wala.shrikeBT.Constants.TYPE_long;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -54,8 +51,8 @@ public class StackMapTableWriter extends Element {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackMapTableWriter(ClassWriter writer, MethodData method, Output output, ClassHierarchyProvider cha) throws FailureException, IOException {
|
public StackMapTableWriter(ClassWriter writer, MethodData method, Output output, ClassHierarchyProvider cha, String[][] vars) throws FailureException, IOException {
|
||||||
this(writer, stackMapTable(writer, method, output, cha));
|
this(writer, stackMapTable(writer, method, output, cha, vars));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<StackMapFrame> remapStackFrames(List<StackMapFrame> sm, int[] newBytecodesToOldBytecodes) {
|
private static List<StackMapFrame> remapStackFrames(List<StackMapFrame> sm, int[] newBytecodesToOldBytecodes) {
|
||||||
|
@ -97,6 +94,8 @@ public class StackMapTableWriter extends Element {
|
||||||
static StackMapType item(String type) {
|
static StackMapType item(String type) {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
return Item.ITEM_Top;
|
return Item.ITEM_Top;
|
||||||
|
} else if (type.equals(TYPE_null)) {
|
||||||
|
return Item.ITEM_Null;
|
||||||
} else if (type.equals(Analyzer.topType)) {
|
} else if (type.equals(Analyzer.topType)) {
|
||||||
return Item.ITEM_Top;
|
return Item.ITEM_Top;
|
||||||
} else if (type.equals(Analyzer.thisType)) {
|
} else if (type.equals(Analyzer.thisType)) {
|
||||||
|
@ -138,7 +137,7 @@ public class StackMapTableWriter extends Element {
|
||||||
|
|
||||||
static StackMapType[] trim(StackMapType[] types) {
|
static StackMapType[] trim(StackMapType[] types) {
|
||||||
int i = types.length-1;
|
int i = types.length-1;
|
||||||
while (i >= 0 && (types[i] == null || types[i] == Item.ITEM_Null)) {
|
while (i >= 0 && (types[i] == null || types[i] == Item.ITEM_Null || types[i] == Item.ITEM_Top)) {
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +152,24 @@ public class StackMapTableWriter extends Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String hackUnknown(String type) {
|
||||||
|
if (type == null) {
|
||||||
|
return type;
|
||||||
|
} else if (type.startsWith("[")) {
|
||||||
|
return "[" + hackUnknown(type.substring(1));
|
||||||
|
} else if ("L?;".equals(type)) {
|
||||||
|
return "Ljava/lang/Object;";
|
||||||
|
} else {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static StackMapType[] types(String[] types, boolean locals) {
|
static StackMapType[] types(String[] types, boolean locals) {
|
||||||
StackMapType[] stackTypes = new StackMapType[ types.length ];
|
StackMapType[] stackTypes = new StackMapType[ types.length ];
|
||||||
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for(int j = 0; j < types.length; j++) {
|
for(int j = 0; j < types.length; j++) {
|
||||||
StackMapType stackType = item("L?;".equals(types[j])? "Ljava/lang/Object;": types[j]);
|
StackMapType stackType = item(hackUnknown(types[j]));
|
||||||
stackTypes[x++] = stackType;
|
stackTypes[x++] = stackType;
|
||||||
if (locals && stackType.size() == 2) {
|
if (locals && stackType.size() == 2) {
|
||||||
j++;
|
j++;
|
||||||
|
@ -178,13 +189,13 @@ public class StackMapTableWriter extends Element {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<StackMapFrame> stackMapTable(ClassWriter writer, MethodData method, Output output, ClassHierarchyProvider cha) throws FailureException, IOException {
|
public static List<StackMapFrame> stackMapTable(ClassWriter writer, MethodData method, Output output, ClassHierarchyProvider cha, String[][] vars) throws FailureException, IOException {
|
||||||
List<StackMapFrame> frames = new ArrayList<StackMapFrame>();
|
List<StackMapFrame> frames = new ArrayList<StackMapFrame>();
|
||||||
|
|
||||||
int[] instructionToBytecode = output.getInstructionOffsets();
|
int[] instructionToBytecode = output.getInstructionOffsets();
|
||||||
IInstruction[] insts = method.getInstructions();
|
IInstruction[] insts = method.getInstructions();
|
||||||
|
|
||||||
Verifier typeChecker = new Verifier(method, instructionToBytecode);
|
Verifier typeChecker = new Verifier(method, instructionToBytecode, vars);
|
||||||
if (cha != null) {
|
if (cha != null) {
|
||||||
typeChecker.setClassHierarchy(cha);
|
typeChecker.setClassHierarchy(cha);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue