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;
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 {
throw new CodegenException("Unknown arg type " + arg);
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:
......
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 {
return false;
}
public boolean isField() {
return false;
}
public InsnNode getParentInsn() {
return parentInsn;
}
......
......@@ -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 <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:
break;
}
......
......@@ -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);
......
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()) {
......
......@@ -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();
......
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