fix: inline CMP instructions to help conditions merge (#2033)

This commit is contained in:
Skylot
2023-10-21 21:57:56 +01:00
parent 4a92ee07cc
commit b310e92d7a
4 changed files with 204 additions and 2 deletions
@@ -1,5 +1,6 @@
package jadx.core.dex.visitors;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -58,6 +59,7 @@ import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.core.utils.BlockUtils.replaceInsn;
import static jadx.core.utils.ListUtils.allMatch;
/**
* Visitor for modify method instructions
@@ -139,6 +141,11 @@ public class ModVisitor extends AbstractVisitor {
processArith(mth, parentClass, (ArithNode) insn);
break;
case CMP_L:
case CMP_G:
inlineCMPInsns(mth, block, i, insn, remover);
break;
case CHECK_CAST:
removeCheckCast(mth, block, i, (IndexInsnNode) insn);
break;
@@ -348,6 +355,27 @@ public class ModVisitor extends AbstractVisitor {
}
}
/**
* Inline CMP instructions into 'if' to help conditions merging
*/
private static void inlineCMPInsns(MethodNode mth, BlockNode block, int i, InsnNode insn, InsnRemover remover) {
RegisterArg resArg = insn.getResult();
List<RegisterArg> useList = resArg.getSVar().getUseList();
if (allMatch(useList, use -> InsnUtils.isInsnType(use.getParentInsn(), InsnType.IF))) {
for (RegisterArg useArg : new ArrayList<>(useList)) {
InsnNode useInsn = useArg.getParentInsn();
if (useInsn != null) {
InsnArg wrapArg = InsnArg.wrapInsnIntoArg(insn.copyWithoutResult());
if (!useInsn.replaceArg(useArg, wrapArg)) {
mth.addWarnComment("Failed to inline CMP insn: " + insn + " into " + useInsn);
return;
}
}
}
remover.addAndUnbind(insn);
}
}
private static boolean checkArrSizes(MethodNode mth, NewArrayNode newArrInsn, FillArrayInsn fillArrInsn) {
int dataSize = fillArrInsn.getSize();
InsnArg arrSizeArg = newArrInsn.getArg(0);
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.Consts;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.IAttributeNode;
import jadx.core.dex.attributes.nodes.JadxError;
@@ -19,7 +20,7 @@ import jadx.core.utils.exceptions.JadxOverflowException;
public class ErrorsCounter {
private static final Logger LOG = LoggerFactory.getLogger(ErrorsCounter.class);
private static final boolean PRINT_MTH_SIZE = true;
private static final boolean PRINT_MTH_SIZE = Consts.DEBUG;
private final Set<IAttributeNode> errorNodes = new HashSet<>();
private int errorsCount;
@@ -44,7 +45,9 @@ public class ErrorsCounter {
String msg = formatMsg(node, error);
if (PRINT_MTH_SIZE && node instanceof MethodNode) {
msg = "[" + ((MethodNode) node).getInsnsCount() + "] " + msg;
String mthSize = "[" + ((MethodNode) node).getInsnsCount() + "] ";
msg = mthSize + msg;
error = mthSize + error;
}
if (e == null) {
LOG.error(msg);
@@ -0,0 +1,14 @@
package jadx.tests.integration.conditions;
import org.junit.jupiter.api.Test;
import jadx.tests.api.SmaliTest;
public class TestTernaryInIf3 extends SmaliTest {
@Test
public void test() {
disableCompilation();
getClassNodeFromSmali();
}
}
@@ -0,0 +1,157 @@
.class public Lconditions/TestTernaryInIf3;
.super Ljava/lang/Object;
.method public static final A01(LX/73h;FFZ)Landroid/util/Pair;
.registers 7
.line 0
const/4 v1, 0x0
.line 1
cmpl-float v0, p1, v1
.line 2
.line 3
if-eqz v0, :cond_33
.line 4
.line 5
cmpl-float v0, p2, v1
.line 6
.line 7
if-eqz v0, :cond_33
.line 8
.line 9
if-eqz p3, :cond_24
.line 10
.line 11
cmpg-float v0, p2, v1
.line 12
.line 13
if-ltz v0, :cond_26
.line 14
.line 15
:cond_f
iget-object v1, p0, LX/73h;->A00:LX/5Yj;
.line 16
.line 17
const-string v0, "translationXCurveDownwards"
.line 18
.line 19
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;
.line 20
.line 21
.line 22
move-result-object v2
.line 23
iget-object v1, p0, LX/73h;->A00:LX/5Yj;
.line 24
.line 25
const-string v0, "translationYCurveDownwards"
.line 26
.line 27
:goto_1b
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;
.line 28
.line 29
.line 30
move-result-object v0
.line 31
invoke-static {v2, v0}, LX/0xz;->A0F(Ljava/lang/Object;Ljava/lang/Object;)Landroid/util/Pair;
.line 32
.line 33
.line 34
move-result-object v0
.line 35
return-object v0
.line 36
:cond_24
if-lez v0, :cond_f
.line 37
.line 38
:cond_26
iget-object v1, p0, LX/73h;->A00:LX/5Yj;
.line 39
.line 40
const-string v0, "translationXCurveUpwards"
.line 41
.line 42
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;
.line 43
.line 44
.line 45
move-result-object v2
.line 46
iget-object v1, p0, LX/73h;->A00:LX/5Yj;
.line 47
.line 48
const-string v0, "translationYCurveUpwards"
.line 49
.line 50
goto :goto_1b
.line 51
:cond_33
iget-object v1, p0, LX/73h;->A00:LX/5Yj;
.line 52
.line 53
const-string v0, "translationXLinear"
.line 54
.line 55
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;
.line 56
.line 57
.line 58
move-result-object v2
.line 59
iget-object v1, p0, LX/73h;->A00:LX/5Yj;
.line 60
.line 61
const-string v0, "translationYLinear"
.line 62
.line 63
goto :goto_1b
.line 64
.line 65
.line 66
.line 67
.line 68
.line 69
.line 70
.line 71
.line 72
.line 73
.line 74
.line 75
.line 76
.line 77
.end method