Search in sources :

Example 66 with AbstractInsnNode

use of org.objectweb.asm.tree.AbstractInsnNode in project bytecode-viewer by Konloch.

the class InstructionPrinter method createPrint.

/**
 * Creates the print
 *
 * @return The print as an ArrayList
 */
public List<String> createPrint() {
    firstLabel = false;
    info.clear();
    for (AbstractInsnNode ain : mNode.instructions) {
        String line = printInstruction(ain);
        if (!line.isEmpty()) {
            if (match)
                if (matchedInsns.contains(ain))
                    line = "   -> " + line;
            info.add(line);
        }
    }
    if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
        info.add("}");
    return info;
}
Also used : AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode)

Example 67 with AbstractInsnNode

use of org.objectweb.asm.tree.AbstractInsnNode in project bytecode-viewer by Konloch.

the class LDCSearch method search.

public void search(final ResourceContainer container, final String resourceWorkingName, final ClassNode node, boolean caseSensitive) {
    final Iterator<MethodNode> methods = node.methods.iterator();
    final String srchText = searchText.getText();
    final String srchTextLowerCase = searchText.getText().toLowerCase();
    if (srchText.isEmpty())
        return;
    while (methods.hasNext()) {
        final MethodNode method = methods.next();
        final InsnList insnlist = method.instructions;
        for (AbstractInsnNode insnNode : insnlist) {
            if (insnNode instanceof LdcInsnNode) {
                final LdcInsnNode ldcObject = ((LdcInsnNode) insnNode);
                final String ldcString = ldcObject.cst.toString();
                // TODO re-add this at some point when the search pane is redone
                boolean exact = false;
                final boolean exactMatch = exact && ldcString.equals(srchText);
                final boolean caseInsensitiveMatch = !exact && caseSensitive && ldcString.contains(srchText);
                final boolean caseSensitiveMatch = !exact && !caseSensitive && ldcString.toLowerCase().contains(srchTextLowerCase);
                final boolean anyMatch = exactMatch || caseInsensitiveMatch || caseSensitiveMatch;
                if (anyMatch) {
                    BytecodeViewer.viewer.searchBoxPane.treeRoot.add(new LDCSearchTreeNodeResult(container, resourceWorkingName, node, method, null, ldcString, ldcObject.cst.getClass().getCanonicalName()));
                }
            }
        }
    }
    final Iterator<FieldNode> fields = node.fields.iterator();
    while (methods.hasNext()) {
        final FieldNode field = fields.next();
        if (field.value instanceof String) {
            BytecodeViewer.viewer.resourcePane.treeRoot.add(new LDCSearchTreeNodeResult(container, resourceWorkingName, node, null, field, String.valueOf(field.value), field.value.getClass().getCanonicalName()));
        }
    }
}
Also used : LdcInsnNode(org.objectweb.asm.tree.LdcInsnNode) MethodNode(org.objectweb.asm.tree.MethodNode) FieldNode(org.objectweb.asm.tree.FieldNode) LDCSearchTreeNodeResult(the.bytecode.club.bytecodeviewer.searching.LDCSearchTreeNodeResult) InsnList(org.objectweb.asm.tree.InsnList) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode)

Example 68 with AbstractInsnNode

use of org.objectweb.asm.tree.AbstractInsnNode in project groovy by apache.

the class VerifyClass method readClass.

private boolean readClass(String clazz) throws IOException {
    ClassNode ca;
    try (final InputStream inputStream = new BufferedInputStream(new FileInputStream(clazz))) {
        ClassReader cr = new ClassReader(inputStream);
        ca = new ClassNode() {

            @Override
            public void visitEnd() {
            // accept(cv);
            }
        };
        cr.accept(new CheckClassAdapter(ca), ClassWriter.COMPUTE_MAXS);
    }
    boolean failed = false;
    List<MethodNode> methods = ca.methods;
    for (MethodNode method : methods) {
        if (method.instructions.size() > 0) {
            Analyzer<?> a = new Analyzer<>(new SimpleVerifier());
            try {
                a.analyze(ca.name, method);
                continue;
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (!failed) {
                failed = true;
                log("verifying of class " + clazz + " failed");
            }
            if (verbose)
                log(method.name + method.desc);
            TraceMethodVisitor mv = new TraceMethodVisitor(null);
            for (int j = 0; j < method.instructions.size(); ++j) {
                AbstractInsnNode insn = method.instructions.get(j);
                if (insn != null) {
                    insn.accept(mv);
                } else {
                    mv.visitLabel(null);
                }
            }
            mv.visitMaxs(method.maxStack, method.maxLocals);
        }
    }
    return !failed;
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) SimpleVerifier(org.objectweb.asm.tree.analysis.SimpleVerifier) BufferedInputStream(java.io.BufferedInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) Analyzer(org.objectweb.asm.tree.analysis.Analyzer) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) TraceMethodVisitor(org.objectweb.asm.util.TraceMethodVisitor) FileInputStream(java.io.FileInputStream) BuildException(org.apache.tools.ant.BuildException) IOException(java.io.IOException) MethodNode(org.objectweb.asm.tree.MethodNode) BufferedInputStream(java.io.BufferedInputStream) CheckClassAdapter(org.objectweb.asm.util.CheckClassAdapter) ClassReader(org.objectweb.asm.ClassReader)

Example 69 with AbstractInsnNode

use of org.objectweb.asm.tree.AbstractInsnNode in project quasar by puniverse.

the class InstrumentMethod method accept.

public void accept(MethodVisitor mv, boolean hasAnnotation) {
    db.log(LogLevel.INFO, "Instrumenting method %s:%s#%s%s", sourceName, className, mn.name, mn.desc);
    if (mn.name.charAt(0) == '<')
        throw new UnableToInstrumentException("special method", className, mn.name, mn.desc);
    collectCallsites();
    final boolean skipInstrumentation = canInstrumentationBeSkipped(suspCallsBcis);
    emitInstrumentedAnn(db, mv, mn, sourceName, className, skipInstrumentation, startSourceLine, endSourceLine, suspCallsSourceLines, suspCallsNames, null);
    if (skipInstrumentation) {
        db.log(LogLevel.INFO, "[OPTIMIZE] Skipping instrumentation for method %s:%s#%s%s", sourceName, className, mn.name, mn.desc);
        // Dump
        mn.accept(mv);
        return;
    }
    // Else instrument
    // Must be called first, sets flags & state used below
    collectCodeBlocks();
    // noinspection ConstantConditions
    final boolean handleProxyInvocations = HANDLE_PROXY_INVOCATIONS && callsSuspendableSupers;
    mv.visitCode();
    Label lMethodStart = new Label();
    Label lMethodStart2 = new Label();
    Label lMethodEnd = new Label();
    Label lCatchSEE = new Label();
    Label lCatchUTE = new Label();
    Label lCatchAll = new Label();
    Label[] lMethodCalls = new Label[numCodeBlocks - 1];
    Label[][] refInvokeTryCatch;
    for (int i = 1; i < numCodeBlocks; i++) lMethodCalls[i - 1] = new Label();
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue);
    // if (verifyInstrumentation) {
    // mv.visitInsn(Opcodes.ICONST_0);
    // mv.visitVarInsn(Opcodes.ISTORE, lvarSuspendableCalled);
    // }
    mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, SUSPEND_EXECUTION_NAME);
    mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, RUNTIME_SUSPEND_EXECUTION_NAME);
    if (handleProxyInvocations)
        mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchUTE, UNDECLARED_THROWABLE_NAME);
    // Prepare visitTryCatchBlocks for InvocationTargetException.
    // With reflective invocations, the SuspendExecution exception will be wrapped in InvocationTargetException. We need to catch it and unwrap it.
    // Note that the InvocationTargetException will be regenrated on every park, adding further overhead on top of the reflective call.
    // This must be done here, before all other visitTryCatchBlock, because the exception's handler
    // will be matched according to the order of in which visitTryCatchBlock has been called. Earlier calls take precedence.
    refInvokeTryCatch = new Label[numCodeBlocks - 1][];
    for (int i = 1; i < numCodeBlocks; i++) {
        final FrameInfo fi = codeBlocks[i];
        final AbstractInsnNode in = mn.instructions.get(fi.endInstruction);
        if (mn.instructions.get(fi.endInstruction) instanceof MethodInsnNode) {
            MethodInsnNode min = (MethodInsnNode) in;
            if (isReflectInvocation(min.owner, min.name)) {
                Label[] ls = new Label[3];
                for (int k = 0; k < 3; k++) ls[k] = new Label();
                refInvokeTryCatch[i - 1] = ls;
                mv.visitTryCatchBlock(ls[0], ls[1], ls[2], "java/lang/reflect/InvocationTargetException");
            }
        }
    }
    // Output try-catch blocks
    for (final Object o : mn.tryCatchBlocks) {
        final TryCatchBlockNode tcb = (TryCatchBlockNode) o;
        if (// we allow catch of SuspendExecution only in methods annotated with @Suspendable and in lambda-generated ones.
        SUSPEND_EXECUTION_NAME.equals(tcb.type) && !hasAnnotation && !mn.name.startsWith(Classes.LAMBDA_METHOD_PREFIX))
            throw new UnableToInstrumentException("catch for SuspendExecution", className, mn.name, mn.desc);
        if (// we allow catch of SuspendExecution in method annotated with @Suspendable.
        handleProxyInvocations && UNDECLARED_THROWABLE_NAME.equals(tcb.type))
            throw new UnableToInstrumentException("catch for UndeclaredThrowableException", className, mn.name, mn.desc);
        // if (INTERRUPTED_EXCEPTION_NAME.equals(tcb.type))
        // throw new UnableToInstrumentException("catch for " + InterruptedException.class.getSimpleName(), className, mn.name, mn.desc);
        tcb.accept(mv);
    }
    // Output parameter annotations
    if (mn.visibleParameterAnnotations != null)
        dumpParameterAnnotations(mv, mn.visibleParameterAnnotations, true);
    if (mn.invisibleParameterAnnotations != null)
        dumpParameterAnnotations(mv, mn.invisibleParameterAnnotations, false);
    // Output method annotations
    if (mn.visibleAnnotations != null) {
        for (Object o : mn.visibleAnnotations) {
            AnnotationNode an = (AnnotationNode) o;
            an.accept(mv.visitAnnotation(an.desc, true));
        }
    }
    mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchAll, null);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, STACK_NAME, "getStack", "()L" + STACK_NAME + ";", false);
    mv.visitInsn(Opcodes.DUP);
    mv.visitVarInsn(Opcodes.ASTORE, lvarStack);
    // println(mv, "STACK: ", lvarStack);
    // dumpStack(mv);
    // DUAL
    mv.visitJumpInsn(Opcodes.IFNULL, lMethodStart);
    mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
    // we'll assume we have been resumed
    emitStoreResumed(mv, true);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "nextMethodEntry", "()I", false);
    mv.visitTableSwitchInsn(1, numCodeBlocks - 1, lMethodStart2, lMethodCalls);
    mv.visitLabel(lMethodStart2);
    // the following code handles the case of an instrumented method called not as part of a suspendable code path
    // isFirstInStack will return false in that case.
    mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "isFirstInStackOrPushed", "()Z", false);
    // if true
    mv.visitJumpInsn(Opcodes.IFNE, lMethodStart);
    // This will reset the fiber stack local if isFirstStack returns false.
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.visitVarInsn(Opcodes.ASTORE, lvarStack);
    mv.visitLabel(lMethodStart);
    // no, we have not been resumed
    emitStoreResumed(mv, false);
    dumpCodeBlock(mv, 0, 0);
    // Blocks leading to suspendable calls
    for (int i = 1; i < numCodeBlocks; i++) {
        final FrameInfo fi = codeBlocks[i];
        // Emit instrumented call
        final AbstractInsnNode min = mn.instructions.get(fi.endInstruction);
        final String owner = getMethodOwner(min), name = getMethodName(min), desc = getMethodDesc(min);
        if (isYieldMethod(owner, name)) {
            // special case - call to yield
            if (min.getOpcode() != Opcodes.INVOKESTATIC)
                throw new UnableToInstrumentException("invalid call to suspending method.", className, mn.name, mn.desc);
            final int numYieldArgs = TypeAnalyzer.getNumArguments(desc);
            final boolean yieldReturnsValue = (Type.getReturnType(desc) != Type.VOID_TYPE);
            // we preserve the arguments for the call to yield on the operand stack
            emitStoreState(mv, i, fi, numYieldArgs);
            // we have not been resumed
            emitStoreResumed(mv, false);
            // emitSuspendableCalled(mv);
            // we call the yield method
            min.accept(mv);
            if (yieldReturnsValue)
                // we ignore the returned value...
                mv.visitInsn(Opcodes.POP);
            // we resume AFTER the call
            mv.visitLabel(lMethodCalls[i - 1]);
            final Label afterPostRestore = new Label();
            mv.visitVarInsn(Opcodes.ILOAD, lvarResumed);
            mv.visitJumpInsn(Opcodes.IFEQ, afterPostRestore);
            emitPostRestore(mv);
            mv.visitLabel(afterPostRestore);
            emitRestoreState(mv, i, fi, numYieldArgs);
            if (yieldReturnsValue)
                // ... and replace the returned value with the value of resumed
                mv.visitVarInsn(Opcodes.ILOAD, lvarResumed);
            // See #211: if Fiber.park() is the last call before catch, ASM generates
            // empty handlers (start_pc = end_pc) that won't pass ASM's nor JVM's bytecode checker because of
            // exception_table's spec here: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.3
            mv.visitInsn(Opcodes.NOP);
            dumpCodeBlock(mv, i, 1);
        } else {
            final Label lbl = new Label();
            // DUAL
            mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
            mv.visitJumpInsn(Opcodes.IFNULL, lbl);
            // normal case - call to a suspendable method - resume before the call
            emitStoreState(mv, i, fi, 0);
            // we have not been resumed
            emitStoreResumed(mv, false);
            // emitPreemptionPoint(mv, PREEMPTION_CALL);
            mv.visitLabel(lMethodCalls[i - 1]);
            emitRestoreState(mv, i, fi, 0);
            // DUAL
            mv.visitLabel(lbl);
            if (isReflectInvocation(owner, name)) {
                // We catch the InvocationTargetException and unwrap it if it wraps a SuspendExecution exception.
                Label[] ls = refInvokeTryCatch[i - 1];
                final Label startTry = ls[0];
                final Label endTry = ls[1];
                final Label startCatch = ls[2];
                final Label endCatch = new Label();
                final Label notSuspendExecution = new Label();
                // mv.visitTryCatchBlock(startTry, endTry, startCatch, "java/lang/reflect/InvocationTargetException");
                // try {
                mv.visitLabel(startTry);
                // method.invoke()
                min.accept(mv);
                // save return value
                mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue);
                // }
                mv.visitLabel(endTry);
                mv.visitJumpInsn(Opcodes.GOTO, endCatch);
                // catch(InvocationTargetException ex) {
                mv.visitLabel(startCatch);
                mv.visitInsn(Opcodes.DUP);
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
                mv.visitTypeInsn(Opcodes.INSTANCEOF, SUSPEND_EXECUTION_NAME);
                mv.visitJumpInsn(Opcodes.IFEQ, notSuspendExecution);
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
                mv.visitLabel(notSuspendExecution);
                mv.visitInsn(Opcodes.ATHROW);
                mv.visitLabel(endCatch);
                // restore return value
                mv.visitVarInsn(Opcodes.ALOAD, lvarInvocationReturnValue);
                dumpCodeBlock(mv, i, 1);
            } else {
                // emitSuspendableCalled(mv);
                dumpCodeBlock(mv, i, 0);
            }
        }
    }
    // Emit catchall's catch section
    mv.visitLabel(lMethodEnd);
    if (handleProxyInvocations) {
        mv.visitLabel(lCatchUTE);
        mv.visitInsn(Opcodes.DUP);
        // println(mv, "CTCH: ");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
        // println(mv, "CAUSE: ");
        mv.visitTypeInsn(Opcodes.INSTANCEOF, SUSPEND_EXECUTION_NAME);
        mv.visitJumpInsn(Opcodes.IFEQ, lCatchAll);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;", false);
        mv.visitJumpInsn(Opcodes.GOTO, lCatchSEE);
    }
    mv.visitLabel(lCatchAll);
    emitPopMethod(mv);
    mv.visitLabel(lCatchSEE);
    // println(mv, "THROW: ");
    // rethrow shared between catchAll and catchSSE
    mv.visitInsn(Opcodes.ATHROW);
    if (mn.localVariables != null) {
        for (Object o : mn.localVariables) ((LocalVariableNode) o).accept(mv);
    }
    // Needed by ASM analysis
    mv.visitMaxs(mn.maxStack + ADD_OPERANDS, mn.maxLocals + NUM_LOCALS + additionalLocals);
    mv.visitEnd();
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) Label(org.objectweb.asm.Label) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) AnnotationNode(org.objectweb.asm.tree.AnnotationNode) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode)

Example 70 with AbstractInsnNode

use of org.objectweb.asm.tree.AbstractInsnNode in project quasar by puniverse.

the class InstrumentMethod method collectCodeBlocks.

private void collectCodeBlocks() {
    final int numIns = mn.instructions.size();
    codeBlocks[0] = FrameInfo.FIRST;
    for (int i = 0; i < numIns; i++) {
        final Frame f = frames[i];
        if (f != null) {
            // reachable ?
            final AbstractInsnNode in = mn.instructions.get(i);
            if (in.getType() == AbstractInsnNode.METHOD_INSN || in.getType() == AbstractInsnNode.INVOKE_DYNAMIC_INSN) {
                boolean susp = true;
                if (in.getType() == AbstractInsnNode.METHOD_INSN) {
                    final MethodInsnNode min = (MethodInsnNode) in;
                    int opcode = min.getOpcode();
                    if (isSyntheticAccess(min.owner, min.name))
                        db.log(LogLevel.DEBUG, "Synthetic accessor method call at instruction %d is assumed suspendable", i);
                    else if (isReflectInvocation(min.owner, min.name))
                        db.log(LogLevel.DEBUG, "Reflective method call at instruction %d is assumed suspendable", i);
                    else if (isMethodHandleInvocation(min.owner, min.name))
                        db.log(LogLevel.DEBUG, "MethodHandle invocation at instruction %d is assumed suspendable", i);
                    else if (isInvocationHandlerInvocation(min.owner, min.name))
                        db.log(LogLevel.DEBUG, "InvocationHandler invocation at instruction %d is assumed suspendable", i);
                    else {
                        SuspendableType st = db.isMethodSuspendable(min.owner, min.name, min.desc, opcode);
                        if (st == SuspendableType.NON_SUSPENDABLE) {
                            susp = false;
                        } else if (st == null) {
                            db.log(LogLevel.WARNING, "Method not found in class - assuming suspendable: %s#%s%s (at %s:%s#%s)", min.owner, min.name, min.desc, sourceName, className, mn.name);
                            susp = true;
                        } else if (st != SuspendableType.SUSPENDABLE_SUPER) {
                            db.log(LogLevel.DEBUG, "Method call at instruction %d to %s#%s%s is suspendable", i, min.owner, min.name, min.desc);
                        }
                        if (st == SuspendableType.SUSPENDABLE_SUPER) {
                            db.log(LogLevel.DEBUG, "Method call at instruction %d to %s#%s%s to suspendable-super (instrumentation for proxy support will be enabled)", i, min.owner, min.name, min.desc);
                            this.callsSuspendableSupers = true;
                        }
                    }
                } else if (in.getType() == AbstractInsnNode.INVOKE_DYNAMIC_INSN) {
                    // invoke dynamic
                    final InvokeDynamicInsnNode idin = (InvokeDynamicInsnNode) in;
                    if (idin.bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory")) {
                        // lambda
                        db.log(LogLevel.DEBUG, "Lambda at instruction %d", i);
                        susp = false;
                    } else
                        db.log(LogLevel.DEBUG, "InvokeDynamic Method call at instruction %d to is assumed suspendable", i);
                }
                if (susp) {
                    FrameInfo fi = addCodeBlock(f, i);
                    splitTryCatch(fi);
                } else if (in.getType() == AbstractInsnNode.METHOD_INSN) {
                    // not invokedynamic
                    // noinspection ConstantConditions
                    final MethodInsnNode min = (MethodInsnNode) in;
                    db.log(LogLevel.DEBUG, "Method call at instruction %d to %s#%s%s is not suspendable", i, min.owner, min.name, min.desc);
                    possiblyWarnAboutBlocking(min);
                }
            }
        }
    }
    addCodeBlock(null, numIns);
}
Also used : SuspendableType(co.paralleluniverse.fibers.instrument.MethodDatabase.SuspendableType) Frame(org.objectweb.asm.tree.analysis.Frame) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) InvokeDynamicInsnNode(org.objectweb.asm.tree.InvokeDynamicInsnNode) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode)

Aggregations

AbstractInsnNode (org.objectweb.asm.tree.AbstractInsnNode)185 MethodInsnNode (org.objectweb.asm.tree.MethodInsnNode)68 MethodNode (org.objectweb.asm.tree.MethodNode)54 InsnList (org.objectweb.asm.tree.InsnList)53 InsnNode (org.objectweb.asm.tree.InsnNode)41 VarInsnNode (org.objectweb.asm.tree.VarInsnNode)38 LdcInsnNode (org.objectweb.asm.tree.LdcInsnNode)37 FieldInsnNode (org.objectweb.asm.tree.FieldInsnNode)35 ClassNode (org.objectweb.asm.tree.ClassNode)33 LabelNode (org.objectweb.asm.tree.LabelNode)27 JumpInsnNode (org.objectweb.asm.tree.JumpInsnNode)26 Test (org.junit.Test)25 Label (org.objectweb.asm.Label)25 ClassReader (org.objectweb.asm.ClassReader)23 TypeInsnNode (org.objectweb.asm.tree.TypeInsnNode)23 HashSet (java.util.HashSet)16 Type (org.objectweb.asm.Type)15 Frame (org.objectweb.asm.tree.analysis.Frame)13 ArrayList (java.util.ArrayList)12 TryCatchBlockNode (org.objectweb.asm.tree.TryCatchBlockNode)11