Search in sources :

Example 1 with InsnList

use of org.objectweb.asm.tree.InsnList in project pinpoint by naver.

the class ASMMethodNodeAdapter method addBeforeInterceptor.

public void addBeforeInterceptor(final int interceptorId, final InterceptorDefinition interceptorDefinition, final int apiId) {
    initInterceptorLocalVariables(interceptorId, interceptorDefinition, apiId);
    final InsnList instructions = new InsnList();
    this.methodVariables.loadInterceptorLocalVariables(instructions, interceptorDefinition, false);
    final String description = Type.getMethodDescriptor(interceptorDefinition.getBeforeMethod());
    instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, Type.getInternalName(interceptorDefinition.getInterceptorBaseClass()), "before", description, true));
    this.methodNode.instructions.insertBefore(this.methodVariables.getEnterInsnNode(), instructions);
}
Also used : MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) InsnList(org.objectweb.asm.tree.InsnList)

Example 2 with InsnList

use of org.objectweb.asm.tree.InsnList in project pinpoint by naver.

the class ASMMethodNodeAdapter method addAfterInterceptor.

public void addAfterInterceptor(final int interceptorId, final InterceptorDefinition interceptorDefinition, final int apiId) {
    initInterceptorLocalVariables(interceptorId, interceptorDefinition, apiId);
    // add try catch block.
    final ASMTryCatch tryCatch = new ASMTryCatch(this.methodNode);
    this.methodNode.instructions.insertBefore(this.methodVariables.getEnterInsnNode(), tryCatch.getStartLabelNode());
    this.methodNode.instructions.insert(this.methodVariables.getExitInsnNode(), tryCatch.getEndLabelNode());
    // find return.
    AbstractInsnNode insnNode = this.methodNode.instructions.getFirst();
    while (insnNode != null) {
        final int opcode = insnNode.getOpcode();
        if (this.methodVariables.isReturnCode(opcode)) {
            final InsnList instructions = new InsnList();
            this.methodVariables.storeResultVar(instructions, opcode);
            invokeAfterInterceptor(instructions, interceptorDefinition, false);
            this.methodNode.instructions.insertBefore(insnNode, instructions);
        }
        insnNode = insnNode.getNext();
    }
    // try catch handler.
    InsnList instructions = new InsnList();
    this.methodVariables.storeThrowableVar(instructions);
    invokeAfterInterceptor(instructions, interceptorDefinition, true);
    // throw exception.
    this.methodVariables.loadInterceptorThrowVar(instructions);
    this.methodNode.instructions.insert(tryCatch.getEndLabelNode(), instructions);
    tryCatch.sort();
}
Also used : AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) InsnList(org.objectweb.asm.tree.InsnList)

Example 3 with InsnList

use of org.objectweb.asm.tree.InsnList in project pinpoint by naver.

the class ASMClassNodeAdapter method addSetterMethod.

public void addSetterMethod(final String methodName, final ASMFieldNodeAdapter fieldNode) {
    if (methodName == null || fieldNode == null) {
        throw new IllegalArgumentException("method name or fieldNode annotation must not be null.");
    }
    // void is V.
    final String desc = "(" + fieldNode.getDesc() + ")V";
    final MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC, methodName, desc, null, null);
    if (methodNode.instructions == null) {
        methodNode.instructions = new InsnList();
    }
    final InsnList instructions = methodNode.instructions;
    // load this.
    instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
    final Type type = Type.getType(fieldNode.getDesc());
    // put field.
    instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), 1));
    instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, fieldNode.getName(), fieldNode.getDesc()));
    // return.
    instructions.add(new InsnNode(Opcodes.RETURN));
    if (this.classNode.methods == null) {
        this.classNode.methods = new ArrayList<MethodNode>();
    }
    this.classNode.methods.add(methodNode);
}
Also used : FieldInsnNode(org.objectweb.asm.tree.FieldInsnNode) VarInsnNode(org.objectweb.asm.tree.VarInsnNode) InsnNode(org.objectweb.asm.tree.InsnNode) Type(org.objectweb.asm.Type) MethodNode(org.objectweb.asm.tree.MethodNode) FieldInsnNode(org.objectweb.asm.tree.FieldInsnNode) InsnList(org.objectweb.asm.tree.InsnList) VarInsnNode(org.objectweb.asm.tree.VarInsnNode)

Example 4 with InsnList

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

use of org.objectweb.asm.tree.InsnList in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class SpecificMethodNodeTransformer method instructionsInserter.

public static SpecificMethodNodeTransformer instructionsInserter(String target, int priority, Function<AbstractInsnNode, Pair<InsnList, Boolean>> inserter) {
    return instructionsTransformer(priority, target, instructions -> {
        for (AbstractInsnNode node : instructions.toArray()) {
            Pair<InsnList, Boolean> pair = inserter.apply(node);
            if (pair != null)
                if (pair.getRight())
                    instructions.insertBefore(node, pair.getLeft());
                else
                    instructions.insert(node, pair.getLeft());
        }
    });
}
Also used : AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) InsnList(org.objectweb.asm.tree.InsnList)

Aggregations

InsnList (org.objectweb.asm.tree.InsnList)11 AbstractInsnNode (org.objectweb.asm.tree.AbstractInsnNode)5 MethodNode (org.objectweb.asm.tree.MethodNode)4 InsnNode (org.objectweb.asm.tree.InsnNode)3 MethodInsnNode (org.objectweb.asm.tree.MethodInsnNode)3 VarInsnNode (org.objectweb.asm.tree.VarInsnNode)3 Type (org.objectweb.asm.Type)2 FieldInsnNode (org.objectweb.asm.tree.FieldInsnNode)2 JumpInsnNode (org.objectweb.asm.tree.JumpInsnNode)2 LabelNode (org.objectweb.asm.tree.LabelNode)2 Field (java.lang.reflect.Field)1 HashMap (java.util.HashMap)1 RemappingClassAdapter (org.objectweb.asm.commons.RemappingClassAdapter)1 ClassNode (org.objectweb.asm.tree.ClassNode)1 LineNumberNode (org.objectweb.asm.tree.LineNumberNode)1 LocalVariableNode (org.objectweb.asm.tree.LocalVariableNode)1 TryCatchBlockNode (org.objectweb.asm.tree.TryCatchBlockNode)1 TypeInsnNode (org.objectweb.asm.tree.TypeInsnNode)1 Analyzer (org.objectweb.asm.tree.analysis.Analyzer)1 Frame (org.objectweb.asm.tree.analysis.Frame)1