Search in sources :

Example 1 with Op

use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.

the class AntlrSmaliUtil method acceptCode.

private static void acceptCode(SmaliParser.SMethodContext ctx, final M m, DexMethodVisitor dexMethodVisitor) {
    if (ctx == null || dexMethodVisitor == null) {
        return;
    }
    final DexCodeVisitor dexCodeVisitor = dexMethodVisitor.visitCode();
    if (dexCodeVisitor == null) {
        return;
    }
    final SmaliCodeVisitor scv = new SmaliCodeVisitor(dexCodeVisitor);
    final DexDebugVisitor dexDebugVisitor = scv.visitDebug();
    final List<SmaliParser.SInstructionContext> instructionContexts = ctx.sInstruction();
    final SmaliBaseVisitor v = new SmaliBaseVisitor() {

        @Override
        public Object visitFregisters(SmaliParser.FregistersContext ctx) {
            return null;
        }

        @Override
        public Object visitFlocals(SmaliParser.FlocalsContext ctx) {
            return null;
        }

        @Override
        public Object visitFline(SmaliParser.FlineContext ctx) {
            if (dexDebugVisitor != null) {
                DexLabel dexLabel = new DexLabel();
                scv.visitLabel(dexLabel);
                dexDebugVisitor.visitLineNumber(Utils.parseInt(ctx.line.getText()), dexLabel);
            }
            return null;
        }

        @Override
        public Object visitFend(SmaliParser.FendContext ctx) {
            if (dexDebugVisitor != null) {
                DexLabel dexLabel = new DexLabel();
                scv.visitLabel(dexLabel);
                int reg = m.pareReg(ctx.r.getText());
                dexDebugVisitor.visitEndLocal(reg, dexLabel);
            }
            return null;
        }

        @Override
        public Object visitFlocal(SmaliParser.FlocalContext ctx) {
            if (dexDebugVisitor != null) {
                DexLabel dexLabel = new DexLabel();
                scv.visitLabel(dexLabel);
                int reg = m.pareReg(ctx.r.getText());
                String name;
                String type;
                if (ctx.v1 != null) {
                    Field fld = parseFieldAndUnescape("Lt;", ctx.v1.getText());
                    name = fld.getName();
                    type = fld.getType();
                } else if (ctx.v2 != null) {
                    String txt = ctx.v2.getText();
                    int i = findString(txt, 1, txt.length(), '\"');
                    name = unescapeStr(txt.substring(0, i + 1));
                    type = unEscapeId(txt.substring(i + 2));
                } else {
                    if (ctx.name2 != null) {
                        name = unescapeStr(ctx.name2.getText());
                    } else {
                        name = unEscapeId(ctx.name1.getText());
                    }
                    type = unEscapeId(ctx.type.getText());
                }
                String sig = ctx.sig == null ? null : unescapeStr(ctx.sig.getText());
                dexDebugVisitor.visitStartLocal(reg, dexLabel, name, type, sig);
            }
            return null;
        }

        @Override
        public Object visitFrestart(SmaliParser.FrestartContext ctx) {
            if (dexDebugVisitor != null) {
                DexLabel dexLabel = new DexLabel();
                scv.visitLabel(dexLabel);
                int reg = m.pareReg(ctx.r.getText());
                dexDebugVisitor.visitRestartLocal(reg, dexLabel);
            }
            return null;
        }

        @Override
        public Object visitFprologue(SmaliParser.FprologueContext ctx) {
            if (dexDebugVisitor != null) {
                DexLabel dexLabel = new DexLabel();
                scv.visitLabel(dexLabel);
                dexDebugVisitor.visitPrologue(dexLabel);
            }
            return null;
        }

        Map<String, DexLabel> labelMap = new HashMap<>();

        @Override
        public Object visitSLabel(SmaliParser.SLabelContext ctx) {
            scv.visitLabel(getLabel(ctx.label.getText()));
            return null;
        }

        @Override
        public Object visitFspareswitch(SmaliParser.FspareswitchContext ctx) {
            List<TerminalNode> ints = ctx.INT();
            List<TerminalNode> ts = ctx.LABEL();
            int[] cases = new int[ts.size()];
            DexLabel[] labels = new DexLabel[ts.size()];
            for (int i = 0; i < ts.size(); i++) {
                cases[i] = parseInt(ints.get(i).getSymbol().getText());
                labels[i] = getLabel(ts.get(i).getSymbol().getText());
            }
            scv.dSparseSwitch(cases, labels);
            return null;
        }

        @Override
        public Object visitFarraydata(SmaliParser.FarraydataContext ctx) {
            int size = parseInt(ctx.size.getText());
            List<SmaliParser.SBaseValueContext> ts = ctx.sBaseValue();
            byte[] ps = new byte[ts.size()];
            for (int i = 0; i < ts.size(); i++) {
                ps[i] = ((Number) parseBaseValue(ts.get(i))).byteValue();
            }
            scv.dArrayData(size, ps);
            return null;
        }

        Op getOp(Token t) {
            return Utils.getOp(t.getText());
        }

        @Override
        public Object visitF0x(SmaliParser.F0xContext ctx) {
            scv.visitStmt0R(getOp(ctx.op));
            return null;
        }

        @Override
        public Object visitF0t(SmaliParser.F0tContext ctx) {
            scv.visitJumpStmt(getOp(ctx.op), 0, 0, getLabel(ctx.target.getText()));
            return null;
        }

        @Override
        public Object visitF1x(SmaliParser.F1xContext ctx) {
            scv.visitStmt1R(getOp(ctx.op), m.pareReg(ctx.r1.getText()));
            return null;
        }

        @Override
        public Object visitFconst(SmaliParser.FconstContext ctx) {
            Op op = getOp(ctx.op);
            int r = m.pareReg(ctx.r1.getText());
            Token cst = ctx.cst;
            switch(op) {
                case CONST_STRING:
                case CONST_STRING_JUMBO:
                    scv.visitConstStmt(op, r, unescapeStr(cst.getText()));
                    break;
                case CONST_CLASS:
                    scv.visitConstStmt(op, r, new DexType(unEscapeId(cst.getText())));
                    break;
                case CHECK_CAST:
                case NEW_INSTANCE:
                    scv.visitTypeStmt(op, r, 0, unEscapeId(cst.getText()));
                    break;
                case CONST_WIDE:
                    scv.visitConstStmt(op, r, cst.getType() == SmaliLexer.INT ? ((long) parseInt(cst.getText())) : parseLong(cst.getText()));
                    break;
                case CONST_WIDE_16:
                    {
                        long v;
                        if (cst.getType() == SmaliLexer.LONG) {
                            v = parseLong(cst.getText());
                        } else {
                            v = (short) parseInt(cst.getText());
                        }
                        scv.visitConstStmt(op, r, v);
                    }
                    break;
                case CONST_WIDE_32:
                    {
                        long v;
                        if (cst.getType() == SmaliLexer.LONG) {
                            v = parseLong(cst.getText());
                        } else {
                            v = parseInt(cst.getText());
                        }
                        scv.visitConstStmt(op, r, v);
                    }
                    break;
                case CONST_WIDE_HIGH16:
                    {
                        long v;
                        if (cst.getType() == SmaliLexer.LONG) {
                            v = parseLong(cst.getText());
                        } else {
                            v = (short) parseInt(cst.getText());
                            v <<= 48;
                        }
                        scv.visitConstStmt(op, r, v);
                    }
                    break;
                case CONST:
                case CONST_4:
                case CONST_16:
                    {
                        int v = parseInt(cst.getText());
                        scv.visitConstStmt(op, r, v);
                    }
                    break;
                case CONST_HIGH16:
                    {
                        int v = parseInt(cst.getText());
                        v <<= 16;
                        scv.visitConstStmt(op, r, v);
                    }
                    break;
                default:
                    throw new RuntimeException();
            }
            return null;
        }

        @Override
        public Object visitFf1c(SmaliParser.Ff1cContext ctx) {
            int r = m.pareReg(ctx.r1.getText());
            Field field = parseFieldAndUnescape(ctx.fld.getText());
            scv.visitFieldStmt(getOp(ctx.op), r, 0, field);
            return null;
        }

        @Override
        public Object visitFt2c(SmaliParser.Ft2cContext ctx) {
            int r1 = m.pareReg(ctx.r1.getText());
            int r2 = m.pareReg(ctx.r2.getText());
            scv.visitTypeStmt(getOp(ctx.op), r1, r2, unEscapeId(ctx.type.getText()));
            return null;
        }

        @Override
        public Object visitFf2c(SmaliParser.Ff2cContext ctx) {
            int r1 = m.pareReg(ctx.r1.getText());
            int r2 = m.pareReg(ctx.r2.getText());
            scv.visitFieldStmt(getOp(ctx.op), r1, r2, parseFieldAndUnescape(ctx.fld.getText()));
            return null;
        }

        @Override
        public Object visitF2x(SmaliParser.F2xContext ctx) {
            int r1 = m.pareReg(ctx.r1.getText());
            int r2 = m.pareReg(ctx.r2.getText());
            scv.visitStmt2R(getOp(ctx.op), r1, r2);
            return null;
        }

        @Override
        public Object visitF3x(SmaliParser.F3xContext ctx) {
            int r1 = m.pareReg(ctx.r1.getText());
            int r2 = m.pareReg(ctx.r2.getText());
            int r3 = m.pareReg(ctx.r3.getText());
            scv.visitStmt3R(getOp(ctx.op), r1, r2, r3);
            return null;
        }

        @Override
        public Object visitFt5c(SmaliParser.Ft5cContext ctx) {
            Op op = getOp(ctx.op);
            List<TerminalNode> ts = ctx.REGISTER();
            int[] rs = new int[ts.size()];
            for (int i = 0; i < ts.size(); i++) {
                rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
            }
            scv.visitFilledNewArrayStmt(op, rs, unEscapeId(ctx.type.getText()));
            return null;
        }

        @Override
        public Object visitFm5c(SmaliParser.Fm5cContext ctx) {
            Op op = getOp(ctx.op);
            List<TerminalNode> ts = ctx.REGISTER();
            int[] rs = new int[ts.size()];
            for (int i = 0; i < ts.size(); i++) {
                rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
            }
            scv.visitMethodStmt(op, rs, parseMethodAndUnescape(ctx.method.getText()));
            return null;
        }

        @Override
        public Object visitFmrc(SmaliParser.FmrcContext ctx) {
            if (ctx.rstart != null) {
                int start = m.pareReg(ctx.rstart.getText());
                int end = m.pareReg(ctx.rend.getText());
                int size = end - start + 1;
                int[] rs = new int[size];
                for (int i = 0; i < size; i++) {
                    rs[i] = start + i;
                }
                scv.visitMethodStmt(getOp(ctx.op), rs, parseMethodAndUnescape(ctx.method.getText()));
            } else {
                scv.visitMethodStmt(getOp(ctx.op), new int[0], parseMethodAndUnescape(ctx.method.getText()));
            }
            return null;
        }

        @Override
        public Object visitFtrc(SmaliParser.FtrcContext ctx) {
            if (ctx.rstart != null) {
                int start = m.pareReg(ctx.rstart.getText());
                int end = m.pareReg(ctx.rend.getText());
                int size = end - start + 1;
                int[] rs = new int[size];
                for (int i = 0; i < size; i++) {
                    rs[i] = start + i;
                }
                scv.visitFilledNewArrayStmt(getOp(ctx.op), rs, unEscapeId(ctx.type.getText()));
            } else {
                scv.visitFilledNewArrayStmt(getOp(ctx.op), new int[0], unEscapeId(ctx.type.getText()));
            }
            return null;
        }

        @Override
        public Object visitF31t(SmaliParser.F31tContext ctx) {
            scv.visitF31tStmt(getOp(ctx.op), m.pareReg(ctx.r1.getText()), getLabel(ctx.label.getText()));
            return null;
        }

        @Override
        public Object visitF1t(SmaliParser.F1tContext ctx) {
            scv.visitJumpStmt(getOp(ctx.op), m.pareReg(ctx.r1.getText()), 0, getLabel(ctx.label.getText()));
            return null;
        }

        @Override
        public Object visitF2t(SmaliParser.F2tContext ctx) {
            scv.visitJumpStmt(getOp(ctx.op), m.pareReg(ctx.r1.getText()), m.pareReg(ctx.r2.getText()), getLabel(ctx.label.getText()));
            return null;
        }

        @Override
        public Object visitF2sb(SmaliParser.F2sbContext ctx) {
            scv.visitStmt2R1N(getOp(ctx.op), m.pareReg(ctx.r1.getText()), m.pareReg(ctx.r2.getText()), parseInt(ctx.lit.getText()));
            return null;
        }

        @Override
        public Object visitFpackageswitch(SmaliParser.FpackageswitchContext ctx) {
            int start = parseInt(ctx.start.getText());
            List<TerminalNode> ts = ctx.LABEL();
            DexLabel[] labels = new DexLabel[ts.size()];
            for (int i = 0; i < ts.size(); i++) {
                labels[i] = getLabel(ts.get(i).getSymbol().getText());
            }
            scv.dPackedSwitch(start, labels);
            return null;
        }

        @Override
        public Object visitFcache(SmaliParser.FcacheContext ctx) {
            scv.visitTryCatch(getLabel(ctx.start.getText()), getLabel(ctx.end.getText()), new DexLabel[] { getLabel(ctx.handle.getText()) }, new String[] { unEscapeId(ctx.type.getText()) });
            return null;
        }

        @Override
        public Object visitFcacheall(SmaliParser.FcacheallContext ctx) {
            scv.visitTryCatch(getLabel(ctx.start.getText()), getLabel(ctx.end.getText()), new DexLabel[] { getLabel(ctx.handle.getText()) }, new String[] { null });
            return null;
        }

        DexLabel getLabel(String name) {
            DexLabel dexLabel = labelMap.get(name);
            if (dexLabel == null) {
                dexLabel = new DexLabel();
                labelMap.put(name, dexLabel);
            }
            return dexLabel;
        }

        @Override
        public Object visitFepiogue(SmaliParser.FepiogueContext ctx) {
            if (dexDebugVisitor != null) {
                DexLabel dexLabel = new DexLabel();
                scv.visitLabel(dexLabel);
                dexDebugVisitor.visitEpiogue(dexLabel);
            }
            return null;
        }
    };
    scv.visitRegister(m.total);
    if (dexDebugVisitor != null) {
        for (int i = 0; i < m.paramNames.length; i++) {
            String name = m.paramNames[i];
            if (name != null) {
                dexDebugVisitor.visitParameterName(i, name);
            }
        }
    }
    for (SmaliParser.SInstructionContext instructionContext : instructionContexts) {
        ParserRuleContext parserRuleContext = (ParserRuleContext) instructionContext.getChild(0);
        parserRuleContext.accept(v);
    }
    scv.visitEnd();
}
Also used : Op(com.googlecode.d2j.reader.Op) Token(org.antlr.v4.runtime.Token) SmaliBaseVisitor(com.googlecode.d2j.smali.antlr4.SmaliBaseVisitor) ParserRuleContext(org.antlr.v4.runtime.ParserRuleContext) HashMap(java.util.HashMap) Map(java.util.Map) SmaliParser(com.googlecode.d2j.smali.antlr4.SmaliParser) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode)

Example 2 with Op

use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.

the class BaksmaliDumper method baksmaliCode.

public void baksmaliCode(DexMethodNode methodNode, DexCodeNode codeNode, Out out) {
    final List<DexLabel> allLabel = new ArrayList<>();
    final Set<DexLabel> usedLabel = new HashSet<>();
    codeNode.accept(new DexCodeVisitor() {

        @Override
        public void visitJumpStmt(Op op, int a, int b, DexLabel label) {
            usedLabel.add(label);
        }

        @Override
        public void visitPackedSwitchStmt(Op op, int aA, int first_case, DexLabel[] labels) {
            usedLabel.addAll(Arrays.asList(labels));
        }

        @Override
        public void visitTryCatch(DexLabel start, DexLabel end, DexLabel[] handler, String[] type) {
            usedLabel.add(start);
            usedLabel.add(end);
            usedLabel.addAll(Arrays.asList(handler));
        }

        @Override
        public void visitLabel(DexLabel label) {
            allLabel.add(label);
        }

        @Override
        public void visitSparseSwitchStmt(Op op, int ra, int[] cases, DexLabel[] labels) {
            usedLabel.addAll(Arrays.asList(labels));
        }
    });
    Map<DexLabel, List<DexDebugNode.DexDebugOpNode>> debugLabelMap = new HashMap<>();
    if (codeNode.debugNode != null) {
        DexDebugNode debugNode = codeNode.debugNode;
        for (DexDebugNode.DexDebugOpNode opNode : debugNode.debugNodes) {
            List<DexDebugNode.DexDebugOpNode> list = debugLabelMap.get(opNode.label);
            if (list == null) {
                list = new ArrayList<>(3);
                debugLabelMap.put(opNode.label, list);
            }
            list.add(opNode);
        }
    }
    int nextLabelNumber = 0;
    for (DexLabel label : allLabel) {
        if (usedLabel.contains(label)) {
            label.displayName = "L" + nextLabelNumber++;
        }
    }
    int inRegs = Utils.methodIns(methodNode.method, (methodNode.access & ACC_STATIC) != 0);
    DexCodeVisitor dexCodeVisitor = new BaksmaliCodeDumper(out, useParameterRegisters, useLocals, nextLabelNumber, codeNode.totalRegister - inRegs, usedLabel, debugLabelMap);
    accept(out, codeNode, dexCodeVisitor);
    dexCodeVisitor.visitEnd();
}
Also used : Op(com.googlecode.d2j.reader.Op) DexCodeVisitor(com.googlecode.d2j.visitors.DexCodeVisitor)

Example 3 with Op

use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.

the class DexWeaverCmd method doCommandLine.

@Override
protected void doCommandLine() throws Exception {
    if (remainingArgs.length == 0) {
        throw new HelpException("no odex");
    }
    final Map<String, Method> map = new HashMap<>();
    for (String ln : Files.readAllLines(config, StandardCharsets.UTF_8)) {
        if (ln.startsWith("#") || ln.length() == 0) {
            continue;
        }
        String[] x = ln.split("=");
        map.put(x[0], parseMethod(x[1]));
    }
    DexFileWriter out = new DexFileWriter();
    DexFileVisitor fv = new DexFileVisitor(out) {

        @Override
        public DexClassVisitor visit(int access_flags, String className, String superClass, String[] interfaceNames) {
            DexClassVisitor dcv = super.visit(access_flags, className, superClass, interfaceNames);
            if (dcv != null) {
                return new DexClassVisitor(dcv) {

                    @Override
                    public DexMethodVisitor visitMethod(int accessFlags, Method method) {
                        DexMethodVisitor dmv = super.visitMethod(accessFlags, method);
                        if (dmv != null) {
                            return new DexMethodVisitor(dmv) {

                                @Override
                                public DexCodeVisitor visitCode() {
                                    DexCodeVisitor code = super.visitCode();
                                    if (code != null) {
                                        return new DexCodeVisitor(code) {

                                            @Override
                                            public void visitMethodStmt(Op op, int[] args, Method method) {
                                                Method replaceTo = map.get(method.toString());
                                                if (replaceTo != null) {
                                                    switch(op) {
                                                        case INVOKE_DIRECT:
                                                        case INVOKE_INTERFACE:
                                                        case INVOKE_STATIC:
                                                        case INVOKE_SUPER:
                                                        case INVOKE_VIRTUAL:
                                                            super.visitMethodStmt(Op.INVOKE_STATIC, args, replaceTo);
                                                            break;
                                                        case INVOKE_DIRECT_RANGE:
                                                        case INVOKE_INTERFACE_RANGE:
                                                        case INVOKE_STATIC_RANGE:
                                                        case INVOKE_SUPER_RANGE:
                                                        case INVOKE_VIRTUAL_RANGE:
                                                            super.visitMethodStmt(Op.INVOKE_STATIC_RANGE, args, replaceTo);
                                                            break;
                                                        default:
                                                    }
                                                } else {
                                                    super.visitMethodStmt(op, args, method);
                                                }
                                            }
                                        };
                                    }
                                    return code;
                                }
                            };
                        }
                        return dmv;
                    }
                };
            }
            return dcv;
        }

        @Override
        public void visitEnd() {
        }
    };
    for (String f : remainingArgs) {
        byte[] data = ZipUtil.readDex(new File(f).toPath());
        DexFileReader r = new DexFileReader(data);
        r.accept(fv);
    }
    if (stub != null) {
        byte[] data = ZipUtil.readDex(stub);
        DexFileReader r = new DexFileReader(data);
        r.accept(new DexFileVisitor(out) {

            @Override
            public void visitEnd() {
            }
        });
    }
    out.visitEnd();
    byte[] data = out.toByteArray();
    Files.write(output, data);
}
Also used : Op(com.googlecode.d2j.reader.Op) HashMap(java.util.HashMap) DexFileWriter(com.googlecode.d2j.dex.writer.DexFileWriter) DexFileReader(com.googlecode.d2j.reader.DexFileReader) Method(com.googlecode.d2j.Method) DexFileVisitor(com.googlecode.d2j.visitors.DexFileVisitor) DexCodeVisitor(com.googlecode.d2j.visitors.DexCodeVisitor) DexClassVisitor(com.googlecode.d2j.visitors.DexClassVisitor) File(java.io.File) DexMethodVisitor(com.googlecode.d2j.visitors.DexMethodVisitor)

Example 4 with Op

use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.

the class Dex2IRConverter method buildInterpreter.

private DvmInterpreter<DvmValue> buildInterpreter() {
    return new DvmInterpreter<DvmValue>() {

        DvmValue b(com.googlecode.dex2jar.ir.expr.Value value) {
            Local local = newLocal();
            emit(Stmts.nAssign(local, value));
            return new DvmValue(local);
        }

        @Override
        public DvmValue newOperation(DexStmtNode insn) {
            switch(insn.op) {
                case CONST:
                case CONST_16:
                case CONST_4:
                case CONST_HIGH16:
                    return b(nInt((Integer) ((ConstStmtNode) insn).value));
                case CONST_WIDE:
                case CONST_WIDE_16:
                case CONST_WIDE_32:
                case CONST_WIDE_HIGH16:
                    return b(nLong((Long) ((ConstStmtNode) insn).value));
                case CONST_CLASS:
                    return b(nType(((DexType) ((ConstStmtNode) insn).value).desc));
                case CONST_STRING:
                case CONST_STRING_JUMBO:
                    return b(nString((String) ((ConstStmtNode) insn).value));
                case SGET:
                case SGET_BOOLEAN:
                case SGET_BYTE:
                case SGET_CHAR:
                case SGET_OBJECT:
                case SGET_SHORT:
                case SGET_WIDE:
                    Field field = ((FieldStmtNode) insn).field;
                    return b(nStaticField(field.getOwner(), field.getName(), field.getType()));
                case NEW_INSTANCE:
                    return b(nNew(((TypeStmtNode) insn).type));
                default:
            }
            return null;
        }

        @Override
        public DvmValue copyOperation(DexStmtNode insn, DvmValue value) {
            if (value == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            return b(getLocal(value));
        }

        @Override
        public DvmValue unaryOperation(DexStmtNode insn, DvmValue value) {
            if (value == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            Local local = getLocal(value);
            switch(insn.op) {
                case NOT_INT:
                    return b(nNot(local, "I"));
                case NOT_LONG:
                    return b(nNot(local, "J"));
                case NEG_DOUBLE:
                    return b(nNeg(local, "D"));
                case NEG_FLOAT:
                    return b(nNeg(local, "F"));
                case NEG_INT:
                    return b(nNeg(local, "I"));
                case NEG_LONG:
                    return b(nNeg(local, "J"));
                case INT_TO_BYTE:
                    return b(nCast(local, "I", "B"));
                case INT_TO_CHAR:
                    return b(nCast(local, "I", "C"));
                case INT_TO_DOUBLE:
                    return b(nCast(local, "I", "D"));
                case INT_TO_FLOAT:
                    return b(nCast(local, "I", "F"));
                case INT_TO_LONG:
                    return b(nCast(local, "I", "J"));
                case INT_TO_SHORT:
                    return b(nCast(local, "I", "S"));
                case FLOAT_TO_DOUBLE:
                    return b(nCast(local, "F", "D"));
                case FLOAT_TO_INT:
                    return b(nCast(local, "F", "I"));
                case FLOAT_TO_LONG:
                    return b(nCast(local, "F", "J"));
                case DOUBLE_TO_FLOAT:
                    return b(nCast(local, "D", "F"));
                case DOUBLE_TO_INT:
                    return b(nCast(local, "D", "I"));
                case DOUBLE_TO_LONG:
                    return b(nCast(local, "D", "J"));
                case LONG_TO_DOUBLE:
                    return b(nCast(local, "J", "D"));
                case LONG_TO_FLOAT:
                    return b(nCast(local, "J", "F"));
                case LONG_TO_INT:
                    return b(nCast(local, "J", "I"));
                case ARRAY_LENGTH:
                    return b(nLength(local));
                case IF_EQZ:
                    emit(nIf(Exprs.nEq(local, nInt(0), TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GEZ:
                    emit(nIf(Exprs.nGe(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GTZ:
                    emit(nIf(Exprs.nGt(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LEZ:
                    emit(nIf(Exprs.nLe(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LTZ:
                    emit(nIf(Exprs.nLt(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_NEZ:
                    emit(nIf(Exprs.nNe(local, nInt(0), TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case PACKED_SWITCH:
                case SPARSE_SWITCH:
                    DexLabel[] labels = ((BaseSwitchStmtNode) insn).labels;
                    LabelStmt[] lss = new LabelStmt[labels.length];
                    for (int i = 0; i < labels.length; i++) {
                        lss[i] = getLabel(labels[i]);
                    }
                    LabelStmt d = new LabelStmt();
                    if (insn.op == Op.PACKED_SWITCH) {
                        emit(nTableSwitch(local, ((PackedSwitchStmtNode) insn).first_case, lss, d));
                    } else {
                        emit(nLookupSwitch(local, ((SparseSwitchStmtNode) insn).cases, lss, d));
                    }
                    emit(d);
                    return null;
                case SPUT:
                case SPUT_BOOLEAN:
                case SPUT_BYTE:
                case SPUT_CHAR:
                case SPUT_OBJECT:
                case SPUT_SHORT:
                case SPUT_WIDE:
                    {
                        Field field = ((FieldStmtNode) insn).field;
                        emit(nAssign(nStaticField(field.getOwner(), field.getName(), field.getType()), local));
                        return null;
                    }
                case IGET:
                case IGET_BOOLEAN:
                case IGET_BYTE:
                case IGET_CHAR:
                case IGET_OBJECT:
                case IGET_SHORT:
                case IGET_WIDE:
                    {
                        Field field = ((FieldStmtNode) insn).field;
                        return b(nField(local, field.getOwner(), field.getName(), field.getType()));
                    }
                case INSTANCE_OF:
                    return b(nInstanceOf(local, ((TypeStmtNode) insn).type));
                case NEW_ARRAY:
                    return b(nNewArray(((TypeStmtNode) insn).type.substring(1), local));
                case CHECK_CAST:
                    return b(nCheckCast(local, ((TypeStmtNode) insn).type));
                case MONITOR_ENTER:
                    emit(nLock(local));
                    return null;
                case MONITOR_EXIT:
                    emit(nUnLock(local));
                    return null;
                case THROW:
                    emit(nThrow(local));
                    return null;
                case ADD_INT_LIT16:
                case ADD_INT_LIT8:
                    return b(nAdd(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case RSUB_INT_LIT8:
                case //
                RSUB_INT:
                    return b(nSub(nInt(((Stmt2R1NNode) insn).content), local, "I"));
                case MUL_INT_LIT8:
                case MUL_INT_LIT16:
                    return b(nMul(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case DIV_INT_LIT16:
                case DIV_INT_LIT8:
                    return b(nDiv(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case REM_INT_LIT16:
                case REM_INT_LIT8:
                    return b(nRem(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case AND_INT_LIT16:
                case AND_INT_LIT8:
                    return b(nAnd(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
                case OR_INT_LIT16:
                case OR_INT_LIT8:
                    return b(nOr(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
                case XOR_INT_LIT16:
                case XOR_INT_LIT8:
                    return b(nXor(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
                case SHL_INT_LIT8:
                    return b(nShl(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case SHR_INT_LIT8:
                    return b(nShr(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case USHR_INT_LIT8:
                    return b(nUshr(local, nInt(((Stmt2R1NNode) insn).content), "I"));
                case FILL_ARRAY_DATA:
                    emit(nFillArrayData(local, nArrayValue(((FillArrayDataStmtNode) insn).array)));
                    return null;
            }
            throw new RuntimeException();
        }

        @Override
        public DvmValue binaryOperation(DexStmtNode insn, DvmValue value1, DvmValue value2) {
            if (value1 == null || value2 == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            Local local1 = getLocal(value1);
            Local local2 = getLocal(value2);
            switch(insn.op) {
                case AGET:
                    return b(nArray(local1, local2, TypeClass.IF.name));
                case AGET_BOOLEAN:
                    return b(nArray(local1, local2, "Z"));
                case AGET_BYTE:
                    return b(nArray(local1, local2, "B"));
                case AGET_CHAR:
                    return b(nArray(local1, local2, "C"));
                case AGET_OBJECT:
                    return b(nArray(local1, local2, "L"));
                case AGET_SHORT:
                    return b(nArray(local1, local2, "S"));
                case AGET_WIDE:
                    return b(nArray(local1, local2, TypeClass.JD.name));
                case CMP_LONG:
                    return b(nLCmp(local1, local2));
                case CMPG_DOUBLE:
                    return b(nDCmpg(local1, local2));
                case CMPG_FLOAT:
                    return b(nFCmpg(local1, local2));
                case CMPL_DOUBLE:
                    return b(nDCmpl(local1, local2));
                case CMPL_FLOAT:
                    return b(nFCmpl(local1, local2));
                case ADD_DOUBLE:
                    return b(nAdd(local1, local2, "D"));
                case ADD_FLOAT:
                    return b(nAdd(local1, local2, "F"));
                case ADD_INT:
                    return b(nAdd(local1, local2, "I"));
                case ADD_LONG:
                    return b(nAdd(local1, local2, "J"));
                case SUB_DOUBLE:
                    return b(nSub(local1, local2, "D"));
                case SUB_FLOAT:
                    return b(nSub(local1, local2, "F"));
                case SUB_INT:
                    return b(nSub(local1, local2, "I"));
                case SUB_LONG:
                    return b(nSub(local1, local2, "J"));
                case MUL_DOUBLE:
                    return b(nMul(local1, local2, "D"));
                case MUL_FLOAT:
                    return b(nMul(local1, local2, "F"));
                case MUL_INT:
                    return b(nMul(local1, local2, "I"));
                case MUL_LONG:
                    return b(nMul(local1, local2, "J"));
                case DIV_DOUBLE:
                    return b(nDiv(local1, local2, "D"));
                case DIV_FLOAT:
                    return b(nDiv(local1, local2, "F"));
                case DIV_INT:
                    return b(nDiv(local1, local2, "I"));
                case DIV_LONG:
                    return b(nDiv(local1, local2, "J"));
                case REM_DOUBLE:
                    return b(nRem(local1, local2, "D"));
                case REM_FLOAT:
                    return b(nRem(local1, local2, "F"));
                case REM_INT:
                    return b(nRem(local1, local2, "I"));
                case REM_LONG:
                    return b(nRem(local1, local2, "J"));
                case AND_INT:
                    return b(nAnd(local1, local2, TypeClass.ZI.name));
                case AND_LONG:
                    return b(nAnd(local1, local2, "J"));
                case OR_INT:
                    return b(nOr(local1, local2, TypeClass.ZI.name));
                case OR_LONG:
                    return b(nOr(local1, local2, "J"));
                case XOR_INT:
                    return b(nXor(local1, local2, TypeClass.ZI.name));
                case XOR_LONG:
                    return b(nXor(local1, local2, "J"));
                case SHL_INT:
                    return b(nShl(local1, local2, "I"));
                case SHL_LONG:
                    return b(nShl(local1, local2, "J"));
                case SHR_INT:
                    return b(nShr(local1, local2, "I"));
                case SHR_LONG:
                    return b(nShr(local1, local2, "J"));
                case USHR_INT:
                    return b(nUshr(local1, local2, "I"));
                case USHR_LONG:
                    return b(nUshr(local1, local2, "J"));
                case IF_EQ:
                    emit(nIf(Exprs.nEq(local1, local2, TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GE:
                    emit(nIf(Exprs.nGe(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_GT:
                    emit(nIf(Exprs.nGt(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LE:
                    emit(nIf(Exprs.nLe(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_LT:
                    emit(nIf(Exprs.nLt(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IF_NE:
                    emit(nIf(Exprs.nNe(local1, local2, TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
                    return null;
                case IPUT:
                case IPUT_BOOLEAN:
                case IPUT_BYTE:
                case IPUT_CHAR:
                case IPUT_OBJECT:
                case IPUT_SHORT:
                case IPUT_WIDE:
                    Field field = ((FieldStmtNode) insn).field;
                    emit(nAssign(nField(local1, field.getOwner(), field.getName(), field.getType()), local2));
                    return null;
                case ADD_DOUBLE_2ADDR:
                    return b(nAdd(local1, local2, "D"));
                case ADD_FLOAT_2ADDR:
                    return b(nAdd(local1, local2, "F"));
                case ADD_INT_2ADDR:
                    return b(nAdd(local1, local2, "I"));
                case ADD_LONG_2ADDR:
                    return b(nAdd(local1, local2, "J"));
                case SUB_DOUBLE_2ADDR:
                    return b(nSub(local1, local2, "D"));
                case SUB_FLOAT_2ADDR:
                    return b(nSub(local1, local2, "F"));
                case SUB_INT_2ADDR:
                    return b(nSub(local1, local2, "I"));
                case SUB_LONG_2ADDR:
                    return b(nSub(local1, local2, "J"));
                case MUL_DOUBLE_2ADDR:
                    return b(nMul(local1, local2, "D"));
                case MUL_FLOAT_2ADDR:
                    return b(nMul(local1, local2, "F"));
                case MUL_INT_2ADDR:
                    return b(nMul(local1, local2, "I"));
                case MUL_LONG_2ADDR:
                    return b(nMul(local1, local2, "J"));
                case DIV_DOUBLE_2ADDR:
                    return b(nDiv(local1, local2, "D"));
                case DIV_FLOAT_2ADDR:
                    return b(nDiv(local1, local2, "F"));
                case DIV_INT_2ADDR:
                    return b(nDiv(local1, local2, "I"));
                case DIV_LONG_2ADDR:
                    return b(nDiv(local1, local2, "J"));
                case REM_DOUBLE_2ADDR:
                    return b(nRem(local1, local2, "D"));
                case REM_FLOAT_2ADDR:
                    return b(nRem(local1, local2, "F"));
                case REM_INT_2ADDR:
                    return b(nRem(local1, local2, "I"));
                case REM_LONG_2ADDR:
                    return b(nRem(local1, local2, "J"));
                case AND_INT_2ADDR:
                    return b(nAnd(local1, local2, TypeClass.ZI.name));
                case AND_LONG_2ADDR:
                    return b(nAnd(local1, local2, "J"));
                case OR_INT_2ADDR:
                    return b(nOr(local1, local2, TypeClass.ZI.name));
                case OR_LONG_2ADDR:
                    return b(nOr(local1, local2, "J"));
                case XOR_INT_2ADDR:
                    return b(nXor(local1, local2, TypeClass.ZI.name));
                case XOR_LONG_2ADDR:
                    return b(nXor(local1, local2, "J"));
                case SHL_INT_2ADDR:
                    return b(nShl(local1, local2, "I"));
                case SHL_LONG_2ADDR:
                    return b(nShl(local1, local2, "J"));
                case SHR_INT_2ADDR:
                    return b(nShr(local1, local2, "I"));
                case SHR_LONG_2ADDR:
                    return b(nShr(local1, local2, "J"));
                case USHR_INT_2ADDR:
                    return b(nUshr(local1, local2, "I"));
                case USHR_LONG_2ADDR:
                    return b(nUshr(local1, local2, "J"));
            }
            throw new RuntimeException();
        }

        @Override
        public DvmValue ternaryOperation(DexStmtNode insn, DvmValue value1, DvmValue value2, DvmValue value3) {
            if (value1 == null || value2 == null || value3 == null) {
                emitNotFindOperand(insn);
                return b(nInt(0));
            }
            Local localArray = getLocal(value1);
            Local localIndex = getLocal(value2);
            Local localValue = getLocal(value3);
            switch(insn.op) {
                case APUT:
                    emit(nAssign(nArray(localArray, localIndex, TypeClass.IF.name), localValue));
                    break;
                case APUT_BOOLEAN:
                    emit(nAssign(nArray(localArray, localIndex, "Z"), localValue));
                    break;
                case APUT_BYTE:
                    emit(nAssign(nArray(localArray, localIndex, "B"), localValue));
                    break;
                case APUT_CHAR:
                    emit(nAssign(nArray(localArray, localIndex, "C"), localValue));
                    break;
                case APUT_OBJECT:
                    emit(nAssign(nArray(localArray, localIndex, "L"), localValue));
                    break;
                case APUT_SHORT:
                    emit(nAssign(nArray(localArray, localIndex, "S"), localValue));
                    break;
                case APUT_WIDE:
                    emit(nAssign(nArray(localArray, localIndex, TypeClass.JD.name), localValue));
                    break;
            }
            return null;
        }

        @Override
        public DvmValue naryOperation(DexStmtNode insn, List<? extends DvmValue> values) {
            for (DvmValue v : values) {
                if (v == null) {
                    emitNotFindOperand(insn);
                    return b(nInt(0));
                }
            }
            switch(insn.op) {
                case FILLED_NEW_ARRAY:
                case FILLED_NEW_ARRAY_RANGE:
                    DvmValue value = new DvmValue();
                    FilledNewArrayStmtNode filledNewArrayStmtNode = (FilledNewArrayStmtNode) insn;
                    String type = filledNewArrayStmtNode.type;
                    String elem = type.substring(1);
                    emit(nAssign(getLocal(value), nNewArray(elem, nInt(values.size()))));
                    for (int i = 0; i < values.size(); i++) {
                        emit(nAssign(nArray(getLocal(value), nInt(i), elem), getLocal(values.get(i))));
                    }
                    return value;
                default:
                    Op op = insn.op;
                    Method method = ((MethodStmtNode) insn).method;
                    Value[] vs = new Value[values.size()];
                    for (int i = 0; i < vs.length; i++) {
                        vs[i] = getLocal(values.get(i));
                    }
                    Value invoke = null;
                    switch(op) {
                        case INVOKE_VIRTUAL_RANGE:
                        case INVOKE_VIRTUAL:
                            invoke = nInvokeVirtual(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        case INVOKE_SUPER_RANGE:
                        case INVOKE_DIRECT_RANGE:
                        case INVOKE_SUPER:
                        case INVOKE_DIRECT:
                            invoke = nInvokeSpecial(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        case INVOKE_STATIC_RANGE:
                        case INVOKE_STATIC:
                            invoke = nInvokeStatic(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        case INVOKE_INTERFACE_RANGE:
                        case INVOKE_INTERFACE:
                            invoke = nInvokeInterface(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
                            break;
                        default:
                            throw new RuntimeException();
                    }
                    if ("V".equals(method.getReturnType())) {
                        emit(nVoidInvoke(invoke));
                        return null;
                    } else {
                        return b(invoke);
                    }
            }
        }

        void emitNotFindOperand(DexStmtNode insn) {
            String msg;
            switch(insn.op) {
                case MOVE_RESULT:
                case MOVE_RESULT_OBJECT:
                case MOVE_RESULT_WIDE:
                    msg = "can't get operand(s) for " + insn.op + ", wrong position ?";
                    break;
                default:
                    msg = "can't get operand(s) for " + insn.op + ", out-of-range or not initialized ?";
                    break;
            }
            System.err.println("WARN: " + msg);
            emit(nThrow(nInvokeNew(new Value[] { nString("d2j: " + msg) }, new String[] { "Ljava/lang/String;" }, "Ljava/lang/VerifyError;")));
        }

        @Override
        public void returnOperation(DexStmtNode insn, DvmValue value) {
            if (value == null) {
                emitNotFindOperand(insn);
                return;
            }
            emit(nReturn(getLocal(value)));
        }
    };
}
Also used : Op(com.googlecode.d2j.reader.Op) Field(com.googlecode.d2j.Field) DvmInterpreter(com.googlecode.d2j.node.analysis.DvmInterpreter) DexType(com.googlecode.d2j.DexType) Local(com.googlecode.dex2jar.ir.expr.Local) IrMethod(com.googlecode.dex2jar.ir.IrMethod) Method(com.googlecode.d2j.Method) Value(com.googlecode.dex2jar.ir.expr.Value) DexLabel(com.googlecode.d2j.DexLabel)

Example 5 with Op

use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.

the class DexFix method fixStaticFinalFieldValue.

/**
     * init value to default if the field is static and final, and the field is not init in clinit method
     *
     * erase the default value if the field is init in clinit method
     * 
     * @param classNode
     */
public static void fixStaticFinalFieldValue(final DexClassNode classNode) {
    if (classNode.fields == null) {
        return;
    }
    final Map<String, DexFieldNode> fs = new HashMap<>();
    final Map<String, DexFieldNode> shouldNotBeAssigned = new HashMap<>();
    for (DexFieldNode fn : classNode.fields) {
        if ((fn.access & ACC_STATIC_FINAL) == ACC_STATIC_FINAL) {
            if (fn.cst == null) {
                char t = fn.field.getType().charAt(0);
                if (t == 'L' || t == '[') {
                    // ignore Object
                    continue;
                }
                fs.put(fn.field.getName() + ":" + fn.field.getType(), fn);
            } else if (isPrimitiveZero(fn.field.getType(), fn.cst)) {
                shouldNotBeAssigned.put(fn.field.getName() + ":" + fn.field.getType(), fn);
            }
        }
    }
    if (fs.isEmpty() && shouldNotBeAssigned.isEmpty()) {
        return;
    }
    DexMethodNode node = null;
    if (classNode.methods != null) {
        for (DexMethodNode mn : classNode.methods) {
            if (mn.method.getName().equals("<clinit>")) {
                node = mn;
                break;
            }
        }
    }
    if (node != null) {
        if (node.codeNode != null) {
            node.codeNode.accept(new DexCodeVisitor() {

                @Override
                public void visitFieldStmt(Op op, int a, int b, Field field) {
                    switch(op) {
                        case SPUT:
                        case SPUT_BOOLEAN:
                        case SPUT_BYTE:
                        case SPUT_CHAR:
                        case SPUT_OBJECT:
                        case SPUT_SHORT:
                        case SPUT_WIDE:
                            if (field.getOwner().equals(classNode.className)) {
                                String key = field.getName() + ":" + field.getType();
                                fs.remove(key);
                                DexFieldNode dn = shouldNotBeAssigned.get(key);
                                if (dn != null) {
                                    //System.out.println(field.getName() + ":" + field.getType());
                                    dn.cst = null;
                                }
                            }
                            break;
                        default:
                            // ignored
                            break;
                    }
                }
            });
        } else {
            // has init but no code
            return;
        }
    }
    for (DexFieldNode fn : fs.values()) {
        fn.cst = getDefaultValueOfType(fn.field.getType().charAt(0));
    }
}
Also used : Op(com.googlecode.d2j.reader.Op) Field(com.googlecode.d2j.Field) HashMap(java.util.HashMap) DexFieldNode(com.googlecode.d2j.node.DexFieldNode) DexMethodNode(com.googlecode.d2j.node.DexMethodNode) DexCodeVisitor(com.googlecode.d2j.visitors.DexCodeVisitor)

Aggregations

Op (com.googlecode.d2j.reader.Op)8 DexCodeVisitor (com.googlecode.d2j.visitors.DexCodeVisitor)4 HashMap (java.util.HashMap)4 DexLabel (com.googlecode.d2j.DexLabel)3 Method (com.googlecode.d2j.Method)3 Field (com.googlecode.d2j.Field)2 DexMethodNode (com.googlecode.d2j.node.DexMethodNode)2 DexClassVisitor (com.googlecode.d2j.visitors.DexClassVisitor)2 DexMethodVisitor (com.googlecode.d2j.visitors.DexMethodVisitor)2 Local (com.googlecode.dex2jar.ir.expr.Local)2 DexType (com.googlecode.d2j.DexType)1 DexFileWriter (com.googlecode.d2j.dex.writer.DexFileWriter)1 DexCodeNode (com.googlecode.d2j.node.DexCodeNode)1 DexFieldNode (com.googlecode.d2j.node.DexFieldNode)1 TryCatchNode (com.googlecode.d2j.node.TryCatchNode)1 DvmInterpreter (com.googlecode.d2j.node.analysis.DvmInterpreter)1 DexFileReader (com.googlecode.d2j.reader.DexFileReader)1 SmaliBaseVisitor (com.googlecode.d2j.smali.antlr4.SmaliBaseVisitor)1 SmaliParser (com.googlecode.d2j.smali.antlr4.SmaliParser)1 DexFileVisitor (com.googlecode.d2j.visitors.DexFileVisitor)1