Search in sources :

Example 31 with RegisterArg

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

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

the class BlockFinallyExtract method extractFinally.

/**
	 * Search and remove common code from 'catch' and 'handlers'.
	 */
private static boolean extractFinally(MethodNode mth, ExceptionHandler handler) {
    int count = handler.getBlocks().size();
    BitSet bs = new BitSet(count);
    List<BlockNode> blocks = new ArrayList<BlockNode>(count);
    for (BlockNode block : handler.getBlocks()) {
        List<InsnNode> insns = block.getInstructions();
        if (!insns.isEmpty()) {
            if (insns.get(0).getType() != InsnType.MOVE_EXCEPTION) {
                blocks.add(block);
            }
            bs.set(block.getId());
        }
    }
    if (blocks.isEmpty()) {
        // nothing to do
        return false;
    }
    List<BlocksRemoveInfo> removes = new LinkedList<BlocksRemoveInfo>();
    Set<BlockNode> splitters = new HashSet<BlockNode>();
    // remove 'finally' from handlers
    TryCatchBlock tryBlock = handler.getTryBlock();
    if (tryBlock.getHandlersCount() > 1) {
        for (ExceptionHandler otherHandler : tryBlock.getHandlers()) {
            if (otherHandler == handler) {
                continue;
            }
            for (BlockNode hb : otherHandler.getBlocks()) {
                BlocksRemoveInfo removeInfo = removeInsns(mth, hb, blocks, bs);
                if (removeInfo != null) {
                    removes.add(removeInfo);
                    break;
                }
            }
        }
        if (removes.size() != tryBlock.getHandlersCount() - 1) {
            return false;
        }
    }
    for (ExceptionHandler otherHandler : tryBlock.getHandlers()) {
        SplitterBlockAttr splitterAttr = otherHandler.getHandlerBlock().get(AType.SPLITTER_BLOCK);
        if (splitterAttr != null) {
            BlockNode splBlock = splitterAttr.getBlock();
            if (!splBlock.getCleanSuccessors().isEmpty()) {
                splitters.add(splBlock);
            }
        }
    }
    // remove 'finally' from 'try' blocks (dominated by splitter block)
    boolean removed = false;
    for (BlockNode splitter : splitters) {
        BlockNode start = splitter.getCleanSuccessors().get(0);
        List<BlockNode> list = BlockUtils.collectBlocksDominatedBy(splitter, start);
        for (BlockNode block : list) {
            if (bs.get(block.getId())) {
                continue;
            }
            BlocksRemoveInfo removeInfo = removeInsns(mth, block, blocks, bs);
            if (removeInfo != null) {
                removes.add(removeInfo);
                removed = true;
                break;
            }
        }
    }
    if (!removed) {
        return false;
    }
    // 'finally' extract confirmed, run remove steps
    LiveVarAnalysis laBefore = null;
    boolean runReMap = isReMapNeeded(removes);
    if (runReMap) {
        laBefore = new LiveVarAnalysis(mth);
        laBefore.runAnalysis();
    }
    for (BlocksRemoveInfo removeInfo : removes) {
        if (!applyRemove(mth, removeInfo)) {
            return false;
        }
    }
    LiveVarAnalysis laAfter = null;
    // remove 'move-exception' instruction
    BlockNode handlerBlock = handler.getHandlerBlock();
    InsnNode me = BlockUtils.getLastInsn(handlerBlock);
    if (me != null && me.getType() == InsnType.MOVE_EXCEPTION) {
        boolean replaced = false;
        List<InsnNode> insnsList = handlerBlock.getInstructions();
        if (!handlerBlock.getCleanSuccessors().isEmpty()) {
            laAfter = new LiveVarAnalysis(mth);
            laAfter.runAnalysis();
            RegisterArg resArg = me.getResult();
            BlockNode succ = handlerBlock.getCleanSuccessors().get(0);
            if (laAfter.isLive(succ, resArg.getRegNum())) {
                // kill variable
                InsnNode kill = new InsnNode(InsnType.NOP, 0);
                kill.setResult(resArg);
                kill.add(AFlag.REMOVE);
                insnsList.set(insnsList.size() - 1, kill);
                replaced = true;
            }
        }
        if (!replaced) {
            insnsList.remove(insnsList.size() - 1);
            handlerBlock.add(AFlag.SKIP);
        }
    }
    // generate 'move' instruction for mapped register pairs
    if (runReMap) {
        if (laAfter == null) {
            laAfter = new LiveVarAnalysis(mth);
            laAfter.runAnalysis();
        }
        performVariablesReMap(mth, removes, laBefore, laAfter);
    }
    handler.setFinally(true);
    return true;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) ExceptionHandler(jadx.core.dex.trycatch.ExceptionHandler) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) SplitterBlockAttr(jadx.core.dex.trycatch.SplitterBlockAttr) LiveVarAnalysis(jadx.core.dex.visitors.ssa.LiveVarAnalysis) TryCatchBlock(jadx.core.dex.trycatch.TryCatchBlock) BlocksRemoveInfo(jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo) HashSet(java.util.HashSet)

Example 33 with RegisterArg

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

the class ModVisitor method checkArgsNames.

private static void checkArgsNames(MethodNode mth) {
    for (RegisterArg arg : mth.getArguments(false)) {
        String name = arg.getName();
        if (name != null && NameMapper.isReserved(name)) {
            name = name + "_";
            arg.getSVar().setName(name);
        }
    }
}
Also used : RegisterArg(jadx.core.dex.instructions.args.RegisterArg)

Example 34 with RegisterArg

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

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

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