core: convert arithmetic operations on field to arith instruction
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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 + ")";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user