diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java index 6dc4846f8c..e9acade0db 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java @@ -1,10 +1,9 @@ package net.runelite.deob.deobfuscators.rename; +import edu.ucla.sspace.graph.Edge; import edu.ucla.sspace.graph.Graph; import edu.ucla.sspace.graph.isomorphism.IsomorphismTester; -import edu.ucla.sspace.graph.isomorphism.TypedVF2IsomorphismTester; import edu.ucla.sspace.graph.isomorphism.VF2IsomorphismTester; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -15,10 +14,9 @@ import java.util.Set; 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.InvokeInstruction; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; +import net.runelite.deob.execution.MethodContext; public class Rename { @@ -33,13 +31,54 @@ public class Rename // methods which have been processed in the original private Set processed = new HashSet<>(); + private static String cname(Method m) { return m.getMethods().getClassFile().getName(); } + private static String mname(Method m) { return cname(m) + "." + m.getName(); } + + private void compare(MethodContext m1, Graph g1, MethodContext m2, Graph g2) + { + Set edges = new HashSet<>(g1.edges()); // edges in g1 not in g2 + for (Edge e : (Set) g2.edges()) + { + edges.remove(e); + } + + for (Edge e : edges) + { + Method me1 = m1.getIdMap().get(e.from()).get(0); + Method me2 = m1.getIdMap().get(e.to()).get(0); + + System.out.println("EDGE IN 1 NOT IN 2: " + mname(me1) + " -> " + mname(me2)); + + Method om1 = m2.getIdMap().get(e.from()).get(0); + Method om2 = m2.getIdMap().get(e.to()).get(0); + + System.out.println(" OTHER SIDE: " + mname(om1) + " -> " + mname(om2)); + } + //System.out.println(edges); + + if (g2.order() == g1.order()) + { + int[] v1 = g1.vertices().toPrimitiveArray(), + v2 = g2.vertices().toPrimitiveArray(); + for (int i = 0; i < g1.order(); ++i) + { + Method me1 = m1.getIdMap().get(v1[i]).get(0); + Method me2 = m2.getIdMap().get(v2[i]).get(0); + + System.out.println("VMATCH " + mname(me1) + " -> " + mname(me2)); + } + } + } + private boolean compare(Frame f1, Frame f2) { Graph g1 = f1.getMethodCtx().getGraph(), g2 = f2.getMethodCtx().getGraph(); IsomorphismTester isoTest = new /*Typed*/VF2IsomorphismTester(); - if (!isoTest.areIsomorphic(g1, g2)) + if (g1.size() != g2.size() || g1.order() != g2.order() || !isoTest.areIsomorphic(g1, g2)) { + System.out.println("IN " + mname(f1.getMethod()) + " -> " + mname(f2.getMethod())); + compare(f1.getMethodCtx(), g1, f2.getMethodCtx(), g2); System.out.println("Not isomorphic " + g1.size() + " " + g2.size()); return false; } @@ -129,6 +168,7 @@ public class Rename if (!b) { System.out.println("Mismatch " + p1.getMethod().getMethods().getClassFile().getName() + "." + p1.getMethod().getName() + " <-> " + p2.getMethod().getMethods().getClassFile().getName() + "." + p2.getMethod().getName()); + System.out.println(one.getMethods().getClassFile().getName() + "." + one.getName() + " and " + two.getMethods().getClassFile().getName() + "." + two.getName()); int i =7; } break outer2; @@ -141,35 +181,35 @@ public class Rename groupOne = one; groupTwo = two; - Execution eone = new Execution(one); - eone.setBuildGraph(true); - eone.setFollowInvokes(false); - eone.populateInitialMethods(); - List initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); - eone.run(); - - Execution etwo = new Execution(two); - etwo.setBuildGraph(true); - etwo.setFollowInvokes(false); - etwo.populateInitialMethods(); - List initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); - etwo.run(); - - assert initial1.size() == initial2.size(); - - for (int i = 0; i < initial1.size(); ++i) - { - Method m1 = initial1.get(i), m2 = initial2.get(i); - - assert m1.getName().equals(m2.getName()); - - objMap.put(m1, m2); - } +// Execution eone = new Execution(one); +// eone.setBuildGraph(true); +// eone.setFollowInvokes(false); +// eone.populateInitialMethods(); +// List initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); +// eone.run(); +// +// Execution etwo = new Execution(two); +// etwo.setBuildGraph(true); +// etwo.setFollowInvokes(false); +// etwo.populateInitialMethods(); +// List initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); +// etwo.run(); +// +// assert initial1.size() == initial2.size(); +// +// for (int i = 0; i < initial1.size(); ++i) +// { +// Method m1 = initial1.get(i), m2 = initial2.get(i); +// +// assert m1.getName().equals(m2.getName()); +// +// objMap.put(m1, m2); +// } -// process( -// one.findClass("class143").findMethod("method3014"), -// two.findClass("class143").findMethod("method2966") -// ); + process( + one.findClass("client").findMethod("vmethod2999"), + two.findClass("client").findMethod("vmethod2978") + ); for (;;) { diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index ee5ec36dc5..4f27b994fd 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -118,6 +118,8 @@ public class Execution public void invoke(InstructionContext from, Method to) { + Frame frame = from.getFrame(); + if (!this.isFollowInvokes() && !to.isStatic()) return; @@ -127,6 +129,9 @@ public class Execution Frame f = new Frame(this, to); f.initialize(from); this.addFrame(f); + + // if (!this.followInvokes && to.isStatic()) + // frame.stop(); // frames continue from the method } public void addMethod(Method to) @@ -145,13 +150,21 @@ public class Execution methods.add(frame.getMethod()); + if (!frame.isExecuting()) + { + frames.remove(0); + processedFrames.add(frame); + continue; + } + ++fcount; + assert frame.isExecuting(); frame.execute(); if (!frame.isExecuting()) { - assert frames.get(0) == frame; - frames.remove(0); + //assert frames.get(0) == frame; + frames.remove(frame); processedFrames.add(frame); } else diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index 3e0d13f536..14afe0289f 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -1,15 +1,8 @@ package net.runelite.deob.execution; import com.google.common.collect.Lists; -import edu.ucla.sspace.graph.DirectedEdge; -import edu.ucla.sspace.graph.Graph; -import edu.ucla.sspace.graph.SimpleDirectedEdge; -import edu.ucla.sspace.graph.SparseDirectedGraph; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; import net.runelite.deob.Method; import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.Exception; @@ -17,8 +10,7 @@ import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.pool.NameAndType; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; -import net.runelite.deob.util.IdGen; -import org.apache.commons.collections4.map.MultiValueMap; +import net.runelite.deob.attributes.code.instruction.types.ReturnInstruction; import org.apache.commons.lang3.mutable.MutableInt; public class Frame @@ -34,6 +26,7 @@ public class Frame protected MutableInt prevVertex = new MutableInt(-1); //protected int prevVertex = -1; //private List prevInvokes; + private Frame from; public Frame(Execution execution, Method method) { @@ -70,8 +63,10 @@ public class Frame // initialize frame from invoking context assert ctx.getInstruction() instanceof InvokeInstruction; - if (this.getMethod().isStatic()) + if (!this.getExecution().isFollowInvokes() && this.getMethod().isStatic()) { + assert from == null; + from = ctx.getFrame(); this.ctx = ctx.getFrame().ctx; // share ctx if this method is static this.prevVertex = ctx.getFrame().prevVertex; } @@ -111,6 +106,7 @@ public class Frame this.ctx = other.ctx; this.prevVertex = new MutableInt(other.prevVertex); //this.prevInvokes = other.prevInvokes; + from = other.from; } public Frame dup() @@ -179,6 +175,10 @@ public class Frame { Instruction oldCur = cur; + if (cur instanceof ReturnInstruction) + if (processReturn()) + break; + try { cur.execute(this); @@ -225,7 +225,11 @@ public class Frame } if (!execution.frames.isEmpty() && execution.frames.get(0) != this) + { + stop(); // the prev frame must be an invokestatic? + assert execution.frames.get(0).getMethod().isStatic(); break; + } } } @@ -271,4 +275,25 @@ public class Frame cur = to; } + + private boolean processReturn() + { + if (this.getExecution().isFollowInvokes() || !this.getMethod().isStatic()) + return false; + + if (from == null) + return false; + + assert !from.isExecuting(); + + // update method, cur, stack, variables, from outermost method + this.method = from.method; + //this.executing = from.executing; + this.cur = from.cur; + this.stack = new Stack(from.stack); + this.variables = new Variables(from.variables); + + //stop(); // now that weve switched this should still be running + return true; // this stops frame execution + } }