From b310e92d7abc015d188540ff8e5aaa31aa98da82 Mon Sep 17 00:00:00 2001 From: Skylot Date: Sat, 21 Oct 2023 21:57:56 +0100 Subject: [PATCH] fix: inline CMP instructions to help conditions merge (#2033) --- .../jadx/core/dex/visitors/ModVisitor.java | 28 ++++ .../java/jadx/core/utils/ErrorsCounter.java | 7 +- .../conditions/TestTernaryInIf3.java | 14 ++ .../smali/conditions/TestTernaryInIf3.smali | 157 ++++++++++++++++++ 4 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf3.java create mode 100644 jadx-core/src/test/smali/conditions/TestTernaryInIf3.smali diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java index d04c5c2aac2..1c4c9e1ea97 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java @@ -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.JadxRuntimeException; import static jadx.core.utils.BlockUtils.replaceInsn; +import static jadx.core.utils.ListUtils.allMatch; /** * Visitor for modify method instructions @@ -139,6 +141,11 @@ private static void replaceStep(MethodNode mth, InsnRemover remover) { 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 @@ private static void processArith(MethodNode mth, ClassNode parentClass, ArithNod } } + /** + * 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 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); diff --git a/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java b/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java index 8d53ce04f63..949a9d2e502 100644 --- a/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java +++ b/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java @@ -10,6 +10,7 @@ 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 @@ 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 errorNodes = new HashSet<>(); private int errorsCount; @@ -44,7 +45,9 @@ private synchronized String addError(N nod 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); diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf3.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf3.java new file mode 100644 index 00000000000..d341a5dfe2e --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf3.java @@ -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(); + } +} diff --git a/jadx-core/src/test/smali/conditions/TestTernaryInIf3.smali b/jadx-core/src/test/smali/conditions/TestTernaryInIf3.smali new file mode 100644 index 00000000000..524344af1fb --- /dev/null +++ b/jadx-core/src/test/smali/conditions/TestTernaryInIf3.smali @@ -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