diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/MappingExecutorUtil.java b/src/main/java/net/runelite/deob/deobfuscators/rename/MappingExecutorUtil.java index 330bc2e887..8bb8bb4a74 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/MappingExecutorUtil.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/MappingExecutorUtil.java @@ -92,8 +92,8 @@ public class MappingExecutorUtil System.out.println(p1.getInstruction() + " <-> " + p2.getInstruction()); - assert p1.getInstruction().getInstructions().getCode().getAttributes().getMethod() == m1; - assert p2.getInstruction().getInstructions().getCode().getAttributes().getMethod() == m2; + //assert p1.getInstruction().getInstructions().getCode().getAttributes().getMethod() == m1; + //assert p2.getInstruction().getInstructions().getCode().getAttributes().getMethod() == m2; assert p1.getInstruction() instanceof MappableInstruction; assert p2.getInstruction() instanceof MappableInstruction; diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index 760750eb97..035f9c3da0 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -30,6 +30,7 @@ public class Frame protected Method nonStatic; // next non static method up the stack private Frame caller; public Frame other; // in the other execution for mapping + public Frame returnTo; // is this the same as caller? public Frame(Execution execution, Method method) { @@ -219,9 +220,7 @@ public class Frame if (oldCur == cur) { - int idx = instructions.indexOf(cur); - assert idx != -1; - cur = instructions.get(idx + 1); + this.nextInstruction(); } else { @@ -236,6 +235,16 @@ public class Frame } } + public void nextInstruction() + { + Instructions ins = method.getCode().getInstructions(); + List instructions = ins.getInstructions(); + + int idx = instructions.indexOf(cur); + assert idx != -1; + cur = instructions.get(idx + 1); + } + private void processExceptions(Instruction i) { if (this.execution.step) diff --git a/src/main/java/net/runelite/deob/execution/ParallellMappingExecutor.java b/src/main/java/net/runelite/deob/execution/ParallellMappingExecutor.java index e205fe6864..880cfb7edc 100644 --- a/src/main/java/net/runelite/deob/execution/ParallellMappingExecutor.java +++ b/src/main/java/net/runelite/deob/execution/ParallellMappingExecutor.java @@ -1,5 +1,9 @@ package net.runelite.deob.execution; +import net.runelite.deob.Method; +import net.runelite.deob.attributes.code.instruction.types.ReturnInstruction; +import net.runelite.deob.attributes.code.instructions.InvokeStatic; + public class ParallellMappingExecutor { private Execution e, e2; @@ -44,10 +48,24 @@ public class ParallellMappingExecutor // step frame f1.execute(); f2.execute(); + + f1 = popStack(f1); + f2 = popStack(f2); // get what each frame is paused/exited on p1 = f1.getInstructions().get(f1.getInstructions().size() - 1); p2 = f2.getInstructions().get(f2.getInstructions().size() - 1); + + if (p1.getInstruction() instanceof InvokeStatic && !(p2.getInstruction() instanceof InvokeStatic)) + { + f1 = stepInto(f1); + p1 = f1.getInstructions().get(f1.getInstructions().size() - 1); + } + else if (p2.getInstruction() instanceof InvokeStatic && !(p1.getInstruction() instanceof InvokeStatic)) + { + f2 = stepInto(f2); + p2 = f2.getInstructions().get(f2.getInstructions().size() - 1); + } // frames can stop executing at different times if one sees a jump // that has been done before, so stop both and remove the pending branch @@ -89,4 +107,72 @@ public class ParallellMappingExecutor { return p2; } + + private Frame stepInto(Frame f) + { + Execution e = f.getExecution(); + + assert e == this.e || e == e2; + assert e.frames.get(0) == f; + + InstructionContext i = f.getInstructions().get(f.getInstructions().size() - 1); + assert i.getInstruction() instanceof InvokeStatic; + + InvokeStatic is = (InvokeStatic) i.getInstruction(); + Method to = is.getMethods().get(0); + + Frame f2 = new Frame(e, to); + f2.initialize(i); + + e.frames.remove(0); // old frame goes away + e.frames.add(0, f2); + + assert f.other.other == f; + + f2.other = f.other; // even though theyre in different methods + f.other.other = f2; + + f.other = null; + + f2.returnTo = new Frame(f); // where to go when we're done + + // step new frame + f2.execute(); + + return f2; + } + + private Frame popStack(Frame f) + { + Execution e = f.getExecution(); + + if (f.isExecuting() || f.returnTo == null) + return f; + + InstructionContext i = f.getInstructions().get(f.getInstructions().size() - 1); + if (!(i.getInstruction() instanceof ReturnInstruction)) + return f; + + assert e.frames.contains(f); + assert !e.frames.contains(f.returnTo); + + // replace frame with returnTo + assert e.frames.get(0) == f; + e.frames.remove(0); + e.frames.add(0, f.returnTo); + + assert f.other.other == f; + assert f.returnTo.other == null; + + Frame newFrame = f.returnTo; + newFrame.other = f.other; + newFrame.other.other = newFrame; + + f.other = null; + + // step return frame + f.returnTo.execute(); + + return f.returnTo; + } } diff --git a/src/test/java/net/runelite/deob/deobfuscators/rename/MapStaticTest.java b/src/test/java/net/runelite/deob/deobfuscators/rename/MapStaticTest.java new file mode 100644 index 0000000000..ec715f200e --- /dev/null +++ b/src/test/java/net/runelite/deob/deobfuscators/rename/MapStaticTest.java @@ -0,0 +1,36 @@ +package net.runelite.deob.deobfuscators.rename; + +import java.io.File; +import java.io.IOException; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Method; +import net.runelite.deob.util.JarUtil; +import org.junit.Assert; +import org.junit.Test; + +public class MapStaticTest +{ + //@Test + public void testMappable() throws IOException + { + ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")); + ClassGroup group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar")); + +// Assert.assertTrue(MappingExecutorUtil.isMappable( +// group1.findClass("class99").findMethod("method2220"), +// group2.findClass("class99").findMethod("method2149") +// )); + } + + @Test + public void test() throws IOException + { + ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")); + ClassGroup group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar")); + + Method m1 = group1.findClass("client").findMethod("vmethod3050"); + Method m2 = group2.findClass("client").findMethod("vmethod3007"); + + ParallelExecutorMapping mappings = MappingExecutorUtil.map(m1, m2); + } +} diff --git a/src/test/java/net/runelite/deob/deobfuscators/rename/MapTest.java b/src/test/java/net/runelite/deob/deobfuscators/rename/MapTest.java index e989bc4256..737296ce6e 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/rename/MapTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/rename/MapTest.java @@ -2,19 +2,8 @@ package net.runelite.deob.deobfuscators.rename; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import net.runelite.deob.ClassGroup; import net.runelite.deob.Method; -import net.runelite.deob.attributes.code.Instruction; -import net.runelite.deob.attributes.code.instruction.types.MappableInstruction; -import net.runelite.deob.execution.Execution; -import net.runelite.deob.execution.Frame; -import net.runelite.deob.execution.InstructionContext; -import net.runelite.deob.execution.ParallellMappingExecutor; import net.runelite.deob.util.JarUtil; import org.junit.Assert; import org.junit.Test; @@ -34,7 +23,7 @@ public class MapTest } @Test - public void main() throws IOException + public void test() throws IOException { ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")); ClassGroup group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));