public void execute(AbstractInsnNode insn, Interpreter interpreter) throws AnalyzerException { boolean never = false; if (never) { super.execute(insn, interpreter); return; } int insnOpcode = insn.getOpcode(); if (insnOpcode == Opcodes.MONITORENTER || insnOpcode == Opcodes.MONITOREXIT) { Value pop = pop(); interpreter.unaryOperation(insn, pop); int local = -1; for (int i = 0; i < getLocals(); i++) { if (getLocal(i) == pop) local = i; } if (local > -1) { if (insnOpcode == Opcodes.MONITORENTER) { monitorEnter(local); } else { monitorExit(local); } } } else { super.execute(insn, interpreter); } }
@Override public Value copyOperation(final AbstractInsnNode insn, Value value) throws AnalyzerException { // Fix error with analyzer for try-with-resources (it sees uninitialized values) if (insn.getOpcode() == Opcodes.ALOAD && (value instanceof BasicValue && !((BasicValue)value).isReference())) { value = newValue(Type.getType("Lnull;")); } return super.copyOperation(insn, value); }
@Override public Value unaryOperation(final AbstractInsnNode insn, Value value) throws AnalyzerException { // Fix error with analyzer for try-with-resources (it sees uninitialized values) if (insn.getOpcode() == Opcodes.ARETURN && (value instanceof BasicValue && !((BasicValue)value).isReference())) { value = newValue(Type.getType("Lnull;")); } return super.unaryOperation(insn, value); }
@Override protected boolean isSubTypeOf(final Value value, final Value expected) { if (!(value instanceof BasicValue)) { return value.equals(expected); } Type expectedType = ((BasicValue)expected).getType(); Type type = ((BasicValue)value).getType(); switch (expectedType.getSort()) { case Type.BOOLEAN: case Type.CHAR: case Type.BYTE: case Type.SHORT: case Type.INT: case Type.FLOAT: case Type.LONG: case Type.DOUBLE: return type.equals(expectedType); case Type.ARRAY: case Type.OBJECT: // We are transforming valid bytecode to (hopefully) valid bytecode // hence pairs of "value" and "expected" must be compatible return true;//isAssignableFrom(expectedType, type); default: throw new Error("Internal error"); } }
public static <V extends Value> Frame<V>[] getFrames(Analyzer<V> analyzer, String clazz, MethodNode method) { try { analyzer.analyze(clazz, method); } catch (AnalyzerException e) { throw new DiSLFatalException("Cause by AnalyzerException : \n" + e.getMessage()); } return analyzer.getFrames(); }
private void dumpCodeBlock(MethodVisitor mv, int idx, int skip) { int start = codeBlocks[idx].endInstruction; int end = codeBlocks[idx+1].endInstruction; for(int i=start+skip ; i<end ; i++) { AbstractInsnNode ins = mn.instructions.get(i); switch(ins.getOpcode()) { case Opcodes.RETURN: case Opcodes.ARETURN: case Opcodes.IRETURN: case Opcodes.LRETURN: case Opcodes.FRETURN: case Opcodes.DRETURN: emitPopMethod(mv); break; case Opcodes.MONITORENTER: case Opcodes.MONITOREXIT: if(!db.isAllowMonitors()) { throw new UnableToInstrumentException("synchronisation", className, mn.name, mn.desc); } else if(!warnedAboutMonitors) { warnedAboutMonitors = true; db.log(LogLevel.WARNING, "Method %s#%s%s contains synchronisation", className, mn.name, mn.desc); } break; case Opcodes.INVOKESPECIAL: MethodInsnNode min = (MethodInsnNode)ins; if("<init>".equals(min.name)) { int argSize = TypeAnalyzer.getNumArguments(min.desc); Frame frame = frames[i]; int stackIndex = frame.getStackSize() - argSize - 1; Value thisValue = frame.getStack(stackIndex); if(stackIndex >= 1 && isNewValue(thisValue, true) && isNewValue(frame.getStack(stackIndex-1), false)) { NewValue newValue = (NewValue)thisValue; if(newValue.omitted) { emitNewAndDup(mv, frame, stackIndex, min); } } else { db.log(LogLevel.WARNING, "Expected to find a NewValue on stack index %d: %s", stackIndex, frame); } } break; } ins.accept(mv); } }
static boolean isNewValue(Value v, boolean dupped) { if(v instanceof NewValue) { return ((NewValue)v).isDupped == dupped; } return false; }
private boolean isUninitialized(final Value value) { return value instanceof FrameAnalyzer.ExtendedValue && ((FrameAnalyzer.ExtendedValue) value).isUninitialized(); }
private int valueSize(final Value local) { return local == null ? 1 : local.getSize(); }
public static <T extends Value> T getStackByIndex(Frame<T> frame, int index) { return frame.getStack(frame.getStackSize() - 1 - index); }
@Override public void setLocal(int i, Value v) throws IndexOutOfBoundsException { super.setLocal(i,v); }
public InstMethodSinkInterpreter(LinkedList<SinkableArrayValue> relevantValues, HashMap<AbstractInsnNode, Value> liveValues) { this.relevant = relevantValues; }
public static <T extends Value> T getStack(Frame<T> frame, int depth) { int index = 0; while (depth > 0) { depth -= frame.getStack(frame.getStackSize() - 1 - index).getSize(); index++; } return frame.getStack(frame.getStackSize() - 1 - index); }
public static <V extends Value> Map<AbstractInsnNode, Frame<V>> createMapping( Analyzer<V> analyzer, String clazz, MethodNode method) { Map<AbstractInsnNode, Frame<V>> mapping; mapping = new HashMap<AbstractInsnNode, Frame<V>>(); Frame<V>[] frames = getFrames(analyzer, clazz, method); for (int i = 0; i < method.instructions.size(); i++) { mapping.put(method.instructions.get(i), frames[i]); } return mapping; }
/** * Constructs a new frame with the given size. * * @param nLocals * the maximum number of local variables of the frame. * @param nStack * the maximum stack size of the frame. */ public Frame(final int nLocals, final int nStack) { this.values = (V[]) new Value[nLocals + nStack]; this.locals = nLocals; }