Search in sources :

Example 6 with IndexInsnNode

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

the class ModVisitor method makeFilledArrayInsn.

private static InsnNode makeFilledArrayInsn(MethodNode mth, FillArrayNode insn) {
    ArgType insnArrayType = insn.getResult().getType();
    ArgType insnElementType = insnArrayType.getArrayElement();
    ArgType elType = insn.getElementType();
    if (!elType.isTypeKnown() && insnElementType.isPrimitive()) {
        if (elType.contains(insnElementType.getPrimitiveType())) {
            elType = insnElementType;
        }
    }
    if (!elType.equals(insnElementType) && !insnArrayType.equals(ArgType.OBJECT)) {
        ErrorsCounter.methodError(mth, "Incorrect type for fill-array insn " + InsnUtils.formatOffset(insn.getOffset()) + ", element type: " + elType + ", insn element type: " + insnElementType);
    }
    if (!elType.isTypeKnown()) {
        LOG.warn("Unknown array element type: {} in mth: {}", elType, mth);
        elType = insnElementType.isTypeKnown() ? insnElementType : elType.selectFirst();
        if (elType == null) {
            throw new JadxRuntimeException("Null array element type");
        }
    }
    insn.mergeElementType(mth.dex(), elType);
    elType = insn.getElementType();
    List<LiteralArg> list = insn.getLiteralArgs();
    InsnNode filledArr = new FilledNewArrayNode(elType, list.size());
    filledArr.setResult(insn.getResult());
    for (LiteralArg arg : list) {
        FieldNode f = mth.getParentClass().getConstFieldByLiteralArg(arg);
        if (f != null) {
            InsnNode fGet = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
            filledArr.addArg(InsnArg.wrapArg(fGet));
        } else {
            filledArr.addArg(arg);
        }
    }
    return filledArr;
}
Also used : ArgType(jadx.core.dex.instructions.args.ArgType) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) FieldNode(jadx.core.dex.nodes.FieldNode) FilledNewArrayNode(jadx.core.dex.instructions.FilledNewArrayNode) LiteralArg(jadx.core.dex.instructions.args.LiteralArg) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode)

Example 7 with IndexInsnNode

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

the class ReSugarCode method checkEnumMapAccess.

public static EnumMapInfo checkEnumMapAccess(MethodNode mth, InsnNode checkInsn) {
    InsnArg sgetArg = checkInsn.getArg(0);
    InsnArg invArg = checkInsn.getArg(1);
    if (!sgetArg.isInsnWrap() || !invArg.isInsnWrap()) {
        return null;
    }
    InsnNode invInsn = ((InsnWrapArg) invArg).getWrapInsn();
    InsnNode sgetInsn = ((InsnWrapArg) sgetArg).getWrapInsn();
    if (invInsn.getType() != InsnType.INVOKE || sgetInsn.getType() != InsnType.SGET) {
        return null;
    }
    InvokeNode inv = (InvokeNode) invInsn;
    if (!inv.getCallMth().getShortId().equals("ordinal()I")) {
        return null;
    }
    ClassNode enumCls = mth.dex().resolveClass(inv.getCallMth().getDeclClass());
    if (enumCls == null || !enumCls.isEnum()) {
        return null;
    }
    Object index = ((IndexInsnNode) sgetInsn).getIndex();
    if (!(index instanceof FieldInfo)) {
        return null;
    }
    FieldNode enumMapField = mth.dex().resolveField((FieldInfo) index);
    if (enumMapField == null || !enumMapField.getAccessFlags().isSynthetic()) {
        return null;
    }
    return new EnumMapInfo(inv.getArg(0), enumMapField);
}
Also used : IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) ClassNode(jadx.core.dex.nodes.ClassNode) FieldNode(jadx.core.dex.nodes.FieldNode) InsnArg(jadx.core.dex.instructions.args.InsnArg) InvokeNode(jadx.core.dex.instructions.InvokeNode) InsnWrapArg(jadx.core.dex.instructions.args.InsnWrapArg) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) FieldInfo(jadx.core.dex.info.FieldInfo)

Example 8 with IndexInsnNode

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

the class ReSugarCode method addToEnumMap.

private static void addToEnumMap(MethodNode mth, EnumMapAttr mapAttr, InsnNode aputInsn) {
    InsnArg litArg = aputInsn.getArg(2);
    if (!litArg.isLiteral()) {
        return;
    }
    EnumMapInfo mapInfo = checkEnumMapAccess(mth, aputInsn);
    if (mapInfo == null) {
        return;
    }
    InsnArg enumArg = mapInfo.getArg();
    FieldNode field = mapInfo.getMapField();
    if (field == null || !enumArg.isInsnWrap()) {
        return;
    }
    InsnNode sget = ((InsnWrapArg) enumArg).getWrapInsn();
    if (!(sget instanceof IndexInsnNode)) {
        return;
    }
    Object index = ((IndexInsnNode) sget).getIndex();
    if (!(index instanceof FieldInfo)) {
        return;
    }
    FieldNode fieldNode = mth.dex().resolveField((FieldInfo) index);
    if (fieldNode == null) {
        return;
    }
    int literal = (int) ((LiteralArg) litArg).getLiteral();
    mapAttr.add(field, literal, fieldNode);
}
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) InsnWrapArg(jadx.core.dex.instructions.args.InsnWrapArg) IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) FieldInfo(jadx.core.dex.info.FieldInfo)

Example 9 with IndexInsnNode

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

use of jadx.core.dex.instructions.IndexInsnNode 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)

Aggregations

IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)14 InsnNode (jadx.core.dex.nodes.InsnNode)11 InsnArg (jadx.core.dex.instructions.args.InsnArg)10 FieldInfo (jadx.core.dex.info.FieldInfo)8 ArgType (jadx.core.dex.instructions.args.ArgType)8 FieldNode (jadx.core.dex.nodes.FieldNode)8 LiteralArg (jadx.core.dex.instructions.args.LiteralArg)5 InvokeNode (jadx.core.dex.instructions.InvokeNode)4 InsnWrapArg (jadx.core.dex.instructions.args.InsnWrapArg)4 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)4 BlockNode (jadx.core.dex.nodes.BlockNode)4 ClassNode (jadx.core.dex.nodes.ClassNode)4 ConstClassNode (jadx.core.dex.instructions.ConstClassNode)3 MethodNode (jadx.core.dex.nodes.MethodNode)3 ArrayList (java.util.ArrayList)3 MethodInfo (jadx.core.dex.info.MethodInfo)2 ArithNode (jadx.core.dex.instructions.ArithNode)2 FillArrayNode (jadx.core.dex.instructions.FillArrayNode)2 FilledNewArrayNode (jadx.core.dex.instructions.FilledNewArrayNode)2 SwitchNode (jadx.core.dex.instructions.SwitchNode)2