From d029c128e33d2678c975982130f005a8da3aa6ec Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 1 Jan 2016 19:01:40 -0500 Subject: [PATCH] Allow parallel mapping executor to step through static methods if it encounters an invokestatic that doesn't match the other executor. Maybe works. Hitting an ifnull vs if check fail in my test. --- .../rename/MappingExecutorUtil.java | 4 +- .../net/runelite/deob/execution/Frame.java | 15 +++- .../execution/ParallellMappingExecutor.java | 86 +++++++++++++++++++ .../deobfuscators/rename/MapStaticTest.java | 36 ++++++++ .../deob/deobfuscators/rename/MapTest.java | 13 +-- 5 files changed, 137 insertions(+), 17 deletions(-) create mode 100644 src/test/java/net/runelite/deob/deobfuscators/rename/MapStaticTest.java 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"));