Search in sources :

Example 6 with ConstructorInsn

use of jadx.core.dex.instructions.mods.ConstructorInsn in project jadx by skylot.

the class ModVisitor method processConstructor.

/**
	 * Replace call of synthetic constructor
	 */
private static ConstructorInsn processConstructor(MethodNode mth, ConstructorInsn co) {
    MethodNode callMth = mth.dex().resolveMethod(co.getCallMth());
    if (callMth == null || !callMth.getAccessFlags().isSynthetic() || !allArgsNull(co)) {
        return null;
    }
    ClassNode classNode = mth.dex().resolveClass(callMth.getParentClass().getClassInfo());
    if (classNode == null) {
        return null;
    }
    boolean passThis = co.getArgsCount() >= 1 && co.getArg(0).isThis();
    String ctrId = "<init>(" + (passThis ? TypeGen.signature(co.getArg(0).getType()) : "") + ")V";
    MethodNode defCtr = classNode.searchMethodByName(ctrId);
    if (defCtr == null) {
        return null;
    }
    ConstructorInsn newInsn = new ConstructorInsn(defCtr.getMethodInfo(), co.getCallType(), co.getInstanceArg());
    newInsn.setResult(co.getResult());
    return newInsn;
}
Also used : ClassNode(jadx.core.dex.nodes.ClassNode) ConstClassNode(jadx.core.dex.instructions.ConstClassNode) MethodNode(jadx.core.dex.nodes.MethodNode) ConstructorInsn(jadx.core.dex.instructions.mods.ConstructorInsn)

Example 7 with ConstructorInsn

use of jadx.core.dex.instructions.mods.ConstructorInsn 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 8 with ConstructorInsn

use of jadx.core.dex.instructions.mods.ConstructorInsn in project jadx by skylot.

the class ClassModifier method removeSyntheticMethods.

private static void removeSyntheticMethods(ClassNode cls) {
    for (MethodNode mth : cls.getMethods()) {
        if (mth.isNoCode()) {
            continue;
        }
        AccessInfo af = mth.getAccessFlags();
        // remove bridge methods
        if (af.isBridge() && af.isSynthetic() && !isMethodUniq(cls, mth)) {
            // TODO add more checks before method deletion
            mth.add(AFlag.DONT_GENERATE);
            continue;
        }
        // remove synthetic constructor for inner classes
        if (af.isSynthetic() && af.isConstructor() && mth.getBasicBlocks().size() == 2) {
            List<InsnNode> insns = mth.getBasicBlocks().get(0).getInstructions();
            if (insns.size() == 1 && insns.get(0).getType() == InsnType.CONSTRUCTOR) {
                ConstructorInsn constr = (ConstructorInsn) insns.get(0);
                List<RegisterArg> args = mth.getArguments(false);
                if (constr.isThis() && !args.isEmpty()) {
                    // remove first arg for non-static class (references to outer class)
                    if (args.get(0).getType().equals(cls.getParentClass().getClassInfo().getType())) {
                        args.get(0).add(AFlag.SKIP_ARG);
                    }
                    // remove unused args
                    for (RegisterArg arg : args) {
                        SSAVar sVar = arg.getSVar();
                        if (sVar != null && sVar.getUseCount() == 0) {
                            arg.add(AFlag.SKIP_ARG);
                        }
                    }
                    mth.add(AFlag.DONT_GENERATE);
                }
            }
        }
    }
}
Also used : IndexInsnNode(jadx.core.dex.instructions.IndexInsnNode) InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) MethodNode(jadx.core.dex.nodes.MethodNode) SSAVar(jadx.core.dex.instructions.args.SSAVar) AccessInfo(jadx.core.dex.info.AccessInfo) ConstructorInsn(jadx.core.dex.instructions.mods.ConstructorInsn)

Aggregations

ConstructorInsn (jadx.core.dex.instructions.mods.ConstructorInsn)8 InsnNode (jadx.core.dex.nodes.InsnNode)6 IndexInsnNode (jadx.core.dex.instructions.IndexInsnNode)5 MethodNode (jadx.core.dex.nodes.MethodNode)5 ClassNode (jadx.core.dex.nodes.ClassNode)4 MethodInfo (jadx.core.dex.info.MethodInfo)3 ConstClassNode (jadx.core.dex.instructions.ConstClassNode)3 InvokeNode (jadx.core.dex.instructions.InvokeNode)3 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)3 EnumClassAttr (jadx.core.dex.attributes.nodes.EnumClassAttr)2 EnumField (jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField)2 FieldInfo (jadx.core.dex.info.FieldInfo)2 InsnArg (jadx.core.dex.instructions.args.InsnArg)2 InsnWrapArg (jadx.core.dex.instructions.args.InsnWrapArg)2 FieldNode (jadx.core.dex.nodes.FieldNode)2 ArrayList (java.util.ArrayList)2 AccessInfo (jadx.core.dex.info.AccessInfo)1 ClassInfo (jadx.core.dex.info.ClassInfo)1 ConstStringNode (jadx.core.dex.instructions.ConstStringNode)1 ArgType (jadx.core.dex.instructions.args.ArgType)1