diff --git a/jadx-core/src/test/java/jadx/tests/integration/others/TestJavaDup2x2.java b/jadx-core/src/test/java/jadx/tests/integration/others/TestJavaDup2x2.java new file mode 100644 index 00000000000..cb8fdcfe44f --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/others/TestJavaDup2x2.java @@ -0,0 +1,17 @@ +package jadx.tests.integration.others; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.RaungTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestJavaDup2x2 extends RaungTest { + + @Test + public void test() { + assertThat(getClassNodeFromRaung()) + .code() + .containsOne("dArr[0] = 127.5d;"); + } +} diff --git a/jadx-core/src/test/raung/others/TestJavaDup2x2.raung b/jadx-core/src/test/raung/others/TestJavaDup2x2.raung new file mode 100644 index 00000000000..f6fdd0cb7e9 --- /dev/null +++ b/jadx-core/src/test/raung/others/TestJavaDup2x2.raung @@ -0,0 +1,24 @@ +.version 45.3 +.class others/TestJavaDup2x2 + +.auto frames + +.method public static test([D)V + aload 0 + iconst_0 + aload 0 + iconst_1 + aload 0 + iconst_2 + aload 0 + iconst_3 + ldc2_w 127.5 + dup2_x2 + dastore + dup2_x2 + dastore + dup2_x2 + dastore + dastore + return +.end method diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java index 1802f9afdf1..9e891bd916d 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/CodeDecodeState.java @@ -9,6 +9,7 @@ import jadx.plugins.input.java.data.JavaClassData; import jadx.plugins.input.java.data.code.StackState.SVType; +@SuppressWarnings("UnusedReturnValue") public class CodeDecodeState { private final JavaClassData clsData; private final DataReader reader; @@ -35,6 +36,7 @@ public void onInsn(int offset) { this.stack = stackState; } if (excHandlers.contains(offset)) { + clear(); stack.push(SVType.NARROW); // push exception excHandler = true; } else { @@ -112,6 +114,10 @@ public CodeDecodeState pushWide(int arg) { return this; } + public int insert(int pos, SVType type) { + return stack.insert(pos, type); + } + public void discard() { stack.pop(); } @@ -124,8 +130,9 @@ public void discardWord() { } } - public void clear() { + public CodeDecodeState clear() { stack.clear(); + return this; } public int push(String type) { diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java index 8c5783eacf6..5074de1ba3e 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java @@ -70,12 +70,11 @@ public void visitInstructions(Consumer insnConsumer) { if (insnInfo == null) { throw new JavaClassParseException("Unknown opcode: 0x" + Integer.toHexString(opcode)); } - insn.setInsnInfo(insnInfo); + insn.setOpcodeUnit(opcode); insn.setInsnInfo(insnInfo); insn.setRegsCount(insnInfo.getRegsCount()); insn.setOpcode(insnInfo.getApiOpcode()); insn.setPayloadSize(insnInfo.getPayloadSize()); - insn.setOpcodeUnit(opcode); insn.setPayload(null); state.onInsn(offset); diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java index e2d5b7960e0..92af7f3340c 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java @@ -158,21 +158,8 @@ public class JavaInsnsRegister { s.peek(1).push(0, s.peekType(1)); } }); - register(arr, 0x5d, "dup2_x1", 0, 10, Opcode.MOVE_MULTI, - s -> { - if (s.peekType(0) == NARROW) { - s.push(0, NARROW).peekFrom(2, 1) - .push(2, NARROW).peekFrom(2, 3) - .peekFrom(2, 4).peekFrom(4, 5) - .peekFrom(3, 6).peekFrom(0, 7) - .peekFrom(4, 8).peekFrom(1, 9); - } else { - s.insn().setRegsCount(6); - s.push(0, WIDE).peekFrom(1, 1) - .peekFrom(1, 2).peekFrom(2, 3) - .peekFrom(2, 4).peekFrom(0, 5); - } - }); + register(arr, 0x5d, "dup2_x1", 0, 10, Opcode.MOVE_MULTI, JavaInsnsRegister::dup2x1); + register(arr, 0x5e, "dup2_x2", 0, 12, Opcode.MOVE_MULTI, JavaInsnsRegister::dup2x2); register(arr, 0x5f, "swap", 0, 6, Opcode.MOVE_MULTI, s -> s.peekFrom(-1, 0).peekFrom(1, 1) .peekFrom(1, 2).peekFrom(0, 3) @@ -309,6 +296,44 @@ public class JavaInsnsRegister { register(arr, 0xc8, "goto_w", 4, 0, Opcode.GOTO, s -> s.jump(s.reader().readS4())); } + private static void dup2x1(CodeDecodeState s) { + if (s.peekType(0) == NARROW) { + s.insert(2, NARROW); + s.insert(2, NARROW); + s.peekFrom(0, 0).peekFrom(2, 1); + s.peekFrom(1, 2).peekFrom(3, 3); + s.peekFrom(2, 4).peekFrom(4, 5); + s.peekFrom(3, 6).peekFrom(0, 7); + s.peekFrom(4, 8).peekFrom(1, 9); + } else { + s.insn().setRegsCount(6); + s.insert(2, WIDE); + s.peekFrom(0, 0).peekFrom(1, 1); + s.peekFrom(1, 2).peekFrom(2, 3); + s.peekFrom(2, 4).peekFrom(0, 5); + } + } + + private static void dup2x2(CodeDecodeState s) { + if (s.peekType(0) == NARROW) { + s.insert(2, NARROW); + s.insert(2, NARROW); + s.peekFrom(0, 0).peekFrom(2, 1); + s.peekFrom(1, 2).peekFrom(3, 3); + s.peekFrom(2, 4).peekFrom(4, 5); + s.peekFrom(3, 6).peekFrom(5, 7); + s.peekFrom(4, 8).peekFrom(0, 9); + s.peekFrom(5, 10).peekFrom(1, 11); + } else { + s.insn().setRegsCount(8); + s.insert(2, WIDE); + s.peekFrom(0, 0).peekFrom(1, 1); + s.peekFrom(1, 2).peekFrom(2, 3); + s.peekFrom(2, 4).peekFrom(3, 5); + s.peekFrom(3, 6).peekFrom(0, 7); + } + } + private static IJavaInsnDecoder newArrayMulti() { return s -> { s.idx(s.u2()); diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java index dc71f123b64..88a8a08a8ca 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/StackState.java @@ -44,6 +44,14 @@ public SVType peekTypeAt(int at) { return SVType.NARROW; } + public int insert(int at, SVType type) { + int p = pos - at; + System.arraycopy(stack, p, stack, p + 1, at); + stack[p] = type; + pos++; + return p; + } + public int push(SVType type) { int p = ++pos; if (checkStackIndex(p)) {