Search in sources :

Example 76 with InsnNode

use of jadx.core.dex.nodes.InsnNode in project jadx by skylot.

the class ReSugarCode method getEnumMap.

private static EnumMapAttr.KeyValueMap getEnumMap(MethodNode mth, FieldNode field) {
    ClassNode syntheticClass = field.getParentClass();
    EnumMapAttr mapAttr = syntheticClass.get(AType.ENUM_MAP);
    if (mapAttr != null) {
        return mapAttr.getMap(field);
    }
    mapAttr = new EnumMapAttr();
    syntheticClass.addAttr(mapAttr);
    MethodNode clsInitMth = syntheticClass.searchMethodByName("<clinit>()V");
    if (clsInitMth == null || clsInitMth.isNoCode()) {
        return null;
    }
    if (clsInitMth.getBasicBlocks() == null) {
        try {
            clsInitMth.load();
        } catch (DecodeException e) {
            LOG.error("Load failed", e);
            return null;
        }
        if (clsInitMth.getBasicBlocks() == null) {
            // TODO:
            return null;
        }
    }
    for (BlockNode block : clsInitMth.getBasicBlocks()) {
        for (InsnNode insn : block.getInstructions()) {
            if (insn.getType() == InsnType.APUT) {
                addToEnumMap(mth, mapAttr, insn);
            }
        }
    }
    return mapAttr.getMap(field);
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) ClassNode(jadx.core.dex.nodes.ClassNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) MethodNode(jadx.core.dex.nodes.MethodNode) EnumMapAttr(jadx.core.dex.attributes.nodes.EnumMapAttr) DecodeException(jadx.core.utils.exceptions.DecodeException)

Example 77 with InsnNode

use of jadx.core.dex.nodes.InsnNode in project jadx by skylot.

the class ReSugarCode method processEnumSwitch.

private static InsnNode processEnumSwitch(MethodNode mth, SwitchNode insn) {
    InsnArg arg = insn.getArg(0);
    if (!arg.isInsnWrap()) {
        return null;
    }
    InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
    if (wrapInsn.getType() != InsnType.AGET) {
        return null;
    }
    EnumMapInfo enumMapInfo = checkEnumMapAccess(mth, wrapInsn);
    if (enumMapInfo == null) {
        return null;
    }
    FieldNode enumMapField = enumMapInfo.getMapField();
    InsnArg invArg = enumMapInfo.getArg();
    EnumMapAttr.KeyValueMap valueMap = getEnumMap(mth, enumMapField);
    if (valueMap == null) {
        return null;
    }
    Object[] keys = insn.getKeys();
    for (Object key : keys) {
        Object newKey = valueMap.get(key);
        if (newKey == null) {
            return null;
        }
    }
    // replace confirmed
    if (!insn.replaceArg(arg, invArg)) {
        return null;
    }
    for (int i = 0; i < keys.length; i++) {
        keys[i] = valueMap.get(keys[i]);
    }
    enumMapField.add(AFlag.DONT_GENERATE);
    checkAndHideClass(enumMapField.getParentClass());
    return null;
}
Also used : IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) FieldNode(jadx.core.dex.nodes.FieldNode) InsnArg(jadx.core.dex.instructions.args.InsnArg) EnumMapAttr(jadx.core.dex.attributes.nodes.EnumMapAttr) InsnWrapArg(jadx.core.dex.instructions.args.InsnWrapArg)

Example 78 with InsnNode

use of jadx.core.dex.nodes.InsnNode in project jadx by skylot.

the class EnumVisitor method visit.

@Override
public boolean visit(ClassNode cls) throws JadxException {
    if (!cls.isEnum()) {
        return true;
    }
    // search class init method
    MethodNode staticMethod = null;
    for (MethodNode mth : cls.getMethods()) {
        MethodInfo mi = mth.getMethodInfo();
        if (mi.isClassInit()) {
            staticMethod = mth;
            break;
        }
    }
    if (staticMethod == null) {
        ErrorsCounter.classError(cls, "Enum class init method not found");
        return true;
    }
    ArgType clsType = cls.getClassInfo().getType();
    String enumConstructor = "<init>(Ljava/lang/String;I)V";
    // TODO: detect these methods by analyzing method instructions
    String valuesOfMethod = "valueOf(Ljava/lang/String;)" + TypeGen.signature(clsType);
    String valuesMethod = "values()" + TypeGen.signature(ArgType.array(clsType));
    // collect enum fields, remove synthetic
    List<FieldNode> enumFields = new ArrayList<FieldNode>();
    for (FieldNode f : cls.getFields()) {
        if (f.getAccessFlags().isEnum()) {
            enumFields.add(f);
            f.add(AFlag.DONT_GENERATE);
        } else if (f.getAccessFlags().isSynthetic()) {
            f.add(AFlag.DONT_GENERATE);
        }
    }
    // remove synthetic methods
    for (MethodNode mth : cls.getMethods()) {
        MethodInfo mi = mth.getMethodInfo();
        if (mi.isClassInit()) {
            continue;
        }
        String shortId = mi.getShortId();
        boolean isSynthetic = mth.getAccessFlags().isSynthetic();
        if (mi.isConstructor() && !isSynthetic) {
            if (shortId.equals(enumConstructor)) {
                mth.add(AFlag.DONT_GENERATE);
            }
        } else if (isSynthetic || shortId.equals(valuesMethod) || shortId.equals(valuesOfMethod)) {
            mth.add(AFlag.DONT_GENERATE);
        }
    }
    EnumClassAttr attr = new EnumClassAttr(enumFields.size());
    cls.addAttr(attr);
    attr.setStaticMethod(staticMethod);
    ClassInfo classInfo = cls.getClassInfo();
    // move enum specific instruction from static method to separate list
    BlockNode staticBlock = staticMethod.getBasicBlocks().get(0);
    List<InsnNode> enumPutInsns = new ArrayList<InsnNode>();
    List<InsnNode> list = staticBlock.getInstructions();
    int size = list.size();
    for (int i = 0; i < size; i++) {
        InsnNode insn = list.get(i);
        if (insn.getType() != InsnType.SPUT) {
            continue;
        }
        FieldInfo f = (FieldInfo) ((IndexInsnNode) insn).getIndex();
        if (!f.getDeclClass().equals(classInfo)) {
            continue;
        }
        FieldNode fieldNode = cls.searchField(f);
        if (fieldNode != null && isEnumArrayField(classInfo, fieldNode)) {
            if (i == size - 1) {
                staticMethod.add(AFlag.DONT_GENERATE);
            } else {
                list.subList(0, i + 1).clear();
            }
            break;
        } else {
            enumPutInsns.add(insn);
        }
    }
    for (InsnNode putInsn : enumPutInsns) {
        ConstructorInsn co = getConstructorInsn(putInsn);
        if (co == null || co.getArgsCount() < 2) {
            continue;
        }
        ClassInfo clsInfo = co.getClassType();
        ClassNode constrCls = cls.dex().resolveClass(clsInfo);
        if (constrCls == null) {
            continue;
        }
        if (!clsInfo.equals(classInfo) && !constrCls.getAccessFlags().isEnum()) {
            continue;
        }
        FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) putInsn).getIndex();
        String name = getConstString(cls.dex(), co.getArg(0));
        if (name != null && !fieldInfo.getAlias().equals(name) && NameMapper.isValidIdentifier(name)) {
            // LOG.debug("Rename enum field: '{}' to '{}' in {}", fieldInfo.getName(), name, cls);
            fieldInfo.setAlias(name);
        }
        EnumField field = new EnumField(fieldInfo, co, 2);
        attr.getFields().add(field);
        if (!co.getClassType().equals(classInfo)) {
            // enum contains additional methods
            for (ClassNode innerCls : cls.getInnerClasses()) {
                processEnumInnerCls(co, field, innerCls);
            }
        }
    }
    return false;
}
Also used : ArgType(jadx.core.dex.instructions.args.ArgType) BlockNode(jadx.core.dex.nodes.BlockNode) ClassNode(jadx.core.dex.nodes.ClassNode) EnumField(jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField) FieldNode(jadx.core.dex.nodes.FieldNode) ArrayList(java.util.ArrayList) EnumClassAttr(jadx.core.dex.attributes.nodes.EnumClassAttr) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) MethodNode(jadx.core.dex.nodes.MethodNode) MethodInfo(jadx.core.dex.info.MethodInfo) ConstructorInsn(jadx.core.dex.instructions.mods.ConstructorInsn) FieldInfo(jadx.core.dex.info.FieldInfo) ClassInfo(jadx.core.dex.info.ClassInfo)

Example 79 with InsnNode

use of jadx.core.dex.nodes.InsnNode in project jadx by skylot.

the class ExtractFieldInit method moveCommonFieldsInit.

private static void moveCommonFieldsInit(ClassNode cls) {
    List<MethodNode> constrList = getConstructorsList(cls);
    if (constrList.isEmpty()) {
        return;
    }
    List<InitInfo> infoList = new ArrayList<InitInfo>(constrList.size());
    for (MethodNode constrMth : constrList) {
        if (constrMth.isNoCode() || constrMth.getBasicBlocks().isEmpty()) {
            return;
        }
        InitInfo info = new InitInfo(constrMth);
        infoList.add(info);
        // TODO: check not only first block
        BlockNode blockNode = constrMth.getBasicBlocks().get(0);
        for (InsnNode insn : blockNode.getInstructions()) {
            if (insn.getType() == InsnType.IPUT && checkInsn(insn)) {
                info.getPutInsns().add(insn);
            } else if (!info.getPutInsns().isEmpty()) {
                break;
            }
        }
    }
    // compare collected instructions
    InitInfo common = null;
    for (InitInfo info : infoList) {
        if (common == null) {
            common = info;
        } else if (!compareInsns(common.getPutInsns(), info.getPutInsns())) {
            return;
        }
    }
    if (common == null) {
        return;
    }
    Set<FieldInfo> fields = new HashSet<FieldInfo>();
    for (InsnNode insn : common.getPutInsns()) {
        FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
        FieldNode field = cls.dex().resolveField(fieldInfo);
        if (field == null) {
            return;
        }
        if (!fields.add(fieldInfo)) {
            return;
        }
    }
    // all checks passed
    for (InitInfo info : infoList) {
        for (InsnNode putInsn : info.getPutInsns()) {
            InstructionRemover.remove(info.getConstrMth(), putInsn);
        }
    }
    for (InsnNode insn : common.getPutInsns()) {
        FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
        FieldNode field = cls.dex().resolveField(fieldInfo);
        addFieldInitAttr(common.getConstrMth(), field, insn);
    }
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) MethodNode(jadx.core.dex.nodes.MethodNode) FieldNode(jadx.core.dex.nodes.FieldNode) ArrayList(java.util.ArrayList) FieldInfo(jadx.core.dex.info.FieldInfo) HashSet(java.util.HashSet)

Example 80 with InsnNode

use of jadx.core.dex.nodes.InsnNode in project jadx by skylot.

the class ExtractFieldInit method checkInsn.

private static boolean checkInsn(InsnNode insn) {
    InsnArg arg = insn.getArg(0);
    if (arg.isInsnWrap()) {
        InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
        if (!wrapInsn.canReorderRecursive() && insn.contains(AType.CATCH_BLOCK)) {
            return false;
        }
    } else {
        return arg.isLiteral() || arg.isThis();
    }
    Set<RegisterArg> regs = new HashSet<RegisterArg>();
    insn.getRegisterArgs(regs);
    if (!regs.isEmpty()) {
        for (RegisterArg reg : regs) {
            if (!reg.isThis()) {
                return false;
            }
        }
    }
    return true;
}
Also used : IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) InsnArg(jadx.core.dex.instructions.args.InsnArg) InsnWrapArg(jadx.core.dex.instructions.args.InsnWrapArg) HashSet(java.util.HashSet)

Aggregations

InsnNode (jadx.core.dex.nodes.InsnNode)123 BlockNode (jadx.core.dex.nodes.BlockNode)41 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)39 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)35 InsnArg (jadx.core.dex.instructions.args.InsnArg)32 InsnWrapArg (jadx.core.dex.instructions.args.InsnWrapArg)19 SSAVar (jadx.core.dex.instructions.args.SSAVar)16 ArrayList (java.util.ArrayList)14 ArgType (jadx.core.dex.instructions.args.ArgType)11 PhiInsn (jadx.core.dex.instructions.PhiInsn)10 FieldNode (jadx.core.dex.nodes.FieldNode)10 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)8 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)7 ClassNode (jadx.core.dex.nodes.ClassNode)7 MethodNode (jadx.core.dex.nodes.MethodNode)7 FieldInfo (jadx.core.dex.info.FieldInfo)6 ArithNode (jadx.core.dex.instructions.ArithNode)6 ConstructorInsn (jadx.core.dex.instructions.mods.ConstructorInsn)6 InsnType (jadx.core.dex.instructions.InsnType)5 IContainer (jadx.core.dex.nodes.IContainer)5