Search in sources :

Example 1 with RegisterArg

use of jadx.core.dex.instructions.args.RegisterArg 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 RegisterArg

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

the class LoopRegionVisitor method checkForIndexedLoop.

/**
	 * Check for indexed loop.
	 */
private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
    InsnNode incrInsn = RegionUtils.getLastInsn(loopRegion);
    if (incrInsn == null) {
        return false;
    }
    RegisterArg incrArg = incrInsn.getResult();
    if (incrArg == null || incrArg.getSVar() == null || !incrArg.getSVar().isUsedInPhi()) {
        return false;
    }
    PhiInsn phiInsn = incrArg.getSVar().getUsedInPhi();
    if (phiInsn == null || phiInsn.getArgsCount() != 2 || !phiInsn.getArg(1).equals(incrArg) || incrArg.getSVar().getUseCount() != 1) {
        return false;
    }
    RegisterArg arg = phiInsn.getResult();
    List<RegisterArg> condArgs = condition.getRegisterArgs();
    if (!condArgs.contains(arg) || arg.getSVar().isUsedInPhi()) {
        return false;
    }
    RegisterArg initArg = phiInsn.getArg(0);
    InsnNode initInsn = initArg.getAssignInsn();
    if (initInsn == null || initArg.getSVar().getUseCount() != 1) {
        return false;
    }
    if (!usedOnlyInLoop(mth, loopRegion, arg)) {
        return false;
    }
    // can't make loop if argument from increment instruction is assign in loop
    List<RegisterArg> args = new LinkedList<RegisterArg>();
    incrInsn.getRegisterArgs(args);
    for (RegisterArg iArg : args) {
        if (assignOnlyInLoop(mth, loopRegion, iArg)) {
            return false;
        }
    }
    // all checks passed
    initInsn.add(AFlag.SKIP);
    incrInsn.add(AFlag.SKIP);
    LoopType arrForEach = checkArrayForEach(mth, initInsn, incrInsn, condition);
    if (arrForEach != null) {
        loopRegion.setType(arrForEach);
        return true;
    }
    loopRegion.setType(new ForLoop(initInsn, incrInsn));
    return true;
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) PhiInsn(jadx.core.dex.instructions.PhiInsn) ForLoop(jadx.core.dex.regions.loops.ForLoop) LoopType(jadx.core.dex.regions.loops.LoopType) LinkedList(java.util.LinkedList)

Example 3 with RegisterArg

use of jadx.core.dex.instructions.args.RegisterArg 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 4 with RegisterArg

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

the class ProcessVariables method visit.

@Override
public void visit(MethodNode mth) throws JadxException {
    if (mth.isNoCode()) {
        return;
    }
    final Map<Variable, Usage> usageMap = new LinkedHashMap<Variable, Usage>();
    for (RegisterArg arg : mth.getArguments(true)) {
        addToUsageMap(arg, usageMap);
    }
    // collect all variables usage
    IRegionVisitor collect = new CollectUsageRegionVisitor(usageMap);
    DepthRegionTraversal.traverse(mth, collect);
    // reduce assigns map
    List<RegisterArg> mthArgs = mth.getArguments(true);
    for (RegisterArg arg : mthArgs) {
        usageMap.remove(new Variable(arg));
    }
    Iterator<Entry<Variable, Usage>> umIt = usageMap.entrySet().iterator();
    while (umIt.hasNext()) {
        Entry<Variable, Usage> entry = umIt.next();
        Usage u = entry.getValue();
        // if no assigns => remove
        if (u.getAssigns().isEmpty()) {
            umIt.remove();
            continue;
        }
        // variable declared at 'catch' clause
        InsnNode parentInsn = u.getArg().getParentInsn();
        if (parentInsn == null || parentInsn.getType() == InsnType.MOVE_EXCEPTION) {
            umIt.remove();
        }
    }
    if (usageMap.isEmpty()) {
        return;
    }
    Map<IContainer, Integer> regionsOrder = new HashMap<IContainer, Integer>();
    calculateOrder(mth.getRegion(), regionsOrder, 0, true);
    for (Iterator<Entry<Variable, Usage>> it = usageMap.entrySet().iterator(); it.hasNext(); ) {
        Entry<Variable, Usage> entry = it.next();
        Usage u = entry.getValue();
        // check if variable can be declared at current assigns
        for (IRegion assignRegion : u.getAssigns()) {
            if (u.getArgRegion() == assignRegion && canDeclareInRegion(u, assignRegion, regionsOrder)) {
                if (declareAtAssign(u)) {
                    it.remove();
                    break;
                }
            }
        }
    }
    if (usageMap.isEmpty()) {
        return;
    }
    // apply
    for (Entry<Variable, Usage> entry : usageMap.entrySet()) {
        Usage u = entry.getValue();
        // find region which contain all usage regions
        Set<IRegion> set = u.getUseRegions();
        for (Iterator<IRegion> it = set.iterator(); it.hasNext(); ) {
            IRegion r = it.next();
            IRegion parent = r.getParent();
            if (parent != null && set.contains(parent)) {
                it.remove();
            }
        }
        IRegion region = null;
        if (!set.isEmpty()) {
            region = set.iterator().next();
        } else if (!u.getAssigns().isEmpty()) {
            region = u.getAssigns().iterator().next();
        }
        if (region == null) {
            continue;
        }
        IRegion parent = region;
        boolean declared = false;
        while (parent != null) {
            if (canDeclareInRegion(u, region, regionsOrder)) {
                declareVar(region, u.getArg());
                declared = true;
                break;
            }
            region = parent;
            parent = region.getParent();
        }
        if (!declared) {
            declareVar(mth.getRegion(), u.getArg());
        }
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) IRegion(jadx.core.dex.nodes.IRegion) LinkedHashMap(java.util.LinkedHashMap) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) Entry(java.util.Map.Entry) IContainer(jadx.core.dex.nodes.IContainer)

Example 5 with RegisterArg

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

the class ProcessVariables method declareAtAssign.

private static boolean declareAtAssign(Usage u) {
    RegisterArg arg = u.getArg();
    InsnNode parentInsn = arg.getParentInsn();
    if (!arg.equals(parentInsn.getResult())) {
        return false;
    }
    parentInsn.add(AFlag.DECLARE_VAR);
    return true;
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg)

Aggregations

RegisterArg (jadx.core.dex.instructions.args.RegisterArg)67 InsnNode (jadx.core.dex.nodes.InsnNode)39 InsnArg (jadx.core.dex.instructions.args.InsnArg)24 SSAVar (jadx.core.dex.instructions.args.SSAVar)22 BlockNode (jadx.core.dex.nodes.BlockNode)17 PhiInsn (jadx.core.dex.instructions.PhiInsn)11 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)10 ArgType (jadx.core.dex.instructions.args.ArgType)8 ArrayList (java.util.ArrayList)8 PhiListAttr (jadx.core.dex.attributes.nodes.PhiListAttr)6 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)6 MethodNode (jadx.core.dex.nodes.MethodNode)4 MethodInfo (jadx.core.dex.info.MethodInfo)3 ConstClassNode (jadx.core.dex.instructions.ConstClassNode)3 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)3 ConstructorInsn (jadx.core.dex.instructions.mods.ConstructorInsn)3 ClassNode (jadx.core.dex.nodes.ClassNode)3 FieldNode (jadx.core.dex.nodes.FieldNode)3 IContainer (jadx.core.dex.nodes.IContainer)3 ExceptionHandler (jadx.core.dex.trycatch.ExceptionHandler)3