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 a7e854060198fa9f16f13dd5c79fe802c9faeaaa..96971ab607341bb79a6377b9e89d0909c9d6690a 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 @@ -86,6 +86,7 @@ public class ModVisitor extends AbstractVisitor { InsnRemover remover = new InsnRemover(mth); replaceStep(mth, remover); removeStep(mth, remover); + iterativeRemoveStep(mth); } private static void replaceStep(MethodNode mth, InsnRemover remover) { @@ -293,6 +294,9 @@ public class ModVisitor extends AbstractVisitor { break; default: + if (insn.contains(AFlag.REMOVE)) { + remover.addAndUnbind(insn); + } break; } } @@ -300,6 +304,33 @@ public class ModVisitor extends AbstractVisitor { } } + private static void iterativeRemoveStep(MethodNode mth) { + boolean changed; + do { + changed = false; + for (BlockNode block : mth.getBasicBlocks()) { + for (InsnNode insn : block.getInstructions()) { + if (insn.getType() == InsnType.MOVE + && insn.isAttrStorageEmpty() + && isResultArgNotUsed(insn)) { + InsnRemover.remove(mth, block, insn); + changed = true; + break; + } + } + } + } while (changed); + } + + private static boolean isResultArgNotUsed(InsnNode insn) { + RegisterArg result = insn.getResult(); + if (result != null) { + SSAVar ssaVar = result.getSVar(); + return ssaVar.getUseCount() == 0; + } + return false; + } + private static void processAnonymousConstructor(MethodNode mth, ConstructorInsn co) { MethodInfo callMth = co.getCallMth(); MethodNode callMthNode = mth.dex().resolveMethod(callMth); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java index 5dfc501e3551de4203d696c4b76814467f581b82..8451d6031e5e23ed6ee9472396eb67fd02480100 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java @@ -422,6 +422,7 @@ public class SSATransform extends AbstractVisitor { if (resArg.getRegNum() != arg.getRegNum() && !resArg.getSVar().isUsedInPhi()) { markThisArgs(resArg); + parentInsn.add(AFlag.REMOVE); parentInsn.add(AFlag.DONT_GENERATE); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/others/TestInsnsBeforeSuper2.java b/jadx-core/src/test/java/jadx/tests/integration/others/TestInsnsBeforeSuper2.java new file mode 100644 index 0000000000000000000000000000000000000000..92dbd26ff4017d6961ebd03e5a9f4b37ece7aeb8 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/others/TestInsnsBeforeSuper2.java @@ -0,0 +1,41 @@ +package jadx.tests.integration.others; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.SmaliTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestInsnsBeforeSuper2 extends SmaliTest { + // @formatter:off + /* + public class TestInsnsBeforeSuper2 extends java.lang.Exception { + private int mErrorType; + + public TestInsnsBeforeSuper2(java.lang.String r9, int r10) { + r8 = this; + r0 = r8 + r1 = r9 + r2 = r10 + r3 = r0 + r4 = r1 + r5 = r2 + r6 = r1 + r0.(r6) + r7 = 0 + r0.mErrorType = r7 + r0.mErrorType = r2 + return + } + } + */ + // @formatter:on + + @Test + public void test() { + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("super(message);") + .containsOne("this.mErrorType = errorType;"); + } +} diff --git a/jadx-core/src/test/smali/others/TestInsnsBeforeSuper2.smali b/jadx-core/src/test/smali/others/TestInsnsBeforeSuper2.smali new file mode 100644 index 0000000000000000000000000000000000000000..c1701b8595df581503bdf5b991ffec4d00fdb3e7 --- /dev/null +++ b/jadx-core/src/test/smali/others/TestInsnsBeforeSuper2.smali @@ -0,0 +1,51 @@ +.class public Lothers/TestInsnsBeforeSuper2; +.super Ljava/lang/Exception; +.source "MyException.java" + +# instance fields +.field private mErrorType:I + + +# direct methods +.method public constructor (Ljava/lang/String;I)V + .locals 8 + + .prologue + move-object v0, p0 + + .local v0, "this":Lothers/TestInsnsBeforeSuper2; + move-object v1, p1 + + .local v1, "message":Ljava/lang/String; + move v2, p2 + + .line 39 + .local v2, "errorType":I + move-object v3, v0 + + .local v3, "this":Lothers/TestInsnsBeforeSuper2; + move-object v4, v1 + + .local v4, "message":Ljava/lang/String; + move v5, v2 + + .line 51 + .end local v0 # "this":Lothers/TestInsnsBeforeSuper2; + .end local v1 # "message":Ljava/lang/String; + .end local v2 # "errorType":I + .local v5, "errorType":I + move-object v6, v1 + + invoke-direct {v0, v6}, Ljava/lang/Exception;->(Ljava/lang/String;)V + + .line 39 + const/4 v7, 0x0 + + iput v7, v0, Lothers/TestInsnsBeforeSuper2;->mErrorType:I + + .line 52 + iput v2, v0, Lothers/TestInsnsBeforeSuper2;->mErrorType:I + + .line 53 + return-void +.end method