From 63232e4a02331ce94910c8e0e83f10467843ce52 Mon Sep 17 00:00:00 2001 From: Julian Dolby Date: Fri, 10 Oct 2014 17:46:56 -0400 Subject: [PATCH] further work on geberating stack maps --- .../wala/shrike/bench/AddBytecodeDebug.java | 2 +- .../src/com/ibm/wala/shrike/bench/Bench.java | 2 +- .../wala/shrike/bench/InterfaceAnalyzer.java | 2 +- .../com/ibm/wala/shrike/bench/Mangler.java | 2 +- .../com/ibm/wala/shrike/bench/Statistics.java | 2 +- .../ibm/wala/shrike/cg/DynamicCallGraph.java | 114 +++++++++--------- .../wala/shrike/copywriter/CopyWriter.java | 2 +- .../src/com/ibm/wala/shrikeBT/Compiler.java | 2 +- .../ibm/wala/shrikeBT/analysis/Analyzer.java | 50 +++++++- .../shrikeBT/analysis/ClassHierarchy.java | 5 + .../ibm/wala/shrikeBT/analysis/Verifier.java | 8 +- .../shrikeBT/shrikeCT/ClassInstrumenter.java | 27 ++++- .../shrikeCT/OfflineInstrumenter.java | 7 +- .../shrikeCT/tools/BatchVerifier.java | 2 +- .../shrikeCT/tools/BootstrapDumper.java | 2 +- .../shrikeBT/shrikeCT/tools/ClassPrinter.java | 2 +- .../shrikeCT/tools/ClassSearcher.java | 2 +- .../shrikeBT/shrikeCT/tools/MethodTracer.java | 2 +- .../tools/OfflineInstrumenterBase.java | 1 + .../shrikeCT/LocalVariableTableReader.java | 16 +-- .../wala/shrikeCT/StackMapTableWriter.java | 31 +++-- 21 files changed, 178 insertions(+), 105 deletions(-) diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/AddBytecodeDebug.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/AddBytecodeDebug.java index 308e68f40..a9759acb5 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/AddBytecodeDebug.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/AddBytecodeDebug.java @@ -42,7 +42,7 @@ public class AddBytecodeDebug { public static void main(String[] args) throws Exception { for (int i = 0; i < 1; i++) { - instrumenter = new OfflineInstrumenter(); + instrumenter = new OfflineInstrumenter(true); Writer w = new BufferedWriter(new FileWriter("report", false)); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Bench.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Bench.java index f0570ef25..9192c83bc 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Bench.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Bench.java @@ -61,7 +61,6 @@ public class Bench { public static void main(String[] args) throws Exception { for (int i = 0; i < 1; i++) { - instrumenter = new OfflineInstrumenter(); Writer w = new BufferedWriter(new FileWriter("report", false)); @@ -74,6 +73,7 @@ public class Bench { doException = true; } } + instrumenter = new OfflineInstrumenter(!doException); instrumenter.setPassUnmodifiedClasses(true); instrumenter.beginTraversal(); ClassInstrumenter ci; diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/InterfaceAnalyzer.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/InterfaceAnalyzer.java index 40b313ba1..e1cc6edbe 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/InterfaceAnalyzer.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/InterfaceAnalyzer.java @@ -41,7 +41,7 @@ public class InterfaceAnalyzer { final static HashMap typeStats = new HashMap(); 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)); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Mangler.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Mangler.java index c0c8045d2..573493316 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Mangler.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Mangler.java @@ -57,7 +57,7 @@ public class Mangler { public static void main(String[] args) throws Exception { for (int i = 0; i < 1; i++) { - instrumenter = new OfflineInstrumenter(); + instrumenter = new OfflineInstrumenter(true); Writer w = new BufferedWriter(new FileWriter("report", false)); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Statistics.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Statistics.java index 16ef1ec16..48392bc10 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Statistics.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/bench/Statistics.java @@ -39,7 +39,7 @@ public class Statistics { public static void main(String[] args) throws Exception { for (int i = 0; i < 1; i++) { - instrumenter = new OfflineInstrumenter(); + instrumenter = new OfflineInstrumenter(true); Writer w = new BufferedWriter(new FileWriter("report", false)); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/DynamicCallGraph.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/DynamicCallGraph.java index e2c00075e..37fbc23fb 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/DynamicCallGraph.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/DynamicCallGraph.java @@ -60,6 +60,8 @@ public class DynamicCallGraph { private final static boolean disasm = true; private final static boolean verify = true; + private static boolean patchExits = true; + private static OfflineInstrumenter instrumenter; private static Class runtime = Runtime.class; @@ -72,24 +74,26 @@ public class DynamicCallGraph { ClassInstrumenter ci; Writer w = new BufferedWriter(new FileWriter("report", false)); - instrumenter = new OfflineInstrumenter(); - args = instrumenter.parseStandardArgs(args); - - for(int i = 0; i < args.length - 1; i++) { - if ("--runtime".equals(args[i])) { - runtime = Class.forName(args[i+1]); - } else if ("--exclusions".equals(args[i])) { - filter = new FileOfClasses(new FileInputStream(args[i+1])); - } else if ("--rt-jar".equals(args[i])) { - System.err.println("using " + args[i+1] + " as stdlib"); - OfflineInstrumenter libReader = new OfflineInstrumenter(); - libReader.addInputJar(new File(args[i+1])); - while ((ci = libReader.nextClass()) != null) { - CTUtils.addClassToHierarchy(cha, ci.getReader()); + for(int i = 0; i < args.length - 1; i++) { + if ("--runtime".equals(args[i])) { + runtime = Class.forName(args[i+1]); + } else if ("--exclusions".equals(args[i])) { + filter = new FileOfClasses(new FileInputStream(args[i+1])); + } else if ("--dont-patch-exits".equals(args[i])) { + patchExits = false; + } else if ("--rt-jar".equals(args[i])) { + System.err.println("using " + args[i+1] + " as stdlib"); + OfflineInstrumenter libReader = new OfflineInstrumenter(true); + libReader.addInputJar(new File(args[i+1])); + while ((ci = libReader.nextClass()) != null) { + CTUtils.addClassToHierarchy(cha, ci.getReader()); + } } } - } - + + instrumenter = new OfflineInstrumenter(!patchExits); + args = instrumenter.parseStandardArgs(args); + instrumenter.setPassUnmodifiedClasses(true); instrumenter.beginTraversal(); @@ -137,7 +141,7 @@ public class DynamicCallGraph { if (verify) { Verifier v = new Verifier(d); - v.setClassHierarchy(cha); + // v.setClassHierarchy(cha); v.verify(); } @@ -163,42 +167,44 @@ public class DynamicCallGraph { } }); - me.addMethodExceptionHandler(null, new MethodEditor.Patch() { - @Override - public void emitTo(Output w) { - w.emit(ConstantInstruction.makeString(theClass)); - w.emit(ConstantInstruction.makeString(theMethod)); - //if (nonStatic) - // w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this - //else - w.emit(Util.makeGet(runtime, "NULL_TAG")); - // w.emit(ConstantInstruction.make(Constants.TYPE_null, null)); - w.emit(ConstantInstruction.make(1)); // true - 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 - public void visitReturn(ReturnInstruction instruction) { - insertBefore(new MethodEditor.Patch() { - @Override - public void emitTo(MethodEditor.Output w) { - w.emit(ConstantInstruction.makeString(theClass)); - w.emit(ConstantInstruction.makeString(theMethod)); - if (nonStatic) - w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this - else - w.emit(Util.makeGet(runtime, "NULL_TAG")); - // w.emit(ConstantInstruction.make(Constants.TYPE, null)); - w.emit(ConstantInstruction.make(0)); // false - w.emit(Util.makeInvoke(runtime, "termination", new Class[] {String.class, String.class, Object.class, boolean.class})); - } - }); - } - }); - + if (patchExits) { + me.addMethodExceptionHandler(null, new MethodEditor.Patch() { + @Override + public void emitTo(Output w) { + w.emit(ConstantInstruction.makeString(theClass)); + w.emit(ConstantInstruction.makeString(theMethod)); + //if (nonStatic) + // w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this + //else + w.emit(Util.makeGet(runtime, "NULL_TAG")); + // w.emit(ConstantInstruction.make(Constants.TYPE_null, null)); + w.emit(ConstantInstruction.make(1)); // true + 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 + public void visitReturn(ReturnInstruction instruction) { + insertBefore(new MethodEditor.Patch() { + @Override + public void emitTo(MethodEditor.Output w) { + w.emit(ConstantInstruction.makeString(theClass)); + w.emit(ConstantInstruction.makeString(theMethod)); + if (nonStatic) + w.emit(LoadInstruction.make(Constants.TYPE_Object, 0)); //load this + else + w.emit(Util.makeGet(runtime, "NULL_TAG")); + // w.emit(ConstantInstruction.make(Constants.TYPE, null)); + 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 me.applyPatches(); @@ -210,7 +216,7 @@ public class DynamicCallGraph { if (verify) { Verifier v = new Verifier(d); - v.setClassHierarchy(cha); + // v.setClassHierarchy(cha); v.verify(); } } diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/copywriter/CopyWriter.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/copywriter/CopyWriter.java index 1deaa3f87..39f3c7379 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/copywriter/CopyWriter.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/copywriter/CopyWriter.java @@ -93,7 +93,7 @@ public class CopyWriter { final ArrayList entries = new ArrayList(); - instrumenter = new OfflineInstrumenter(); + instrumenter = new OfflineInstrumenter(true); instrumenter.setManifestBuilder(new OfflineInstrumenter.ManifestBuilder() { @Override public void addEntry(ZipEntry ze) { diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/Compiler.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/Compiler.java index 79a3981ed..13918e15c 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/Compiler.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/Compiler.java @@ -1681,7 +1681,7 @@ public abstract class Compiler implements Constants { } 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) { v.setClassHierarchy(hierarchy); } diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Analyzer.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Analyzer.java index 0999f7225..dabdac94a 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Analyzer.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Analyzer.java @@ -13,6 +13,7 @@ package com.ibm.wala.shrikeBT.analysis; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; import java.util.List; @@ -71,12 +72,14 @@ public class Analyzer { protected int[][] backEdges; protected int[] instToBC; + + protected String[][] varTypes; protected final static String[] noStrings = new String[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) { throw new IllegalArgumentException("null instructions"); } @@ -95,6 +98,7 @@ public class Analyzer { this.instructions = instructions; this.handlers = handlers; this.instToBC = instToBC; + this.varTypes = vars; } /** @@ -203,6 +207,15 @@ public class Analyzer { 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) { return topType; } @@ -213,7 +226,7 @@ public class Analyzer { 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); } @@ -694,6 +707,28 @@ public class Analyzer { instr.visit(localsUpdate); // visit localStore before popping System.arraycopy(curStack, popped, curStack, 0, 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(); 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)) { computeTypes(targets[j], visitor, makeTypesAt, path); } @@ -830,11 +870,11 @@ public class Analyzer { } protected Analyzer(MethodData info) { - this(info.getName().equals(""), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), info.getInstructionsToBytecodes()); + this(info.getName().equals(""), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), info.getInstructionsToBytecodes(), null); } - protected Analyzer(MethodData info, int[] instToBC) { - this(info.getName().equals(""), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), instToBC); + protected Analyzer(MethodData info, int[] instToBC, String[][] vars) { + this(info.getName().equals(""), info.getIsStatic(), info.getClassType(), info.getSignature(), info.getInstructions(), info.getHandlers(), instToBC, vars); } public static Analyzer createAnalyzer(MethodData info) { diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/ClassHierarchy.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/ClassHierarchy.java index 3e0b0ff7b..fee09c2f3 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/ClassHierarchy.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/ClassHierarchy.java @@ -277,6 +277,11 @@ public final class ClassHierarchy { } 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) { return t2; } else if (isSubtypeOf(hierarchy, t2, t1) == YES) { diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Verifier.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Verifier.java index 37e7a658f..cdd28f3cf 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Verifier.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/analysis/Verifier.java @@ -287,8 +287,8 @@ public final class Verifier extends Analyzer { /** * Initialize a verifier. */ - public Verifier(boolean isConstructor, boolean isStatic, String classType, String signature, IInstruction[] instructions, ExceptionHandler[][] handlers, int[] instToBC) { - super(isConstructor, isStatic, classType, signature, instructions, handlers, 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, vars); } /** @@ -300,8 +300,8 @@ public final class Verifier extends Analyzer { super(info); } - public Verifier(MethodData info, int[] instToBC) throws NullPointerException { - super(info, instToBC); + public Verifier(MethodData info, int[] instToBC, String[][] vars) throws NullPointerException { + super(info, instToBC, vars); } /** diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/ClassInstrumenter.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/ClassInstrumenter.java index 07fc978bc..a5641a089 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/ClassInstrumenter.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/ClassInstrumenter.java @@ -63,11 +63,13 @@ final public class ClassInstrumenter { private final ClassHierarchyProvider cha; + private final boolean reuseStackMaps; + /** * Create a class instrumenter from raw bytes. */ - public ClassInstrumenter(String inputName, byte[] bytes, ClassHierarchyProvider cha) throws InvalidClassFileException { - this(inputName, new ClassReader(bytes), cha); + public ClassInstrumenter(String inputName, byte[] bytes, ClassHierarchyProvider cha, boolean reuseStackMaps) throws InvalidClassFileException { + this(inputName, new ClassReader(bytes), cha, reuseStackMaps); } /** @@ -91,12 +93,13 @@ final public class ClassInstrumenter { * * @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) { throw new IllegalArgumentException("cr is null"); } this.cr = cr; this.cha = cha; + this.reuseStackMaps = reuseStackMaps; methods = new MethodData[cr.getMethodCount()]; oldCode = new CodeReader[methods.length]; cpr = CTDecoder.makeConstantPoolReader(cr); @@ -426,7 +429,23 @@ final public class ClassInstrumenter { stacks = new StackMapTableWriter(w, sm, output.getNewBytecodesToOldBytecodes()); codeAttrCount++; } 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++; // } } catch (IOException | FailureException e) { diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/OfflineInstrumenter.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/OfflineInstrumenter.java index 35ae74703..63a84f5e7 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/OfflineInstrumenter.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/OfflineInstrumenter.java @@ -25,11 +25,12 @@ import com.ibm.wala.shrikeCT.InvalidClassFileException; * specialization of OfflineInstrumenterBase to use the shrikeCT functionality. */ final public class OfflineInstrumenter extends OfflineInstrumenterBase { + private final boolean reuseStackMaps; /** * Create an empty collection of classes to instrument. */ - public OfflineInstrumenter() { - + public OfflineInstrumenter(boolean reuseStackMaps) { + this.reuseStackMaps = reuseStackMaps; } @Override @@ -37,7 +38,7 @@ final public class OfflineInstrumenter extends OfflineInstrumenterBase { byte[] bytes = new byte[s.available()]; Util.readFully(s, bytes); try { - return new ClassInstrumenter(inputName, bytes, cha); + return new ClassInstrumenter(inputName, bytes, cha, reuseStackMaps); } catch (InvalidClassFileException e) { throw new IOException("Class is invalid: " + e.getMessage()); } diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BatchVerifier.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BatchVerifier.java index 4650edf26..4a6829abc 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BatchVerifier.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BatchVerifier.java @@ -48,7 +48,7 @@ public class BatchVerifier { private static int errors = 0; public static void main(String[] args) throws Exception { - OfflineInstrumenter oi = new OfflineInstrumenter(); + OfflineInstrumenter oi = new OfflineInstrumenter(true); args = oi.parseStandardArgs(args); for (int i = 0; i < args.length; i++) { diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BootstrapDumper.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BootstrapDumper.java index 75f556434..3db6ddf83 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BootstrapDumper.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/BootstrapDumper.java @@ -42,7 +42,7 @@ public class BootstrapDumper { } public static void main(String[] args) throws Exception { - OfflineInstrumenter oi = new OfflineInstrumenter(); + OfflineInstrumenter oi = new OfflineInstrumenter(true); String[] classpathEntries = oi.parseStandardArgs(args); PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassPrinter.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassPrinter.java index 8da0a1432..8c705108b 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassPrinter.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassPrinter.java @@ -72,7 +72,7 @@ public class ClassPrinter { } public static void main(String[] args) throws Exception { - OfflineInstrumenter oi = new OfflineInstrumenter(); + OfflineInstrumenter oi = new OfflineInstrumenter(true); args = oi.parseStandardArgs(args); PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassSearcher.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassSearcher.java index 33b14793d..56b5bbaff 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassSearcher.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/ClassSearcher.java @@ -36,7 +36,7 @@ public class ClassSearcher { private static int scanned = 0; public static void main(String[] args) throws Exception { - instrumenter = new OfflineInstrumenter(); + instrumenter = new OfflineInstrumenter(true); Writer w = new BufferedWriter(new FileWriter("report", true)); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/MethodTracer.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/MethodTracer.java index a2205f794..fc9a39f55 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/MethodTracer.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/shrikeCT/tools/MethodTracer.java @@ -51,7 +51,7 @@ public class MethodTracer { public static void main(String[] args) throws Exception { for (int i = 0; i < 1; i++) { - instrumenter = new OfflineInstrumenter(); + instrumenter = new OfflineInstrumenter(true); Writer w = new BufferedWriter(new FileWriter("report", false)); diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/tools/OfflineInstrumenterBase.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/tools/OfflineInstrumenterBase.java index 4d6aeb519..3421d43a7 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/tools/OfflineInstrumenterBase.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/tools/OfflineInstrumenterBase.java @@ -27,6 +27,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.zip.ZipEntry; +import java.util.zip.ZipException; import com.ibm.wala.shrikeBT.analysis.ClassHierarchyProvider; diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/LocalVariableTableReader.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/LocalVariableTableReader.java index dd4cd746f..6523b8c0d 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/LocalVariableTableReader.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/LocalVariableTableReader.java @@ -97,19 +97,9 @@ public final class LocalVariableTableReader extends AttributeReader { + " in LocalVariableTable"); } - int rangeStart = startPC; - while (rangeStart < startPC + length) { - int rangeLength = 1; - 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; + for (int k = startPC; k < startPC + length; k++) { + int[] newVector = makeVarVector(r[k], varIndex, nameIndex, typeIndex); + r[k] = newVector; } } } diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapTableWriter.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapTableWriter.java index 3717dc037..e5a1a2ab0 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapTableWriter.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapTableWriter.java @@ -1,9 +1,6 @@ package com.ibm.wala.shrikeCT; -import static com.ibm.wala.shrikeBT.Constants.TYPE_double; -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 static com.ibm.wala.shrikeBT.Constants.*; import java.io.ByteArrayOutputStream; 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 { - this(writer, stackMapTable(writer, method, output, cha)); + public StackMapTableWriter(ClassWriter writer, MethodData method, Output output, ClassHierarchyProvider cha, String[][] vars) throws FailureException, IOException { + this(writer, stackMapTable(writer, method, output, cha, vars)); } private static List remapStackFrames(List sm, int[] newBytecodesToOldBytecodes) { @@ -97,6 +94,8 @@ public class StackMapTableWriter extends Element { static StackMapType item(String type) { if (type == null) { return Item.ITEM_Top; + } else if (type.equals(TYPE_null)) { + return Item.ITEM_Null; } else if (type.equals(Analyzer.topType)) { return Item.ITEM_Top; } else if (type.equals(Analyzer.thisType)) { @@ -138,7 +137,7 @@ public class StackMapTableWriter extends Element { static StackMapType[] trim(StackMapType[] types) { 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--; } @@ -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) { StackMapType[] stackTypes = new StackMapType[ types.length ]; int x = 0; 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; if (locals && stackType.size() == 2) { j++; @@ -178,13 +189,13 @@ public class StackMapTableWriter extends Element { return false; } - public static List stackMapTable(ClassWriter writer, MethodData method, Output output, ClassHierarchyProvider cha) throws FailureException, IOException { + public static List stackMapTable(ClassWriter writer, MethodData method, Output output, ClassHierarchyProvider cha, String[][] vars) throws FailureException, IOException { List frames = new ArrayList(); int[] instructionToBytecode = output.getInstructionOffsets(); IInstruction[] insts = method.getInstructions(); - Verifier typeChecker = new Verifier(method, instructionToBytecode); + Verifier typeChecker = new Verifier(method, instructionToBytecode, vars); if (cha != null) { typeChecker.setClassHierarchy(cha); }