Search in sources :

Example 16 with Method

use of com.googlecode.d2j.Method in project dex2jar by pxb1988.

the class DexWeaver method genSwitchMethod.

private void genSwitchMethod(DexClassVisitor dcv, String typeNameDesc, String methodName, CB callback) {
    DexMethodVisitor dmv = dcv.visitMethod(DexConstants.ACC_PUBLIC, new Method(typeNameDesc, methodName, new String[0], "Ljava/lang/String;"));
    DexCodeVisitor code = dmv.visitCode();
    code.visitRegister(3);
    code.visitFieldStmt(Op.IGET, 0, 2, new Field(typeNameDesc, "idx", "I"));
    DexLabel[] labels = new DexLabel[callbacks.size()];
    Map<String, DexLabel> strMap = new TreeMap<>();
    for (int i = 0; i < labels.length; i++) {
        Callback cb = callbacks.get(i);
        String key = callback.getKey((Method) cb.target);
        DexLabel label = strMap.get(key);
        if (label == null) {
            label = new DexLabel();
            strMap.put(key, label);
        }
        labels[i] = label;
    }
    code.visitPackedSwitchStmt(Op.PACKED_SWITCH, 0, 0, labels);
    code.visitTypeStmt(Op.NEW_INSTANCE, 0, 0, "Ljava/lang/RuntimeException;");
    code.visitConstStmt(Op.CONST_STRING, 1, "invalid idx");
    code.visitMethodStmt(Op.INVOKE_DIRECT, new int[] { 0, 1 }, new Method("Ljava/lang/RuntimeException;", "<init>", new String[] { "Ljava/lang/String;" }, "V"));
    code.visitStmt1R(Op.THROW, 0);
    for (Map.Entry<String, DexLabel> e : strMap.entrySet()) {
        code.visitLabel(e.getValue());
        code.visitConstStmt(Op.CONST_STRING, 0, e.getKey());
        code.visitStmt1R(Op.RETURN_OBJECT, 0);
    }
    code.visitEnd();
    dmv.visitEnd();
}
Also used : Method(com.googlecode.d2j.Method) TreeMap(java.util.TreeMap) Field(com.googlecode.d2j.Field) DexCodeVisitor(com.googlecode.d2j.visitors.DexCodeVisitor) DexLabel(com.googlecode.d2j.DexLabel) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) Map(java.util.Map) DexMethodVisitor(com.googlecode.d2j.visitors.DexMethodVisitor)

Example 17 with Method

use of com.googlecode.d2j.Method in project dex2jar by pxb1988.

the class DexWeaver method wrap.

public DexClassVisitor wrap(final String classNameDesc, final DexClassVisitor dcv) {
    return dcv == null ? null : new DexClassVisitor(dcv) {

        Map<MtdInfo, Method> cache = new HashMap<>();

        @Override
        public DexMethodVisitor visitMethod(final int accessFlags, Method method) {
            final DexMethodVisitor dmv = superVisitDexMethod(accessFlags, method);
            final MtdInfo mapTo = findDefinedTargetMethod(method.getOwner(), method.getName(), method.getDesc());
            if (mapTo != null) {
                final Method t = new Method(method.getOwner(), buildMethodAName(method.getName()), method.getParameterTypes(), method.getReturnType());
                final Method src = method;
                return new DexMethodNode(accessFlags, method) {

                    @Override
                    public void visitEnd() {
                        super.visitEnd();
                        DexCodeNode code = this.codeNode;
                        this.codeNode = null;
                        accept(dmv);
                        Op opcode;
                        if (Modifier.isStatic(access)) {
                            opcode = Op.INVOKE_STATIC_RANGE;
                        } else {
                            opcode = Op.INVOKE_VIRTUAL_RANGE;
                        }
                        generateMtdACode(opcode, t, mapTo, dmv, src);
                        // make sure public
                        int newAccess = (access & ~(DexConstants.ACC_PRIVATE | DexConstants.ACC_PROTECTED)) | DexConstants.ACC_PUBLIC;
                        code.accept(wrap(superVisitDexMethod(newAccess, t), dcv));
                    }
                };
            } else {
                return wrap(dmv, dcv);
            }
        }

        private DexMethodVisitor wrap(DexMethodVisitor dmv, final DexClassVisitor classVisitor) {
            return dmv == null ? null : new DexMethodVisitor(dmv) {

                @Override
                public DexCodeVisitor visitCode() {
                    return wrap(super.visitCode(), classVisitor);
                }
            };
        }

        private DexCodeVisitor wrap(DexCodeVisitor dcv, final DexClassVisitor classVisitor) {
            return dcv == null ? null : new DexCodeVisitor(dcv) {

                @Override
                public void visitMethodStmt(Op op, int[] args, Method method) {
                    MtdInfo mapTo = findTargetMethod(method.getOwner(), method.getName(), method.getDesc());
                    if (mapTo != null) {
                        Method methodA = cache.get(buildKey(method.getOwner(), method.getName(), method.getDesc()));
                        if (methodA == null) {
                            if (isStatic(op)) {
                                methodA = new Method(classNameDesc, buildMethodAName(method.getName()), method.getParameterTypes(), method.getReturnType());
                            } else {
                                methodA = new Method(classNameDesc, buildMethodAName(method.getName()), join(method.getOwner(), method.getParameterTypes()), method.getReturnType());
                            }
                            DexMethodVisitor dmv = classVisitor.visitMethod(DexConstants.ACC_PRIVATE | DexConstants.ACC_STATIC, methodA);
                            generateMtdACode(op, method, mapTo, dmv, method);
                            dmv.visitEnd();
                            cache.put(buildKey(method.getOwner(), method.getName(), method.getDesc()), methodA);
                        }
                        super.visitMethodStmt(isRange(op) ? Op.INVOKE_STATIC_RANGE : Op.INVOKE_STATIC, args, methodA);
                    } else {
                        super.visitMethodStmt(op, args, method);
                    }
                }
            };
        }

        private void generateMtdACode(Op opcode, Method t, MtdInfo mapTo, DexMethodVisitor dmv, Method src) {
            DexCodeVisitor dcv = dmv.visitCode();
            int countArge = countArgs(t);
            boolean haveThis = haveThis(opcode);
            int registers = 4 + (haveThis ? 1 : 0) + countArge;
            dcv.visitRegister(registers);
            int argStart = 4;
            if (haveThis) {
                dcv.visitStmt2R(Op.MOVE_OBJECT, 0, argStart);
                argStart++;
            } else {
                dcv.visitConstStmt(Op.CONST_4, 0, 0);
            }
            if (t.getParameterTypes().length == 0) {
                dcv.visitConstStmt(Op.CONST_4, 1, 0);
            } else {
                dcv.visitConstStmt(Op.CONST, 1, t.getParameterTypes().length);
                dcv.visitTypeStmt(Op.NEW_ARRAY, 1, 1, "[Ljava/lang/Object;");
                for (int i = 0; i < t.getParameterTypes().length; i++) {
                    char type = t.getParameterTypes()[i].charAt(0);
                    dcv.visitConstStmt(Op.CONST, 2, i);
                    box(type, argStart, 3, dcv);
                    dcv.visitStmt3R(Op.APUT_OBJECT, 3, 1, 2);
                    if (type == 'J' || type == 'D') {
                        argStart += 2;
                    } else {
                        argStart += 1;
                    }
                }
            }
            int nextIdx = callbacks.size();
            dcv.visitConstStmt(Op.CONST, 2, nextIdx);
            String miTypeDesc = "L" + getCurrentInvocationName() + ";";
            dcv.visitTypeStmt(Op.NEW_INSTANCE, 3, 0, miTypeDesc);
            dcv.visitMethodStmt(Op.INVOKE_DIRECT, new int[] { 3, 0, 1, 2 }, new Method(miTypeDesc, "<init>", new String[] { "Ljava/lang/Object;", "[Ljava/lang/Object;", "I" }, "V"));
            Method call = build(mapTo);
            dcv.visitMethodStmt(Op.INVOKE_STATIC, new int[] { 3 }, call);
            if (!"V".equals(t.getReturnType())) {
                switch(call.getReturnType().charAt(0)) {
                    case '[':
                    case 'L':
                        dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, 0);
                        break;
                    case 'J':
                    case 'D':
                        dcv.visitStmt1R(Op.MOVE_RESULT_WIDE, 0);
                        break;
                    default:
                        dcv.visitStmt1R(Op.MOVE_RESULT, 0);
                        break;
                }
                unbox(t.getReturnType(), 0, dcv);
                switch(t.getReturnType().charAt(0)) {
                    case '[':
                    case 'L':
                        dcv.visitStmt1R(Op.RETURN_OBJECT, 0);
                        break;
                    case 'J':
                    case 'D':
                        dcv.visitStmt1R(Op.RETURN_WIDE, 0);
                        break;
                    default:
                        dcv.visitStmt1R(Op.RETURN, 0);
                        break;
                }
            } else {
                dcv.visitStmt0R(Op.RETURN_VOID);
            }
            Callback cb = new Callback();
            cb.idx = nextIdx;
            cb.callback = newMethodCallback(opcode, t);
            cb.target = src;
            cb.isSpecial = isSuper(opcode);
            cb.isStatic = isStatic(opcode);
            callbacks.add(cb);
        }

        private Method newMethodCallback(Op opcode, Method t) {
            boolean isStatic = !haveThis(opcode);
            boolean isSuper = isSuper(opcode);
            Method m;
            if (isSuper || isStatic) {
                m = new Method(t.getOwner(), buildCallbackMethodName(t.getName()), new String[] { "[Ljava/lang/Object;" }, "Ljava/lang/Object;");
            } else {
                m = new Method(t.getOwner(), buildCallbackMethodName(t.getName()), new String[] { "Ljava/lang/Object;", "[Ljava/lang/Object;" }, "Ljava/lang/Object;");
            }
            DexMethodVisitor dmv = superVisitDexMethod(DexConstants.ACC_PUBLIC | (isSuper ? 0 : DexConstants.ACC_STATIC), m);
            DexCodeVisitor dcv = dmv.visitCode();
            int totalRegs;
            int argStart;
            if (isStatic) {
                totalRegs = 1 + countArgs(t) + 1;
                argStart = totalRegs - 1;
            } else {
                totalRegs = 1 + countArgs(t) + 2;
                argStart = totalRegs - 2;
            }
            dcv.visitRegister(totalRegs);
            int[] args = new int[countArgs(t) + (isStatic ? 0 : 1)];
            int args_index = 0;
            int i = 1;
            if (!isStatic) {
                if (i != argStart) {
                    dcv.visitStmt2R(Op.MOVE_OBJECT, i, argStart);
                }
                if (!isSuper) {
                    dcv.visitTypeStmt(Op.CHECK_CAST, i, -1, t.getOwner());
                }
                args[args_index++] = i;
                i++;
                argStart++;
            }
            String[] parameterTypes = t.getParameterTypes();
            for (int i1 = 0; i1 < parameterTypes.length; i1++) {
                String argType = parameterTypes[i1];
                dcv.visitConstStmt(Op.CONST, 0, i1);
                dcv.visitStmt3R(Op.AGET_OBJECT, i, argStart, 0);
                unbox(argType, i, dcv);
                args[args_index++] = i;
                if (argType.charAt(0) == 'J' || argType.charAt(0) == 'D') {
                    args[args_index++] = i + 1;
                    i += 2;
                } else {
                    i += 1;
                }
            }
            dcv.visitMethodStmt(opcode, args, t);
            if ("V".equals(t.getReturnType())) {
                dcv.visitConstStmt(Op.CONST, 0, 0);
            } else {
                switch(t.getReturnType().charAt(0)) {
                    case '[':
                    case 'L':
                        dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, 0);
                        break;
                    case 'J':
                    case 'D':
                        dcv.visitStmt1R(Op.MOVE_RESULT_WIDE, 0);
                        break;
                    default:
                        dcv.visitStmt1R(Op.MOVE_RESULT, 0);
                        break;
                }
                box(t.getReturnType().charAt(0), 0, 0, dcv);
            }
            dcv.visitStmt1R(Op.RETURN_OBJECT, 0);
            return m;
        }

        private DexMethodVisitor superVisitDexMethod(int accessFlags, Method method) {
            return super.visitMethod(accessFlags, method);
        }
    };
}
Also used : Op(com.googlecode.d2j.reader.Op) HashMap(java.util.HashMap) Method(com.googlecode.d2j.Method) DexCodeNode(com.googlecode.d2j.node.DexCodeNode) DexMethodNode(com.googlecode.d2j.node.DexMethodNode) DexCodeVisitor(com.googlecode.d2j.visitors.DexCodeVisitor) DexClassVisitor(com.googlecode.d2j.visitors.DexClassVisitor) DexMethodVisitor(com.googlecode.d2j.visitors.DexMethodVisitor)

Example 18 with Method

use of com.googlecode.d2j.Method in project dex2jar by pxb1988.

the class DexWeaver method box.

private void box(char type, int from, int to, DexCodeVisitor dcv) {
    switch(type) {
        case 'L':
        case '[':
            dcv.visitStmt2R(Op.MOVE_OBJECT, from, to);
            break;
        case 'Z':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from }, new Method("Ljava/lang/Boolean;", "valueOf", new String[] { "Z" }, "Ljava/lang/Boolean;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
        case 'B':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from }, new Method("Ljava/lang/Byte;", "valueOf", new String[] { "B" }, "Ljava/lang/Byte;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
        case 'S':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from }, new Method("Ljava/lang/Short;", "valueOf", new String[] { "S" }, "Ljava/lang/Short;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
        case 'C':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from }, new Method("Ljava/lang/Character;", "valueOf", new String[] { "C" }, "Ljava/lang/Character;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
        case 'I':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from }, new Method("Ljava/lang/Integer;", "valueOf", new String[] { "I" }, "Ljava/lang/Integer;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
        case 'F':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from }, new Method("Ljava/lang/Float;", "valueOf", new String[] { "F" }, "Ljava/lang/Float;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
        case 'D':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from, from + 1 }, new Method("Ljava/lang/Double;", "valueOf", new String[] { "D" }, "Ljava/lang/Double;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
        case 'J':
            dcv.visitMethodStmt(Op.INVOKE_STATIC_RANGE, new int[] { from, from + 1 }, new Method("Ljava/lang/Long;", "valueOf", new String[] { "J" }, "Ljava/lang/Long;"));
            dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, to);
            break;
    }
}
Also used : Method(com.googlecode.d2j.Method)

Example 19 with Method

use of com.googlecode.d2j.Method in project dex2jar by pxb1988.

the class ArrayTypeTest method a120.

@Test
public static void a120(DexClassVisitor cv) {
    DexMethodVisitor mv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, new Method("La;", "b", new String[] {}, "V"));
    DexCodeVisitor code = mv.visitCode();
    code.visitRegister(3);
    code.visitConstStmt(CONST, 0, Integer.valueOf(0));
    code.visitMethodStmt(INVOKE_VIRTUAL, new int[] { 0 }, new Method("Ljava/lang/String;", "toString", new String[] {}, "Ljava/lang/String;"));
    code.visitConstStmt(CONST, 1, Integer.valueOf(0));
    code.visitStmt2R(ARRAY_LENGTH, 2, 1);
    code.visitStmt0R(RETURN_VOID);
    code.visitEnd();
    mv.visitEnd();
}
Also used : DexCodeVisitor(com.googlecode.d2j.visitors.DexCodeVisitor) Method(com.googlecode.d2j.Method) DexMethodVisitor(com.googlecode.d2j.visitors.DexMethodVisitor) Test(org.junit.Test)

Example 20 with Method

use of com.googlecode.d2j.Method in project dex2jar by pxb1988.

the class ArrayTypeTest method merge1.

@Test
public static void merge1(DexClassVisitor cv) {
    // obj = array
    DexMethodVisitor mv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, new Method("La;", "b", new String[] {}, "V"));
    DexCodeVisitor code = mv.visitCode();
    DexLabel L0 = new DexLabel();
    DexLabel L1 = new DexLabel();
    code.visitRegister(3);
    code.visitConstStmt(CONST, 0, 0);
    code.visitJumpStmt(GOTO, -1, -1, L1);
    code.visitLabel(L0);
    code.visitStmt2R(ARRAY_LENGTH, 1, 0);
    code.visitConstStmt(CONST, 1, 0);
    code.visitStmt3R(AGET, 2, 0, 1);
    code.visitStmt0R(RETURN_VOID);
    code.visitLabel(L1);
    code.visitConstStmt(CONST, 1, 1);
    code.visitTypeStmt(NEW_ARRAY, 0, 1, "[Ljava/security/cert/X509Certificate;");
    code.visitJumpStmt(GOTO, -1, -1, L0);
    code.visitEnd();
    mv.visitEnd();
}
Also used : DexCodeVisitor(com.googlecode.d2j.visitors.DexCodeVisitor) DexLabel(com.googlecode.d2j.DexLabel) Method(com.googlecode.d2j.Method) DexMethodVisitor(com.googlecode.d2j.visitors.DexMethodVisitor) Test(org.junit.Test)

Aggregations

Method (com.googlecode.d2j.Method)22 DexCodeVisitor (com.googlecode.d2j.visitors.DexCodeVisitor)18 DexMethodVisitor (com.googlecode.d2j.visitors.DexMethodVisitor)18 Test (org.junit.Test)13 DexLabel (com.googlecode.d2j.DexLabel)10 Field (com.googlecode.d2j.Field)9 DexClassVisitor (com.googlecode.d2j.visitors.DexClassVisitor)4 Op (com.googlecode.d2j.reader.Op)3 HashMap (java.util.HashMap)3 DexFileWriter (com.googlecode.d2j.dex.writer.DexFileWriter)2 DexFieldVisitor (com.googlecode.d2j.visitors.DexFieldVisitor)2 File (java.io.File)2 DexType (com.googlecode.d2j.DexType)1 DexCodeNode (com.googlecode.d2j.node.DexCodeNode)1 DexMethodNode (com.googlecode.d2j.node.DexMethodNode)1 DvmInterpreter (com.googlecode.d2j.node.analysis.DvmInterpreter)1 DexFileReader (com.googlecode.d2j.reader.DexFileReader)1 ASMifierFileV (com.googlecode.d2j.util.ASMifierFileV)1 DexAnnotationAble (com.googlecode.d2j.visitors.DexAnnotationAble)1 DexAnnotationVisitor (com.googlecode.d2j.visitors.DexAnnotationVisitor)1