-
Notifications
You must be signed in to change notification settings - Fork 5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
13 changed files
with
342 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
jadx-core/src/main/java/jadx/core/dex/instructions/InvokePolymorphicNode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package jadx.core.dex.instructions; | ||
|
||
import jadx.api.plugins.input.data.IMethodProto; | ||
import jadx.api.plugins.input.insns.InsnData; | ||
import jadx.core.dex.info.MethodInfo; | ||
import jadx.core.dex.nodes.InsnNode; | ||
import jadx.core.utils.InsnUtils; | ||
|
||
public class InvokePolymorphicNode extends InvokeNode { | ||
private final IMethodProto proto; | ||
private final MethodInfo baseCallRef; | ||
|
||
public InvokePolymorphicNode(MethodInfo callMth, InsnData insn, IMethodProto proto, MethodInfo baseRef, boolean isRange) { | ||
super(callMth, insn, InvokeType.POLYMORPHIC, true, isRange); | ||
this.proto = proto; | ||
this.baseCallRef = baseRef; | ||
} | ||
|
||
public InvokePolymorphicNode(MethodInfo callMth, int argsCount, IMethodProto proto, MethodInfo baseRef) { | ||
super(callMth, InvokeType.POLYMORPHIC, argsCount); | ||
this.proto = proto; | ||
this.baseCallRef = baseRef; | ||
} | ||
|
||
public IMethodProto getProto() { | ||
return proto; | ||
} | ||
|
||
public MethodInfo getBaseCallRef() { | ||
return baseCallRef; | ||
} | ||
|
||
@Override | ||
public InsnNode copy() { | ||
InvokePolymorphicNode copy = new InvokePolymorphicNode(getCallMth(), getArgsCount(), proto, baseCallRef); | ||
copyCommonParams(copy); | ||
return copy; | ||
} | ||
|
||
@Override | ||
public boolean isSame(InsnNode obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
if (!(obj instanceof InvokePolymorphicNode) || !super.isSame(obj)) { | ||
return false; | ||
} | ||
InvokePolymorphicNode other = (InvokePolymorphicNode) obj; | ||
return proto.equals(other.proto); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
StringBuilder sb = new StringBuilder(); | ||
sb.append(InsnUtils.formatOffset(offset)).append(": INVOKE_POLYMORPHIC "); | ||
if (getResult() != null) { | ||
sb.append(getResult()).append(" = "); | ||
} | ||
if (!appendArgs(sb)) { | ||
sb.append('\n'); | ||
} | ||
sb.append(" base: ").append(baseCallRef).append('\n'); | ||
sb.append(" proto: ").append(proto).append('\n'); | ||
return sb.toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
jadx-core/src/test/java/jadx/tests/integration/invoke/TestPolymorphicInvoke.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package jadx.tests.integration.invoke; | ||
|
||
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.MethodType; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import jadx.core.dex.nodes.ClassNode; | ||
import jadx.tests.api.SmaliTest; | ||
import jadx.tests.api.extensions.profiles.TestProfile; | ||
import jadx.tests.api.extensions.profiles.TestWithProfiles; | ||
|
||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; | ||
import static org.junit.jupiter.api.Assertions.fail; | ||
|
||
public class TestPolymorphicInvoke extends SmaliTest { | ||
|
||
public static class TestCls { | ||
public String func(int a, int c) { | ||
return String.valueOf(a + c); | ||
} | ||
|
||
public String test() { | ||
try { | ||
MethodType methodType = MethodType.methodType(String.class, Integer.TYPE, Integer.TYPE); | ||
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(TestCls.class, "func", methodType); | ||
return (String) methodHandle.invoke(this, 1, 2); | ||
} catch (Throwable e) { | ||
fail(e); | ||
return null; | ||
} | ||
} | ||
|
||
public void check() { | ||
assertThat(test()).isEqualTo("3"); | ||
} | ||
} | ||
|
||
@TestWithProfiles({ TestProfile.DX_J8, TestProfile.D8_J11 }) | ||
public void test() { | ||
ClassNode cls = getClassNode(TestCls.class); | ||
assertThat(cls).code() | ||
.containsOne("return (String) methodHandle.invoke(this, 1, 2);"); | ||
assertThat(cls).disasmCode() | ||
.containsOne("invoke-polymorphic"); | ||
} | ||
|
||
@TestWithProfiles({ TestProfile.JAVA8, TestProfile.JAVA11 }) | ||
public void testJava() { | ||
assertThat(getClassNode(TestCls.class)) | ||
.code() | ||
.containsOne("return (String) methodHandle.invoke(this, 1, 2);"); | ||
// java uses 'invokevirtual' | ||
} | ||
|
||
@Test | ||
public void testSmali() { | ||
assertThat(getClassNodeFromSmali()) | ||
.code() | ||
.containsOne("String ret = (String) methodHandle.invoke(this, 10, 20);"); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
jadx-core/src/test/java/jadx/tests/integration/invoke/TestPolymorphicRangeInvoke.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package jadx.tests.integration.invoke; | ||
|
||
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.MethodType; | ||
|
||
import jadx.core.dex.nodes.ClassNode; | ||
import jadx.tests.api.IntegrationTest; | ||
import jadx.tests.api.extensions.profiles.TestProfile; | ||
import jadx.tests.api.extensions.profiles.TestWithProfiles; | ||
|
||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; | ||
import static org.junit.jupiter.api.Assertions.fail; | ||
|
||
public class TestPolymorphicRangeInvoke extends IntegrationTest { | ||
|
||
public static class TestCls { | ||
public String func2(int a, int b, int c, int d, int e, int f) { | ||
return String.valueOf(a + b + c + d + e + f); | ||
} | ||
|
||
public String test() { | ||
try { | ||
MethodHandles.Lookup lookup = MethodHandles.lookup(); | ||
MethodType methodType = MethodType.methodType(String.class, Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, | ||
Integer.TYPE, Integer.TYPE); | ||
MethodHandle methodHandle = lookup.findVirtual(TestCls.class, "func2", methodType); | ||
return (String) methodHandle.invoke(this, 10, 20, 30, 40, 50, 60); | ||
} catch (Throwable e) { | ||
fail(e); | ||
return null; | ||
} | ||
} | ||
|
||
public void check() { | ||
assertThat(test()).isEqualTo("210"); | ||
} | ||
} | ||
|
||
@TestWithProfiles({ TestProfile.DX_J8 }) | ||
public void test() { | ||
ClassNode cls = getClassNode(TestCls.class); | ||
assertThat(cls).code() | ||
.containsOne("return (String) methodHandle.invoke(this, 10, 20, 30, 40, 50, 60);"); | ||
assertThat(cls).disasmCode() | ||
.containsOne("invoke-polymorphic/range"); | ||
} | ||
} |
Oops, something went wrong.