Search in sources :

Example 1 with SSAVar

use of jadx.core.dex.instructions.args.SSAVar in project jadx by skylot.

the class LoopRegionVisitor method checkArrayForEach.

private static LoopType checkArrayForEach(MethodNode mth, InsnNode initInsn, InsnNode incrInsn, IfCondition condition) {
    if (!(incrInsn instanceof ArithNode)) {
        return null;
    }
    ArithNode arithNode = (ArithNode) incrInsn;
    if (arithNode.getOp() != ArithOp.ADD) {
        return null;
    }
    InsnArg lit = incrInsn.getArg(1);
    if (!lit.isLiteral() || ((LiteralArg) lit).getLiteral() != 1) {
        return null;
    }
    if (initInsn.getType() != InsnType.CONST || !initInsn.getArg(0).isLiteral() || ((LiteralArg) initInsn.getArg(0)).getLiteral() != 0) {
        return null;
    }
    InsnArg condArg = incrInsn.getArg(0);
    if (!condArg.isRegister()) {
        return null;
    }
    SSAVar sVar = ((RegisterArg) condArg).getSVar();
    List<RegisterArg> args = sVar.getUseList();
    if (args.size() != 3 || args.get(2) != condArg) {
        return null;
    }
    condArg = args.get(0);
    RegisterArg arrIndex = args.get(1);
    InsnNode arrGetInsn = arrIndex.getParentInsn();
    if (arrGetInsn == null || arrGetInsn.getType() != InsnType.AGET) {
        return null;
    }
    if (!condition.isCompare()) {
        return null;
    }
    Compare compare = condition.getCompare();
    if (compare.getOp() != IfOp.LT || compare.getA() != condArg) {
        return null;
    }
    InsnNode len;
    InsnArg bCondArg = compare.getB();
    if (bCondArg.isInsnWrap()) {
        len = ((InsnWrapArg) bCondArg).getWrapInsn();
    } else if (bCondArg.isRegister()) {
        len = ((RegisterArg) bCondArg).getAssignInsn();
    } else {
        return null;
    }
    if (len == null || len.getType() != InsnType.ARRAY_LENGTH) {
        return null;
    }
    InsnArg arrayArg = len.getArg(0);
    if (!arrayArg.equals(arrGetInsn.getArg(0))) {
        return null;
    }
    RegisterArg iterVar = arrGetInsn.getResult();
    if (iterVar == null) {
        return null;
    }
    // array for each loop confirmed
    len.add(AFlag.SKIP);
    arrGetInsn.add(AFlag.SKIP);
    InstructionRemover.unbindInsn(mth, len);
    // inline array variable
    CodeShrinker.shrinkMethod(mth);
    if (arrGetInsn.contains(AFlag.WRAPPED)) {
        InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, arrGetInsn);
        if (wrapArg != null && wrapArg.getParentInsn() != null) {
            wrapArg.getParentInsn().replaceArg(wrapArg, iterVar);
        } else {
            LOG.debug(" checkArrayForEach: Wrapped insn not found: {}, mth: {}", arrGetInsn, mth);
        }
    }
    return new ForEachLoop(iterVar, len.getArg(0));
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) SSAVar(jadx.core.dex.instructions.args.SSAVar) InsnArg(jadx.core.dex.instructions.args.InsnArg) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) Compare(jadx.core.dex.regions.conditions.Compare) ArithNode(jadx.core.dex.instructions.ArithNode) ForEachLoop(jadx.core.dex.regions.loops.ForEachLoop)

Example 2 with SSAVar

use of jadx.core.dex.instructions.args.SSAVar in project jadx by skylot.

the class LoopRegionVisitor method checkIterableForEach.

private static boolean checkIterableForEach(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
    List<RegisterArg> condArgs = condition.getRegisterArgs();
    if (condArgs.size() != 1) {
        return false;
    }
    RegisterArg iteratorArg = condArgs.get(0);
    SSAVar sVar = iteratorArg.getSVar();
    if (sVar == null || sVar.isUsedInPhi()) {
        return false;
    }
    List<RegisterArg> useList = sVar.getUseList();
    InsnNode assignInsn = iteratorArg.getAssignInsn();
    if (useList.size() != 2 || assignInsn == null || !checkInvoke(assignInsn, null, "iterator()Ljava/util/Iterator;", 0)) {
        return false;
    }
    InsnArg iterableArg = assignInsn.getArg(0);
    InsnNode hasNextCall = useList.get(0).getParentInsn();
    InsnNode nextCall = useList.get(1).getParentInsn();
    if (hasNextCall == null || nextCall == null || !checkInvoke(hasNextCall, "java.util.Iterator", "hasNext()Z", 0) || !checkInvoke(nextCall, "java.util.Iterator", "next()Ljava/lang/Object;", 0)) {
        return false;
    }
    List<InsnNode> toSkip = new LinkedList<InsnNode>();
    RegisterArg iterVar = nextCall.getResult();
    if (iterVar == null) {
        return false;
    }
    if (nextCall.contains(AFlag.WRAPPED)) {
        InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, nextCall);
        if (wrapArg != null && wrapArg.getParentInsn() != null) {
            InsnNode parentInsn = wrapArg.getParentInsn();
            if (parentInsn.getType() != InsnType.CHECK_CAST) {
                if (!fixIterableType(mth, iterableArg, iterVar)) {
                    return false;
                }
                parentInsn.replaceArg(wrapArg, iterVar);
            } else {
                iterVar = parentInsn.getResult();
                if (iterVar == null || !fixIterableType(mth, iterableArg, iterVar)) {
                    return false;
                }
                InsnArg castArg = BlockUtils.searchWrappedInsnParent(mth, parentInsn);
                if (castArg != null && castArg.getParentInsn() != null) {
                    castArg.getParentInsn().replaceArg(castArg, iterVar);
                } else {
                    // cast not inlined
                    toSkip.add(parentInsn);
                }
            }
        } else {
            LOG.warn(" checkIterableForEach: Wrapped insn not found: {}, mth: {}", nextCall, mth);
            return false;
        }
    } else {
        toSkip.add(nextCall);
    }
    assignInsn.add(AFlag.SKIP);
    for (InsnNode insnNode : toSkip) {
        insnNode.add(AFlag.SKIP);
    }
    loopRegion.setType(new ForEachLoop(iterVar, iterableArg));
    return true;
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) SSAVar(jadx.core.dex.instructions.args.SSAVar) InsnArg(jadx.core.dex.instructions.args.InsnArg) ForEachLoop(jadx.core.dex.regions.loops.ForEachLoop) LinkedList(java.util.LinkedList)

Example 3 with SSAVar

use of jadx.core.dex.instructions.args.SSAVar in project jadx by skylot.

the class ModVisitor method processMoveException.

private static void processMoveException(MethodNode mth, BlockNode block, InsnNode insn, InstructionRemover remover) {
    ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER);
    if (excHandlerAttr == null) {
        return;
    }
    ExceptionHandler excHandler = excHandlerAttr.getHandler();
    // result arg used both in this insn and exception handler,
    RegisterArg resArg = insn.getResult();
    ArgType type = excHandler.isCatchAll() ? ArgType.THROWABLE : excHandler.getCatchType().getType();
    String name = excHandler.isCatchAll() ? "th" : "e";
    if (resArg.getName() == null) {
        resArg.setName(name);
    }
    SSAVar sVar = insn.getResult().getSVar();
    if (sVar.getUseCount() == 0) {
        excHandler.setArg(new NamedArg(name, type));
        remover.add(insn);
    } else if (sVar.isUsedInPhi()) {
        // exception var moved to external variable => replace with 'move' insn
        InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
        moveInsn.setResult(insn.getResult());
        NamedArg namedArg = new NamedArg(name, type);
        moveInsn.addArg(namedArg);
        excHandler.setArg(namedArg);
        replaceInsn(block, 0, moveInsn);
    }
}
Also used : ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) ArgType(jadx.core.dex.instructions.args.ArgType) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) ExcHandlerAttr(jadx.core.dex.trycatch.ExcHandlerAttr) SSAVar(jadx.core.dex.instructions.args.SSAVar) NamedArg(jadx.core.dex.instructions.args.NamedArg)

Example 4 with SSAVar

use of jadx.core.dex.instructions.args.SSAVar in project jadx by skylot.

the class ModVisitor method processAnonymousConstructor.

private static void processAnonymousConstructor(MethodNode mth, ConstructorInsn co) {
    MethodInfo callMth = co.getCallMth();
    MethodNode callMthNode = mth.dex().resolveMethod(callMth);
    if (callMthNode == null) {
        return;
    }
    ClassNode classNode = callMthNode.getParentClass();
    ClassInfo classInfo = classNode.getClassInfo();
    ClassNode parentClass = mth.getParentClass();
    if (!classInfo.isInner() || !Character.isDigit(classInfo.getShortName().charAt(0)) || !parentClass.getInnerClasses().contains(classNode)) {
        return;
    }
    if (!classNode.getAccessFlags().isStatic() && (callMth.getArgsCount() == 0 || !callMth.getArgumentsTypes().get(0).equals(parentClass.getClassInfo().getType()))) {
        return;
    }
    // TODO: calculate this constructor and other constructor usage
    Map<InsnArg, FieldNode> argsMap = getArgsToFieldsMapping(callMthNode, co);
    if (argsMap.isEmpty()) {
        return;
    }
    // all checks passed
    classNode.add(AFlag.ANONYMOUS_CLASS);
    callMthNode.add(AFlag.DONT_GENERATE);
    for (Map.Entry<InsnArg, FieldNode> entry : argsMap.entrySet()) {
        FieldNode field = entry.getValue();
        if (field == null) {
            continue;
        }
        InsnArg arg = entry.getKey();
        field.addAttr(new FieldReplaceAttr(arg));
        field.add(AFlag.DONT_GENERATE);
        if (arg.isRegister()) {
            RegisterArg reg = (RegisterArg) arg;
            SSAVar sVar = reg.getSVar();
            if (sVar != null) {
                sVar.add(AFlag.FINAL);
                sVar.add(AFlag.DONT_INLINE);
            }
            reg.add(AFlag.SKIP_ARG);
        }
    }
}
Also used : ClassNode(jadx.core.dex.nodes.ClassNode) ConstClassNode(jadx.core.dex.instructions.ConstClassNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) MethodNode(jadx.core.dex.nodes.MethodNode) FieldNode(jadx.core.dex.nodes.FieldNode) SSAVar(jadx.core.dex.instructions.args.SSAVar) InsnArg(jadx.core.dex.instructions.args.InsnArg) FieldReplaceAttr(jadx.core.dex.attributes.nodes.FieldReplaceAttr) MethodInfo(jadx.core.dex.info.MethodInfo) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ClassInfo(jadx.core.dex.info.ClassInfo)

Example 5 with SSAVar

use of jadx.core.dex.instructions.args.SSAVar in project jadx by skylot.

the class ModVisitor method getParentInsnSkipMove.

private static InsnNode getParentInsnSkipMove(RegisterArg arg) {
    SSAVar sVar = arg.getSVar();
    if (sVar.getUseCount() != 1) {
        return null;
    }
    RegisterArg useArg = sVar.getUseList().get(0);
    InsnNode parentInsn = useArg.getParentInsn();
    if (parentInsn == null) {
        return null;
    }
    if (parentInsn.getType() == InsnType.MOVE) {
        return getParentInsnSkipMove(parentInsn.getResult());
    }
    return parentInsn;
}
Also used : IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) SSAVar(jadx.core.dex.instructions.args.SSAVar)

Aggregations

SSAVar (jadx.core.dex.instructions.args.SSAVar)28 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)22 InsnNode (jadx.core.dex.nodes.InsnNode)16 InsnArg (jadx.core.dex.instructions.args.InsnArg)9 PhiInsn (jadx.core.dex.instructions.PhiInsn)7 BlockNode (jadx.core.dex.nodes.BlockNode)7 ArgType (jadx.core.dex.instructions.args.ArgType)6 PhiListAttr (jadx.core.dex.attributes.nodes.PhiListAttr)5 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)5 ArrayList (java.util.ArrayList)5 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)4 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)3 FieldNode (jadx.core.dex.nodes.FieldNode)2 MethodNode (jadx.core.dex.nodes.MethodNode)2 ForEachLoop (jadx.core.dex.regions.loops.ForEachLoop)2 MethodParameters (jadx.core.dex.attributes.annotations.MethodParameters)1 FieldReplaceAttr (jadx.core.dex.attributes.nodes.FieldReplaceAttr)1 AccessInfo (jadx.core.dex.info.AccessInfo)1 ClassInfo (jadx.core.dex.info.ClassInfo)1 MethodInfo (jadx.core.dex.info.MethodInfo)1