Commit d7ce0245 authored by Skylot's avatar Skylot

core: convert arithmetic operations on field to arith instruction

parent 49c5ceb0
...@@ -18,6 +18,7 @@ import jadx.core.dex.instructions.InvokeNode; ...@@ -18,6 +18,7 @@ import jadx.core.dex.instructions.InvokeNode;
import jadx.core.dex.instructions.InvokeType; import jadx.core.dex.instructions.InvokeType;
import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.SwitchNode;
import jadx.core.dex.instructions.args.ArgType; 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.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg; import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.LiteralArg;
...@@ -77,7 +78,7 @@ public class InsnGen { ...@@ -77,7 +78,7 @@ public class InsnGen {
public String arg(InsnArg arg) throws CodegenException { public String arg(InsnArg arg) throws CodegenException {
if (arg.isRegister()) { if (arg.isRegister()) {
return arg((RegisterArg) arg); return mgen.makeArgName((RegisterArg) arg);
} else if (arg.isLiteral()) { } else if (arg.isLiteral()) {
return lit((LiteralArg) arg); return lit((LiteralArg) arg);
} else if (arg.isInsnWrap()) { } else if (arg.isInsnWrap()) {
...@@ -86,16 +87,21 @@ public class InsnGen { ...@@ -86,16 +87,21 @@ public class InsnGen {
return code.toString(); return code.toString();
} else if (arg.isNamed()) { } else if (arg.isNamed()) {
return ((NamedArg) arg).getName(); 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 { } else {
throw new CodegenException("Unknown arg type " + arg); throw new CodegenException("Unknown arg type " + arg);
} }
} }
public String arg(RegisterArg arg) { public String assignVar(InsnNode insn) throws CodegenException {
return mgen.makeArgName(arg);
}
public String assignVar(InsnNode insn) {
RegisterArg arg = insn.getResult(); RegisterArg arg = insn.getResult();
if (insn.getAttributes().contains(AttributeType.DECLARE_VARIABLE)) { if (insn.getAttributes().contains(AttributeType.DECLARE_VARIABLE)) {
return declareVar(arg); return declareVar(arg);
...@@ -112,13 +118,11 @@ public class InsnGen { ...@@ -112,13 +118,11 @@ public class InsnGen {
return TypeGen.literalToString(arg.getLiteral(), arg.getType()); return TypeGen.literalToString(arg.getLiteral(), arg.getType());
} }
private String ifield(IndexInsnNode insn, int reg) throws CodegenException { private String ifield(FieldInfo field, InsnArg arg) throws CodegenException {
FieldInfo field = (FieldInfo) insn.getIndex(); return arg(arg) + "." + field.getName();
return arg(insn.getArg(reg)) + '.' + field.getName();
} }
private String sfield(IndexInsnNode insn) { private String sfield(FieldInfo field) {
FieldInfo field = (FieldInfo) insn.getIndex();
String thisClass = mth.getParentClass().getFullName(); String thisClass = mth.getParentClass().getFullName();
if (field.getDeclClass().getFullName().equals(thisClass)) { if (field.getDeclClass().getFullName().equals(thisClass)) {
return field.getName(); return field.getName();
...@@ -289,20 +293,24 @@ public class InsnGen { ...@@ -289,20 +293,24 @@ public class InsnGen {
code.add(arg(insn, 0)).add('[').add(arg(insn, 1)).add("] = ").add(arg(insn, 2)); code.add(arg(insn, 0)).add('[').add(arg(insn, 1)).add("] = ").add(arg(insn, 2));
break; break;
case IGET: case IGET: {
code.add(ifield((IndexInsnNode) insn, 0)); FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
code.add(ifield(fieldInfo, insn.getArg(0)));
break; 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; break;
}
case SGET: case SGET:
code.add(sfield((IndexInsnNode) insn)); code.add(sfield((FieldInfo) ((IndexInsnNode) insn).getIndex()));
break; break;
case SPUT: case SPUT:
IndexInsnNode node = (IndexInsnNode) insn; IndexInsnNode node = (IndexInsnNode) insn;
fieldPut(node); 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; break;
case STR_CONCAT: case STR_CONCAT:
......
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 + ")";
}
}
...@@ -50,6 +50,10 @@ public abstract class InsnArg extends Typed { ...@@ -50,6 +50,10 @@ public abstract class InsnArg extends Typed {
return false; return false;
} }
public boolean isField() {
return false;
}
public InsnNode getParentInsn() { public InsnNode getParentInsn() {
return parentInsn; return parentInsn;
} }
......
...@@ -2,12 +2,15 @@ package jadx.core.dex.visitors; ...@@ -2,12 +2,15 @@ package jadx.core.dex.visitors;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo; import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.ArithNode; import jadx.core.dex.instructions.ArithNode;
import jadx.core.dex.instructions.ArithOp; import jadx.core.dex.instructions.ArithOp;
import jadx.core.dex.instructions.IfNode; import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.InvokeNode; 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.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg; import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.LiteralArg;
...@@ -187,6 +190,40 @@ public class CodeShrinker extends AbstractVisitor { ...@@ -187,6 +190,40 @@ public class CodeShrinker extends AbstractVisitor {
} }
break; break;
case IPUT:
case SPUT:
// convert field arith operation to arith instruction
// (IPUT = ARITH (IGET, lit) -> ARITH (fieldArg <op>= 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: default:
break; break;
} }
......
...@@ -36,9 +36,10 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -36,9 +36,10 @@ public class ConstInlinerVisitor extends AbstractVisitor {
private static boolean checkInsn(MethodNode mth, BlockNode block, InsnNode insn) { private static boolean checkInsn(MethodNode mth, BlockNode block, InsnNode insn) {
if (insn.getType() == InsnType.CONST) { 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 */) { && 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); return replaceConst(mth, block, insn, lit);
} }
// TODO process string and class const // TODO process string and class const
...@@ -57,8 +58,7 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -57,8 +58,7 @@ public class ConstInlinerVisitor extends AbstractVisitor {
BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn); BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn);
if (useBlock == block || useBlock.isDominator(block)) { if (useBlock == block || useBlock.isDominator(block)) {
if (arg != insn.getResult() if (arg != insn.getResult() && !registerReassignOnPath(block, useBlock, insn)) {
&& !registerReassignOnPath(block, useBlock, insn)) {
// in most cases type not equal arg.getType() // in most cases type not equal arg.getType()
// just set unknown type and run type fixer // just set unknown type and run type fixer
LiteralArg litArg = InsnArg.lit(literal, ArgType.NARROW); LiteralArg litArg = InsnArg.lit(literal, ArgType.NARROW);
......
package jadx.core.dex.visitors; package jadx.core.dex.visitors;
import jadx.core.Consts;
import jadx.core.deobf.NameMapper; import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AttributeType; import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.info.MethodInfo; import jadx.core.dex.info.MethodInfo;
...@@ -67,8 +66,8 @@ public class ModVisitor extends AbstractVisitor { ...@@ -67,8 +66,8 @@ public class ModVisitor extends AbstractVisitor {
ConstructorInsn co = new ConstructorInsn(mth, inv); ConstructorInsn co = new ConstructorInsn(mth, inv);
if (co.isSuper()) { if (co.isSuper()) {
try { try {
// don't call 'super' if parent 'Object' if (co.getArgsCount() != 0) {
if (!co.getClassType().getFullName().equals(Consts.CLASS_OBJECT)) { // inline super call args
for (int j = 0; j < co.getArgsCount(); j++) { for (int j = 0; j < co.getArgsCount(); j++) {
InsnArg arg = co.getArg(j); InsnArg arg = co.getArg(j);
if (arg.isRegister()) { if (arg.isRegister()) {
......
...@@ -77,7 +77,7 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -77,7 +77,7 @@ public class ProcessVariables extends AbstractVisitor {
InsnNode insn = container.getInstructions().get(i); InsnNode insn = container.getInstructions().get(i);
// result // result
RegisterArg result = insn.getResult(); RegisterArg result = insn.getResult();
if (result != null) { if (result != null && result.isRegister()) {
Usage u = usageMap.get(result); Usage u = usageMap.get(result);
if (u == null) { if (u == null) {
u = new Usage(); u = new Usage();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment