@@ -277,7 +277,8 @@ public class InsnGen {
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
oneArgInsn(code, insn, state, '~');
|
||||
char op = insn.getArg(0).getType() == ArgType.BOOLEAN ? '!' : '~';
|
||||
oneArgInsn(code, insn, state, op);
|
||||
break;
|
||||
|
||||
case RETURN:
|
||||
|
||||
@@ -4,18 +4,26 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import jadx.core.dex.instructions.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.core.Consts;
|
||||
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.CallMthInterface;
|
||||
import jadx.core.dex.instructions.ConstStringNode;
|
||||
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.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;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.instructions.mods.ConstructorInsn;
|
||||
import jadx.core.dex.instructions.mods.TernaryInsn;
|
||||
import jadx.core.dex.nodes.BlockNode;
|
||||
@@ -54,7 +62,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
}
|
||||
switch (insn.getType()) {
|
||||
case ARITH:
|
||||
return simplifyArith(insn);
|
||||
return simplifyArith((ArithNode) insn);
|
||||
|
||||
case IF:
|
||||
simplifyIf((IfNode) insn);
|
||||
@@ -64,7 +72,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
break;
|
||||
|
||||
case INVOKE:
|
||||
return convertInvoke(mth, insn);
|
||||
return convertInvoke(mth, (InvokeNode) insn);
|
||||
|
||||
case IPUT:
|
||||
case SPUT:
|
||||
@@ -151,8 +159,8 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
* @param insn
|
||||
* @return
|
||||
*/
|
||||
private static InsnNode convertInvoke(MethodNode mth, InsnNode insn) {
|
||||
MethodInfo callMth = ((InvokeNode) insn).getCallMth();
|
||||
private static InsnNode convertInvoke(MethodNode mth, InvokeNode insn) {
|
||||
MethodInfo callMth = insn.getCallMth();
|
||||
|
||||
// If this is a 'new StringBuilder(xxx).append(yyy).append(zzz).toString(),
|
||||
// convert it to STRING_CONCAT pseudo instruction.
|
||||
@@ -225,8 +233,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static InsnNode simplifyArith(InsnNode insn) {
|
||||
ArithNode arith = (ArithNode) insn;
|
||||
private static InsnNode simplifyArith(ArithNode arith) {
|
||||
if (arith.getArgsCount() != 2) {
|
||||
return null;
|
||||
}
|
||||
@@ -245,9 +252,17 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
// fix 'c + (-1)' => 'c - (1)'
|
||||
if (arith.getOp() == ArithOp.ADD && lit < 0) {
|
||||
return new ArithNode(ArithOp.SUB,
|
||||
arith.getResult(), insn.getArg(0),
|
||||
arith.getResult(), arith.getArg(0),
|
||||
InsnArg.lit(-lit, litArg.getType()));
|
||||
}
|
||||
InsnArg firstArg = arith.getArg(0);
|
||||
if (arith.getOp() == ArithOp.XOR && firstArg.getType() == ArgType.BOOLEAN
|
||||
&& (lit == 0 || lit == 1)) {
|
||||
InsnNode node = new InsnNode(lit == 0 ? InsnType.MOVE : InsnType.NOT, 1);
|
||||
node.setResult(arith.getResult());
|
||||
node.addArg(firstArg);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,34 +1,58 @@
|
||||
package jadx.tests.integration.conditions;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.NotYetImplemented;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
public class TestXor extends IntegrationTest {
|
||||
public class TestXor extends SmaliTest {
|
||||
|
||||
public static class TestCls {
|
||||
public boolean test() {
|
||||
return test2() ^ true;
|
||||
public boolean test1() {
|
||||
return test() ^ true;
|
||||
}
|
||||
|
||||
public boolean test2() {
|
||||
public boolean test2(boolean v) {
|
||||
return v ^ true;
|
||||
}
|
||||
|
||||
public boolean test() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@NotYetImplemented
|
||||
public void test409() {
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, not(containsOne("1")));
|
||||
assertThat(code, containsOne("return !test();"));
|
||||
assertThat(code, containsOne("return !v;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void smali() {
|
||||
/*
|
||||
public boolean test1() {
|
||||
return test() ^ true;
|
||||
}
|
||||
|
||||
public boolean test2() {
|
||||
return test() ^ false;
|
||||
}
|
||||
|
||||
public boolean test() {
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestXor");
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("return !test();"));
|
||||
assertThat(code, containsOne("return test();"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
.class public LTestXor;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>()V
|
||||
.locals 0
|
||||
|
||||
.line 9
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
|
||||
# virtual methods
|
||||
.method public test()Z
|
||||
.locals 1
|
||||
|
||||
.line 20
|
||||
const/4 v0, 0x1
|
||||
|
||||
return v0
|
||||
.end method
|
||||
|
||||
.method public test1()Z
|
||||
.locals 1
|
||||
|
||||
.line 12
|
||||
invoke-virtual {p0}, Lcom/example/myapplication/MainActivity;->test()Z
|
||||
|
||||
move-result v0
|
||||
|
||||
xor-int/lit8 v0, v0, 0x1
|
||||
|
||||
return v0
|
||||
.end method
|
||||
|
||||
.method public test2()Z
|
||||
.locals 1
|
||||
|
||||
.line 16
|
||||
invoke-virtual {p0}, Lcom/example/myapplication/MainActivity;->test()Z
|
||||
|
||||
move-result v0
|
||||
|
||||
xor-int/lit8 v0, v0, 0x0
|
||||
|
||||
return v0
|
||||
.end method
|
||||
Reference in New Issue
Block a user