Search in sources :

Example 1 with PhiInsn

use of jadx.core.dex.instructions.PhiInsn 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 2 with PhiInsn

use of jadx.core.dex.instructions.PhiInsn in project jadx by skylot.

the class TernaryMod method checkLineStats.

/**
	 * Return 'true' if there are several args with same source lines
	 */
private static boolean checkLineStats(InsnNode t, InsnNode e) {
    if (t.getResult() == null || e.getResult() == null) {
        return false;
    }
    PhiInsn tPhi = t.getResult().getSVar().getUsedInPhi();
    PhiInsn ePhi = e.getResult().getSVar().getUsedInPhi();
    if (tPhi == null || ePhi == null || tPhi != ePhi) {
        return false;
    }
    Map<Integer, Integer> map = new HashMap<Integer, Integer>(tPhi.getArgsCount());
    for (InsnArg arg : tPhi.getArguments()) {
        if (!arg.isRegister()) {
            continue;
        }
        InsnNode assignInsn = ((RegisterArg) arg).getAssignInsn();
        if (assignInsn == null) {
            continue;
        }
        int sourceLine = assignInsn.getSourceLine();
        if (sourceLine != 0) {
            Integer count = map.get(sourceLine);
            if (count != null) {
                map.put(sourceLine, count + 1);
            } else {
                map.put(sourceLine, 1);
            }
        }
    }
    for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
        if (entry.getValue() >= 2) {
            return true;
        }
    }
    return false;
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) PhiInsn(jadx.core.dex.instructions.PhiInsn) HashMap(java.util.HashMap) InsnArg(jadx.core.dex.instructions.args.InsnArg) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with PhiInsn

use of jadx.core.dex.instructions.PhiInsn in project jadx by skylot.

the class TernaryMod method makeTernaryInsn.

static boolean makeTernaryInsn(MethodNode mth, IfRegion ifRegion) {
    if (ifRegion.contains(AFlag.ELSE_IF_CHAIN)) {
        return false;
    }
    IContainer thenRegion = ifRegion.getThenRegion();
    IContainer elseRegion = ifRegion.getElseRegion();
    if (thenRegion == null || elseRegion == null) {
        return false;
    }
    BlockNode tb = getTernaryInsnBlock(thenRegion);
    BlockNode eb = getTernaryInsnBlock(elseRegion);
    if (tb == null || eb == null) {
        return false;
    }
    BlockNode header = ifRegion.getHeader();
    InsnNode t = tb.getInstructions().get(0);
    InsnNode e = eb.getInstructions().get(0);
    if (t.getSourceLine() != e.getSourceLine()) {
        if (t.getSourceLine() != 0 && e.getSourceLine() != 0) {
            // sometimes source lines incorrect
            if (!checkLineStats(t, e)) {
                return false;
            }
        } else {
            // no debug info
            if (containsTernary(t) || containsTernary(e)) {
                // TODO: add addition checks
                return false;
            }
        }
    }
    if (t.getResult() != null && e.getResult() != null) {
        PhiInsn phi = t.getResult().getSVar().getUsedInPhi();
        if (phi == null || !t.getResult().equalRegisterAndType(e.getResult())) {
            return false;
        }
        if (!ifRegion.getParent().replaceSubBlock(ifRegion, header)) {
            return false;
        }
        InsnList.remove(tb, t);
        InsnList.remove(eb, e);
        RegisterArg resArg;
        if (phi.getArgsCount() == 2) {
            resArg = phi.getResult();
        } else {
            resArg = t.getResult();
            phi.removeArg(e.getResult());
        }
        TernaryInsn ternInsn = new TernaryInsn(ifRegion.getCondition(), resArg, InsnArg.wrapArg(t), InsnArg.wrapArg(e));
        ternInsn.setSourceLine(t.getSourceLine());
        // remove 'if' instruction
        header.getInstructions().clear();
        header.getInstructions().add(ternInsn);
        // shrink method again
        CodeShrinker.shrinkMethod(mth);
        return true;
    }
    if (!mth.getReturnType().equals(ArgType.VOID) && t.getType() == InsnType.RETURN && e.getType() == InsnType.RETURN) {
        if (!ifRegion.getParent().replaceSubBlock(ifRegion, header)) {
            return false;
        }
        InsnList.remove(tb, t);
        InsnList.remove(eb, e);
        tb.remove(AFlag.RETURN);
        eb.remove(AFlag.RETURN);
        TernaryInsn ternInsn = new TernaryInsn(ifRegion.getCondition(), null, t.getArg(0), e.getArg(0));
        ternInsn.setSourceLine(t.getSourceLine());
        InsnNode retInsn = new InsnNode(InsnType.RETURN, 1);
        retInsn.addArg(InsnArg.wrapArg(ternInsn));
        header.getInstructions().clear();
        header.getInstructions().add(retInsn);
        header.add(AFlag.RETURN);
        CodeShrinker.shrinkMethod(mth);
        return true;
    }
    return false;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) PhiInsn(jadx.core.dex.instructions.PhiInsn) TernaryInsn(jadx.core.dex.instructions.mods.TernaryInsn) IContainer(jadx.core.dex.nodes.IContainer)

Example 4 with PhiInsn

use of jadx.core.dex.instructions.PhiInsn in project jadx by skylot.

the class EliminatePhiNodes method removePhiInstructions.

private static void removePhiInstructions(MethodNode mth) {
    for (BlockNode block : mth.getBasicBlocks()) {
        PhiListAttr phiList = block.get(AType.PHI_LIST);
        if (phiList == null) {
            continue;
        }
        List<PhiInsn> list = phiList.getList();
        for (PhiInsn phiInsn : list) {
            removeInsn(mth, block, phiInsn);
        }
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) PhiInsn(jadx.core.dex.instructions.PhiInsn) PhiListAttr(jadx.core.dex.attributes.nodes.PhiListAttr)

Example 5 with PhiInsn

use of jadx.core.dex.instructions.PhiInsn in project jadx by skylot.

the class SSATransform method renameVar.

private static void renameVar(MethodNode mth, SSAVar[] vars, int[] vers, BlockNode block) {
    SSAVar[] inputVars = Arrays.copyOf(vars, vars.length);
    for (InsnNode insn : block.getInstructions()) {
        if (insn.getType() != InsnType.PHI) {
            for (InsnArg arg : insn.getArguments()) {
                if (!arg.isRegister()) {
                    continue;
                }
                RegisterArg reg = (RegisterArg) arg;
                int regNum = reg.getRegNum();
                SSAVar var = vars[regNum];
                if (var == null) {
                    throw new JadxRuntimeException("Not initialized variable reg: " + regNum + ", insn: " + insn + ", block:" + block + ", method: " + mth);
                }
                var.use(reg);
            }
        }
        RegisterArg result = insn.getResult();
        if (result != null) {
            int regNum = result.getRegNum();
            vars[regNum] = newSSAVar(mth, vers, result, regNum);
        }
    }
    for (BlockNode s : block.getSuccessors()) {
        PhiListAttr phiList = s.get(AType.PHI_LIST);
        if (phiList == null) {
            continue;
        }
        for (PhiInsn phiInsn : phiList.getList()) {
            int regNum = phiInsn.getResult().getRegNum();
            SSAVar var = vars[regNum];
            if (var == null) {
                continue;
            }
            RegisterArg arg = phiInsn.bindArg(block);
            var.use(arg);
            var.setUsedInPhi(phiInsn);
        }
    }
    for (BlockNode domOn : block.getDominatesOn()) {
        renameVar(mth, vars, vers, domOn);
    }
    System.arraycopy(inputVars, 0, vars, 0, vars.length);
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) SSAVar(jadx.core.dex.instructions.args.SSAVar) PhiInsn(jadx.core.dex.instructions.PhiInsn) InsnArg(jadx.core.dex.instructions.args.InsnArg) PhiListAttr(jadx.core.dex.attributes.nodes.PhiListAttr) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException)

Aggregations

PhiInsn (jadx.core.dex.instructions.PhiInsn)16 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)11 InsnNode (jadx.core.dex.nodes.InsnNode)10 PhiListAttr (jadx.core.dex.attributes.nodes.PhiListAttr)8 BlockNode (jadx.core.dex.nodes.BlockNode)8 SSAVar (jadx.core.dex.instructions.args.SSAVar)7 InsnArg (jadx.core.dex.instructions.args.InsnArg)4 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)3 ArrayList (java.util.ArrayList)2 ArgType (jadx.core.dex.instructions.args.ArgType)1 TernaryInsn (jadx.core.dex.instructions.mods.TernaryInsn)1 DexNode (jadx.core.dex.nodes.DexNode)1 IContainer (jadx.core.dex.nodes.IContainer)1 ForLoop (jadx.core.dex.regions.loops.ForLoop)1 LoopType (jadx.core.dex.regions.loops.LoopType)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1