diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java index 0fea36715..18a2f14ca 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java @@ -77,7 +77,7 @@ public abstract class InsnArg extends Typed { return parentInsn; } - public void setParentInsn(InsnNode parentInsn) { + public void setParentInsn(@Nullable InsnNode parentInsn) { this.parentInsn = parentInsn; } @@ -88,7 +88,6 @@ public abstract class InsnArg extends Typed { } if (parent == insn) { LOG.debug("Can't wrap instruction info itself: {}", insn); - Thread.dumpStack(); return null; } int i = getArgIndex(parent, this); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java index 686428bad..bb771e1a1 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.ListIterator; import java.util.Set; +import org.jetbrains.annotations.Nullable; + public class CodeShrinker extends AbstractVisitor { @Override @@ -227,15 +229,16 @@ public class CodeShrinker extends AbstractVisitor { if (assignBlock != null && assignInsn != arg.getParentInsn() && canMoveBetweenBlocks(assignInsn, assignBlock, block, argsInfo.getInsn())) { - arg.wrapInstruction(assignInsn); - InsnList.remove(assignBlock, assignInsn); + if (inline(arg, assignInsn, assignBlock, mth)) { + InsnList.remove(assignBlock, assignInsn); + } } } } } if (!wrapList.isEmpty()) { for (WrapInfo wrapInfo : wrapList) { - wrapInfo.getArg().wrapInstruction(wrapInfo.getInsn()); + inline(wrapInfo.getArg(), wrapInfo.getInsn(), block, mth); } for (WrapInfo wrapInfo : wrapList) { insnList.remove(wrapInfo.getInsn()); @@ -243,6 +246,29 @@ public class CodeShrinker extends AbstractVisitor { } } + private static boolean inline(RegisterArg arg, InsnNode insn, @Nullable BlockNode block, MethodNode mth) { + InsnNode parentInsn = arg.getParentInsn(); + // replace move instruction if needed + if (parentInsn != null && parentInsn.getType() == InsnType.MOVE) { + if (block == null) { + block = BlockUtils.getBlockByInsn(mth, parentInsn); + } + if (block != null) { + int index = InsnList.getIndex(block.getInstructions(), parentInsn); + if (index != -1) { + insn.setResult(parentInsn.getResult()); + insn.copyAttributesFrom(parentInsn); + insn.setOffset(parentInsn.getOffset()); + + block.getInstructions().set(index, insn); + return true; + } + } + } + // simple case + return arg.wrapInstruction(insn) != null; + } + private static boolean canMoveBetweenBlocks(InsnNode assignInsn, BlockNode assignBlock, BlockNode useBlock, InsnNode useInsn) { if (!BlockUtils.isPathExists(assignBlock, useBlock)) { @@ -300,7 +326,7 @@ public class CodeShrinker extends AbstractVisitor { for (RegisterArg rarg : list) { InsnNode ai = rarg.getAssignInsn(); if (ai != assignInsn && ai != null && ai != rarg.getParentInsn()) { - rarg.wrapInstruction(ai); + inline(rarg, ai, null, mth); } } // remove method args diff --git a/jadx-core/src/test/java/jadx/tests/smali/TestInlineVarArg.java b/jadx-core/src/test/java/jadx/tests/smali/TestInlineVarArg.java new file mode 100644 index 000000000..50b934838 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/smali/TestInlineVarArg.java @@ -0,0 +1,21 @@ +package jadx.tests.smali; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.SmaliTest; + +import org.junit.Test; + +import static jadx.tests.api.utils.JadxMatchers.containsOne; +import static org.junit.Assert.assertThat; + +public class TestInlineVarArg extends SmaliTest { + + @Test + public void test() { + noDebugInfo(); + ClassNode cls = getClassNodeFromSmali("TestInlineVarArg"); + String code = cls.getCode().toString(); + + assertThat(code, containsOne("f(\"a\", \"b\", \"c\");")); + } +} diff --git a/jadx-core/src/test/smali/TestInlineVarArg.smali b/jadx-core/src/test/smali/TestInlineVarArg.smali new file mode 100644 index 000000000..7c62c667d --- /dev/null +++ b/jadx-core/src/test/smali/TestInlineVarArg.smali @@ -0,0 +1,41 @@ +.class public LTestInlineVarArg; +.super Ljava/lang/Object; + +.method public static varargs f([Ljava/lang/String;)V + .registers 1 + return-void +.end method + +.method public test()V + .registers 5 + + const/4 v2, 0x3 + + new-array v1, v2, [Ljava/lang/String; + + move-object v0, v1 + + const/4 v2, 0x0 + + const-string v3, "a" + + aput-object v3, v0, v2 + + const/4 v2, 0x1 + + const-string v3, "b" + + aput-object v3, v0, v2 + + const/4 v2, 0x2 + + const-string v3, "c" + + aput-object v3, v0, v2 + + move-object v1, v0 + + invoke-static {v1}, LTestInlineVarArg;->f([Ljava/lang/String;)V + + return-void +.end method