From d7ce0245f68870dfe5579275ac88e36ed58284b4 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 9 Sep 2013 23:30:10 +0400 Subject: [PATCH] core: convert arithmetic operations on field to arith instruction --- .../main/java/jadx/core/codegen/InsnGen.java | 42 +++++++++++-------- .../core/dex/instructions/args/FieldArg.java | 36 ++++++++++++++++ .../core/dex/instructions/args/InsnArg.java | 4 ++ .../jadx/core/dex/visitors/CodeShrinker.java | 37 ++++++++++++++++ .../dex/visitors/ConstInlinerVisitor.java | 8 ++-- .../jadx/core/dex/visitors/ModVisitor.java | 5 +-- .../visitors/regions/ProcessVariables.java | 2 +- 7 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index eea2c63d0..79c5ebac4 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -18,6 +18,7 @@ import jadx.core.dex.instructions.InvokeNode; import jadx.core.dex.instructions.InvokeType; import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.instructions.args.FieldArg; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnWrapArg; import jadx.core.dex.instructions.args.LiteralArg; @@ -77,7 +78,7 @@ public class InsnGen { public String arg(InsnArg arg) throws CodegenException { if (arg.isRegister()) { - return arg((RegisterArg) arg); + return mgen.makeArgName((RegisterArg) arg); } else if (arg.isLiteral()) { return lit((LiteralArg) arg); } else if (arg.isInsnWrap()) { @@ -86,16 +87,21 @@ public class InsnGen { return code.toString(); } else if (arg.isNamed()) { return ((NamedArg) arg).getName(); + } else if (arg.isField()) { + FieldArg f = (FieldArg) arg; + if (f.isStatic()) { + return sfield(f.getField()); + } else { + RegisterArg regArg = new RegisterArg(f.getRegNum()); + regArg.setTypedVar(f.getTypedVar()); + return ifield(f.getField(), regArg); + } } else { throw new CodegenException("Unknown arg type " + arg); } } - public String arg(RegisterArg arg) { - return mgen.makeArgName(arg); - } - - public String assignVar(InsnNode insn) { + public String assignVar(InsnNode insn) throws CodegenException { RegisterArg arg = insn.getResult(); if (insn.getAttributes().contains(AttributeType.DECLARE_VARIABLE)) { return declareVar(arg); @@ -112,13 +118,11 @@ public class InsnGen { return TypeGen.literalToString(arg.getLiteral(), arg.getType()); } - private String ifield(IndexInsnNode insn, int reg) throws CodegenException { - FieldInfo field = (FieldInfo) insn.getIndex(); - return arg(insn.getArg(reg)) + '.' + field.getName(); + private String ifield(FieldInfo field, InsnArg arg) throws CodegenException { + return arg(arg) + "." + field.getName(); } - private String sfield(IndexInsnNode insn) { - FieldInfo field = (FieldInfo) insn.getIndex(); + private String sfield(FieldInfo field) { String thisClass = mth.getParentClass().getFullName(); if (field.getDeclClass().getFullName().equals(thisClass)) { return field.getName(); @@ -289,20 +293,24 @@ public class InsnGen { code.add(arg(insn, 0)).add('[').add(arg(insn, 1)).add("] = ").add(arg(insn, 2)); break; - case IGET: - code.add(ifield((IndexInsnNode) insn, 0)); + case IGET: { + FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex(); + code.add(ifield(fieldInfo, insn.getArg(0))); break; - case IPUT: - code.add(ifield((IndexInsnNode) insn, 1)).add(" = ").add(arg(insn.getArg(0))); + } + case IPUT: { + FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex(); + code.add(ifield(fieldInfo, insn.getArg(1))).add(" = ").add(arg(insn.getArg(0))); break; + } case SGET: - code.add(sfield((IndexInsnNode) insn)); + code.add(sfield((FieldInfo) ((IndexInsnNode) insn).getIndex())); break; case SPUT: IndexInsnNode node = (IndexInsnNode) insn; fieldPut(node); - code.add(sfield(node)).add(" = ").add(arg(node.getArg(0))); + code.add(sfield((FieldInfo) node.getIndex())).add(" = ").add(arg(node.getArg(0))); break; case STR_CONCAT: diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java new file mode 100644 index 000000000..4d3c2422a --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java @@ -0,0 +1,36 @@ +package jadx.core.dex.instructions.args; + +import jadx.core.dex.info.FieldInfo; + +public final class FieldArg extends RegisterArg { + + private final FieldInfo field; + + public FieldArg(FieldInfo field, int regNum) { + super(regNum, field.getType()); + this.field = field; + } + + public FieldInfo getField() { + return field; + } + + public boolean isStatic() { + return regNum == -1; + } + + @Override + public boolean isField() { + return true; + } + + @Override + public boolean isRegister() { + return false; + } + + @Override + public String toString() { + return "(" + field + ")"; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java index 6a2ba343c..e466b63ee 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java @@ -50,6 +50,10 @@ public abstract class InsnArg extends Typed { return false; } + public boolean isField() { + return false; + } + public InsnNode getParentInsn() { return parentInsn; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java index 44007cce6..d660d0a08 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java @@ -2,12 +2,15 @@ package jadx.core.dex.visitors; import jadx.core.Consts; import jadx.core.dex.attributes.AttributeFlag; +import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.MethodInfo; import jadx.core.dex.instructions.ArithNode; import jadx.core.dex.instructions.ArithOp; import jadx.core.dex.instructions.IfNode; +import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InvokeNode; +import jadx.core.dex.instructions.args.FieldArg; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnWrapArg; import jadx.core.dex.instructions.args.LiteralArg; @@ -187,6 +190,40 @@ public class CodeShrinker extends AbstractVisitor { } break; + case IPUT: + case SPUT: + // convert field arith operation to arith instruction + // (IPUT = ARITH (IGET, lit) -> ARITH (fieldArg = lit)) + InsnArg arg = insn.getArg(0); + if (arg.isInsnWrap()) { + InsnNode wrap = ((InsnWrapArg) arg).getWrapInsn(); + if (wrap.getType() == InsnType.ARITH && wrap.getArg(0).isInsnWrap()) { + InsnNode get = ((InsnWrapArg) wrap.getArg(0)).getWrapInsn(); + InsnType getType = get.getType(); + if (getType == InsnType.IGET || getType == InsnType.SGET) { + FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex(); + FieldInfo innerField = (FieldInfo) ((IndexInsnNode) get).getIndex(); + if (field.equals(innerField)) { + try { + ArithNode ar = (ArithNode) wrap; + RegisterArg reg = null; + if (getType == InsnType.IGET) { + reg = ((RegisterArg) get.getArg(0)); + } + RegisterArg fArg = new FieldArg(field, reg != null ? reg.getRegNum() : -1); + if (reg != null) { + fArg.setTypedVar(get.getArg(0).getTypedVar()); + } + return new ArithNode(ar.getOp(), fArg, fArg, ar.getArg(1)); + } catch (Throwable e) { + LOG.debug("Can't convert field arith insn: {}, mth: {}", insn, mth, e); + } + } + } + } + } + break; + default: break; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java index 0721dd848..0c5028f04 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlinerVisitor.java @@ -36,9 +36,10 @@ public class ConstInlinerVisitor extends AbstractVisitor { private static boolean checkInsn(MethodNode mth, BlockNode block, InsnNode insn) { if (insn.getType() == InsnType.CONST) { - if (insn.getArg(0).isLiteral() + InsnArg arg = insn.getArg(0); + if (arg.isLiteral() && insn.getResult().getType().getRegCount() == 1 /* process only narrow types */) { - long lit = ((LiteralArg) insn.getArg(0)).getLiteral(); + long lit = ((LiteralArg) arg).getLiteral(); return replaceConst(mth, block, insn, lit); } // TODO process string and class const @@ -57,8 +58,7 @@ public class ConstInlinerVisitor extends AbstractVisitor { BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn); if (useBlock == block || useBlock.isDominator(block)) { - if (arg != insn.getResult() - && !registerReassignOnPath(block, useBlock, insn)) { + if (arg != insn.getResult() && !registerReassignOnPath(block, useBlock, insn)) { // in most cases type not equal arg.getType() // just set unknown type and run type fixer LiteralArg litArg = InsnArg.lit(literal, ArgType.NARROW); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java index 673eb2a3d..d5a0b0c8a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java @@ -1,6 +1,5 @@ package jadx.core.dex.visitors; -import jadx.core.Consts; import jadx.core.deobf.NameMapper; import jadx.core.dex.attributes.AttributeType; import jadx.core.dex.info.MethodInfo; @@ -67,8 +66,8 @@ public class ModVisitor extends AbstractVisitor { ConstructorInsn co = new ConstructorInsn(mth, inv); if (co.isSuper()) { try { - // don't call 'super' if parent 'Object' - if (!co.getClassType().getFullName().equals(Consts.CLASS_OBJECT)) { + if (co.getArgsCount() != 0) { + // inline super call args for (int j = 0; j < co.getArgsCount(); j++) { InsnArg arg = co.getArg(j); if (arg.isRegister()) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java index c1a22ea91..acb88c5b3 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java @@ -77,7 +77,7 @@ public class ProcessVariables extends AbstractVisitor { InsnNode insn = container.getInstructions().get(i); // result RegisterArg result = insn.getResult(); - if (result != null) { + if (result != null && result.isRegister()) { Usage u = usageMap.get(result); if (u == null) { u = new Usage();