Search in sources :

Example 6 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project dex2jar by pxb1988.

the class InvocationWeaver method wrapper.

public ClassVisitor wrapper(final ClassVisitor cv) {
    return new RemappingClassAdapter(cv, remapper) {

        Map<MtdInfo, MtdInfo> toCreate = new HashMap<MtdInfo, MtdInfo>();

        String clzName;

        private MtdInfo newMethodA(int opcode, MtdInfo t, MtdInfo mapTo) {
            MtdInfo n = toCreate.get(t);
            if (n != null) {
                return n;
            }
            n = new MtdInfo();
            n.owner = t.owner;
            n.name = buildMethodAName(t.name);
            boolean hasThis = opcode != INVOKESTATIC;
            if (hasThis) {
                Type[] args = Type.getArgumentTypes(t.desc);
                Type ret = Type.getReturnType(t.desc);
                List<Type> ts = new ArrayList<>(args.length + 1);
                ts.add(Type.getType(t.owner));
                ts.addAll(Arrays.asList(args));
                n.desc = Type.getMethodDescriptor(ret, ts.toArray(new Type[ts.size()]));
            } else {
                n.desc = t.desc;
            }
            toCreate.put(t, n);
            MethodVisitor mv = cv.visitMethod(ACC_SYNTHETIC | ACC_PRIVATE | ACC_STATIC, n.name, n.desc, null, null);
            mv.visitCode();
            genMethodACode(opcode, t, mapTo, mv, t);
            return n;
        }

        private void genMethodACode(int opcode, MtdInfo t, MtdInfo mapTo, MethodVisitor mv, MtdInfo src) {
            boolean hasThis = opcode != INVOKESTATIC;
            Type[] args = Type.getArgumentTypes(t.desc);
            Type ret = Type.getReturnType(t.desc);
            final int start;
            mv.visitTypeInsn(NEW, getCurrentInvocationName());
            mv.visitInsn(DUP);
            if (hasThis) {
                mv.visitVarInsn(ALOAD, 0);
                start = 1;
            } else {
                mv.visitInsn(ACONST_NULL);
                start = 0;
            }
            if (args.length == 0) {
                mv.visitInsn(ACONST_NULL);
            } else {
                mv.visitLdcInsn(args.length);
                mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
                for (int i = 0; i < args.length; i++) {
                    mv.visitInsn(DUP);
                    mv.visitLdcInsn(i);
                    mv.visitVarInsn(args[i].getOpcode(ILOAD), i + start);
                    box(args[i], mv);
                    mv.visitInsn(AASTORE);
                }
            }
            int nextIdx = callbacks.size();
            mv.visitLdcInsn(nextIdx);
            mv.visitMethodInsn(INVOKESPECIAL, getCurrentInvocationName(), "<init>", "(Ljava/lang/Object;[Ljava/lang/Object;I)V");
            mv.visitMethodInsn(INVOKESTATIC, toInternal(mapTo.owner), mapTo.name, mapTo.desc);
            unBox(ret, Type.getReturnType(mapTo.desc), mv);
            mv.visitInsn(ret.getOpcode(IRETURN));
            mv.visitMaxs(-1, -1);
            mv.visitEnd();
            Callback cb = new Callback();
            cb.idx = nextIdx;
            cb.callback = newMethodCallback(opcode, t);
            cb.target = src;
            cb.isSpecial = opcode == INVOKESPECIAL;
            cb.isStatic = opcode == INVOKESTATIC;
            callbacks.add(cb);
        }

        private MtdInfo newMethodCallback(int opcode, MtdInfo t) {
            MtdInfo n = new MtdInfo();
            n.owner = "L" + className + ";";
            n.name = buildCallbackMethodName(t.name);
            if (opcode == INVOKESPECIAL || opcode == INVOKESTATIC) {
                n.desc = "([Ljava/lang/Object;)Ljava/lang/Object;";
            } else {
                n.desc = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;";
            }
            MethodVisitor mv = cv.visitMethod(opcode == INVOKESPECIAL ? ACC_PUBLIC : ACC_PUBLIC | ACC_STATIC, n.name, n.desc, null, null);
            mv.visitCode();
            int start;
            if (opcode != INVOKESTATIC) {
                mv.visitVarInsn(ALOAD, 0);
                if (opcode != INVOKESPECIAL) {
                    mv.visitTypeInsn(CHECKCAST, toInternal(t.owner));
                }
                start = 1;
            } else {
                start = 0;
            }
            Type[] args = Type.getArgumentTypes(t.desc);
            for (int i = 0; i < args.length; i++) {
                mv.visitVarInsn(ALOAD, start);
                mv.visitLdcInsn(i);
                mv.visitInsn(AALOAD);
                unBox(args[i], OBJECT_TYPE, mv);
            }
            mv.visitMethodInsn(opcode, toInternal(t.owner), t.name, t.desc);
            Type ret = Type.getReturnType(t.desc);
            box(ret, mv);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(-1, -1);
            mv.visitEnd();
            return n;
        }

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            super.visit(version, access, name, signature, superName, interfaces);
            clzName = name;
        }

        public MethodVisitor visitMethod(int access, final String name, String desc, String signature, String[] exceptions) {
            final MethodVisitor superMv = superMethodVisitor(access, name, desc, signature, exceptions);
            final MtdInfo mapTo = findDefinedTargetMethod("L" + clzName + ";", name, desc);
            if (mapTo != null) {
                final MtdInfo t1 = new MtdInfo();
                t1.owner = "L" + clzName + ";";
                t1.name = buildMethodAName(name);
                t1.desc = desc;
                final MtdInfo t = t1;
                final MtdInfo src = new MtdInfo();
                src.owner = t.owner;
                src.name = name;
                src.desc = desc;
                return new MethodNode(Opcodes.ASM4, access, name, desc, signature, exceptions) {

                    @Override
                    public void visitEnd() {
                        InsnList instructions = this.instructions;
                        List<TryCatchBlockNode> tryCatchBlocks = this.tryCatchBlocks;
                        List<LocalVariableNode> localVariables = this.localVariables;
                        this.instructions = new InsnList();
                        this.tryCatchBlocks = new ArrayList<>();
                        this.localVariables = new ArrayList<>();
                        this.maxLocals = -1;
                        this.maxStack = -1;
                        accept(superMv);
                        int opcode;
                        if (Modifier.isStatic(access)) {
                            opcode = Opcodes.INVOKESTATIC;
                        } else {
                            opcode = Opcodes.INVOKEVIRTUAL;
                        }
                        genMethodACode(opcode, t, mapTo, superMv, src);
                        // make sure public
                        int newAccess = (access & ~(ACC_PRIVATE | ACC_PROTECTED)) | ACC_PUBLIC;
                        MethodVisitor rmv = wrap(superMethodVisitor(newAccess, t.name, desc, null, null));
                        if (rmv != null) {
                            rmv.visitCode();
                            int n, i;
                            n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
                            for (i = 0; i < n; ++i) {
                                tryCatchBlocks.get(i).accept(rmv);
                            }
                            instructions.accept(rmv);
                            n = localVariables == null ? 0 : localVariables.size();
                            for (i = 0; i < n; ++i) {
                                localVariables.get(i).accept(rmv);
                            }
                            rmv.visitMaxs(-1, -1);
                            rmv.visitEnd();
                        }
                    }
                };
            } else {
                return wrap(superMv);
            }
        }

        private MethodVisitor superMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) {
            return super.visitMethod(access, name, desc, signature, exceptions);
        }

        MethodVisitor wrap(MethodVisitor mv) {
            return mv == null ? null : new ReplaceMethodVisitor(mv);
        }

        class ReplaceMethodVisitor extends MethodVisitor {

            public ReplaceMethodVisitor(MethodVisitor mv) {
                super(Opcodes.ASM4, mv);
            }

            @Override
            public void visitMethodInsn(int opcode, String owner, String name, String desc) {
                MtdInfo mapTo = findTargetMethod("L" + owner + ";", name, desc);
                if (mapTo != null) {
                    boolean isStatic = opcode == INVOKESTATIC;
                    Type orgRet = Type.getReturnType(desc);
                    Type[] orgArgs = Type.getArgumentTypes(desc);
                    Type nRet = Type.getReturnType(mapTo.desc);
                    Type[] nArgs = Type.getArgumentTypes(mapTo.desc);
                    if (orgRet.getSort() != Type.VOID && nRet.getSort() == Type.VOID) {
                        throw new RuntimeException("can't cast " + nRet + " to " + orgRet);
                    }
                    if (nArgs.length == 1 && nArgs[0].getDescriptor().equals(invocationInterfaceDesc)) {
                        MtdInfo t = new MtdInfo();
                        t.owner = "L" + owner + ";";
                        t.name = name;
                        t.desc = desc;
                        MtdInfo n = newMethodA(opcode, t, mapTo);
                        super.visitMethodInsn(INVOKESTATIC, clzName, n.name, n.desc);
                    } else {
                        // checking for invalid replace
                        if (isStatic) {
                            if (!Arrays.deepEquals(orgArgs, nArgs)) {
                                throw new RuntimeException("arguments not equal: " + owner + "." + name + desc + " <> " + mapTo.owner + "." + mapTo.name + mapTo.desc);
                            }
                        } else {
                            if (nArgs.length != orgArgs.length + 1) {
                                throw new RuntimeException("arguments not equal: " + owner + "." + name + desc + " <> " + mapTo.owner + "." + mapTo.name + mapTo.desc);
                            }
                            if (orgArgs.length > 0) {
                                for (int i = 0; i < orgArgs.length; i++) {
                                    if (!orgArgs[i].equals(nArgs[i + 1])) {
                                        throw new RuntimeException("arguments not equal: " + owner + "." + name + desc + " <> " + mapTo.owner + "." + mapTo.name + mapTo.desc);
                                    }
                                }
                            }
                        }
                        // replace it!
                        super.visitMethodInsn(INVOKESTATIC, toInternal(mapTo.owner), mapTo.name, mapTo.desc);
                        unBox(orgRet, nRet, this.mv);
                    }
                } else {
                    super.visitMethodInsn(opcode, owner, name, desc);
                }
            }
        }
    };
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) InsnList(org.objectweb.asm.tree.InsnList) LocalVariableNode(org.objectweb.asm.tree.LocalVariableNode) MethodNode(org.objectweb.asm.tree.MethodNode) RemappingClassAdapter(org.objectweb.asm.commons.RemappingClassAdapter)

Example 7 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project dex2jar by pxb1988.

the class TestUtils method verify.

@SuppressWarnings("rawtypes")
public static void verify(final ClassReader cr, PrintWriter out) throws AnalyzerException, IllegalArgumentException, IllegalAccessException {
    ClassNode cn = new ClassNode();
    cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
    List methods = cn.methods;
    for (int i = 0; i < methods.size(); ++i) {
        MethodNode method = (MethodNode) methods.get(i);
        List tryCatchBlocks = method.tryCatchBlocks;
        for (int j = 0; j < tryCatchBlocks.size(); j++) {
            TryCatchBlockNode tcn = (TryCatchBlockNode) tryCatchBlocks.get(j);
            if (tcn.start.equals(tcn.end)) {
                throw new DexException("try/catch block %d in %s has same start(%s) and end(%s)", j, method.name, tcn.start.getLabel(), tcn.end.getLabel());
            }
        }
        BasicVerifier verifier = new BasicVerifier();
        Analyzer a = new Analyzer(verifier);
        try {
            a.analyze(cn.name, method);
        } catch (Exception e) {
            out.println(cr.getClassName() + "." + method.name + method.desc);
            printAnalyzerResult(method, a, out);
            e.printStackTrace(out);
            out.flush();
            throw new DexException("method " + method.name + " " + method.desc, e);
        }
    }
}
Also used : BasicVerifier(org.objectweb.asm.tree.analysis.BasicVerifier) ClassNode(org.objectweb.asm.tree.ClassNode) DexClassNode(com.googlecode.d2j.node.DexClassNode) TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) DexException(com.googlecode.d2j.DexException) DexMethodNode(com.googlecode.d2j.node.DexMethodNode) MethodNode(org.objectweb.asm.tree.MethodNode) CheckClassAdapter(org.objectweb.asm.util.CheckClassAdapter) List(java.util.List) ArrayList(java.util.ArrayList) Analyzer(org.objectweb.asm.tree.analysis.Analyzer) AnalyzerException(org.objectweb.asm.tree.analysis.AnalyzerException) DexException(com.googlecode.d2j.DexException) ZipException(java.util.zip.ZipException) ParseException(com.android.dx.cf.iface.ParseException)

Example 8 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode 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 9 with TryCatchBlockNode

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

the class InstrumentMethod method splitTryCatch.

@SuppressWarnings("unchecked")
private void splitTryCatch(FrameInfo fi) {
    for (int i = 0; i < mn.tryCatchBlocks.size(); i++) {
        TryCatchBlockNode tcb = (TryCatchBlockNode) mn.tryCatchBlocks.get(i);
        int start = getLabelIdx(tcb.start);
        int end = getLabelIdx(tcb.end);
        if (start <= fi.endInstruction && end >= fi.endInstruction) {
            db.log(LogLevel.DEBUG, "Splitting try-catch in %s, block %d call at instruction %d", mn.name, i, fi.endInstruction);
            // need to split try/catch around the suspendable call
            if (start == fi.endInstruction) {
                // Starts exactly at the suspendable call => just make it start after it
                tcb.start = fi.createAfterLabel();
            } else {
                if (end > fi.endInstruction) {
                    TryCatchBlockNode tcb2 = new TryCatchBlockNode(fi.createAfterLabel(), tcb.end, tcb.handler, tcb.type);
                    mn.tryCatchBlocks.add(i + 1, tcb2);
                }
                // Make it end before the suspendable call
                tcb.end = fi.createBeforeLabel();
            }
        }
    }
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode)

Example 10 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project jacoco by jacoco.

the class SynchronizedFilter method filter.

public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) {
    for (final TryCatchBlockNode tryCatch : methodNode.tryCatchBlocks) {
        if (tryCatch.type != null) {
            continue;
        }
        if (tryCatch.start == tryCatch.handler) {
            continue;
        }
        final AbstractInsnNode to = new Matcher(tryCatch.handler).match();
        if (to == null) {
            continue;
        }
        output.ignore(tryCatch.handler, to);
    }
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode)

Aggregations

TryCatchBlockNode (org.objectweb.asm.tree.TryCatchBlockNode)27 AbstractInsnNode (org.objectweb.asm.tree.AbstractInsnNode)11 InsnNode (org.objectweb.asm.tree.InsnNode)5 LabelNode (org.objectweb.asm.tree.LabelNode)5 MethodInsnNode (org.objectweb.asm.tree.MethodInsnNode)5 MethodNode (org.objectweb.asm.tree.MethodNode)5 Label (org.objectweb.asm.Label)4 LdcInsnNode (org.objectweb.asm.tree.LdcInsnNode)4 Frame (org.objectweb.asm.tree.analysis.Frame)4 ArrayList (java.util.ArrayList)3 Type (org.objectweb.asm.Type)3 FrameNode (org.objectweb.asm.tree.FrameNode)3 InsnList (org.objectweb.asm.tree.InsnList)3 IntInsnNode (org.objectweb.asm.tree.IntInsnNode)3 JumpInsnNode (org.objectweb.asm.tree.JumpInsnNode)3 HashSet (java.util.HashSet)2 List (java.util.List)2 Analyzer (org.objectweb.asm.tree.analysis.Analyzer)2 Textifier (org.objectweb.asm.util.Textifier)2 TraceMethodVisitor (org.objectweb.asm.util.TraceMethodVisitor)2