From 5e4458ae6eab91777efda1972f5667c8dca3016d Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 Nov 2015 20:46:23 -0500 Subject: [PATCH] Instead execute static functions inline as if they arent there to build the graph. Involved changing the executor to execute new frames as they appear. Can match my simple test method. --- pom.xml | 5 ++ .../deob/deobfuscators/rename/Rename.java | 62 +++++++++---------- .../runelite/deob/execution/Execution.java | 9 +-- .../net/runelite/deob/execution/Frame.java | 23 +++++-- .../deob/execution/MethodContext.java | 39 ++++++------ 5 files changed, 76 insertions(+), 62 deletions(-) diff --git a/pom.xml b/pom.xml index f0f8bb8be5..4b58e1d18a 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,11 @@ gson 2.4 + + org.apache.commons + commons-lang3 + 3.1 + org.slf4j 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 4e890bb320..5e7c8c6372 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java @@ -129,41 +129,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( -// initial1.get(0).getMethod(), -// initial2.get(0).getMethod() -// ); -// processed.add(initial1.get(0).getMethod()); -// process( -// one.findClass("class143").findMethod("run"), -// two.findClass("class143").findMethod("run") -// ); -// processed.add(one.findClass("client").findMethod("init")); + process( + one.findClass("class143").findMethod("method3014"), + two.findClass("class143").findMethod("method2966") + ); for (;;) { diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index 32b3fa753e..7a85773b06 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -115,15 +115,16 @@ public class Execution public void invoke(InstructionContext from, Method to) { - if (!this.isFollowInvokes()) + if (!this.isFollowInvokes() && !to.isStatic()) return; - if (hasInvoked(from, to)) - return; +// if (hasInvoked(from, to)) +// return; Frame f = new Frame(this, to); f.initialize(from); - this.addFrame(f); + frames.add(0, f); + //this.addFrame(f); } public void addMethod(Method to) diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index 21b231d3fa..37e3751334 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -19,6 +19,7 @@ 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 org.apache.commons.lang3.mutable.MutableInt; public class Frame { @@ -30,8 +31,9 @@ public class Frame private Variables variables; private List instructions = new ArrayList<>(); // instructions executed in this frame private MethodContext ctx; - protected int prevVertex = -1; - private List prevInvokes; + protected MutableInt prevVertex = new MutableInt(-1); + //protected int prevVertex = -1; + //private List prevInvokes; public Frame(Execution execution, Method method) { @@ -68,6 +70,12 @@ public class Frame // initialize frame from invoking context assert ctx.getInstruction() instanceof InvokeInstruction; + if (this.getMethod().isStatic()) + { + this.ctx = ctx.getFrame().ctx; // share ctx if this method is static + this.prevVertex = ctx.getFrame().prevVertex; + } + // initialize LVT. the last argument is popped first, and is at arguments[0] List pops = ctx.getPops(); pops = Lists.reverse(new ArrayList<>(pops)); // reverse the list so first argument is at index 0 @@ -101,8 +109,8 @@ public class Frame this.stack = new Stack(other.stack); this.variables = new Variables(other.variables); this.ctx = other.ctx; - this.prevVertex = other.prevVertex; - this.prevInvokes = other.prevInvokes; + this.prevVertex = new MutableInt(other.prevVertex); + //this.prevInvokes = other.prevInvokes; } public Frame dup() @@ -193,12 +201,15 @@ public class Frame execution.executed.add(oldCur); + if (!execution.frames.isEmpty() && execution.frames.get(0) != this) + break; + processExceptions(oldCur); if (oldCur instanceof InvokeInstruction) { InvokeInstruction ii = (InvokeInstruction) oldCur; - this.prevInvokes = ii.getMethods(); + // this.prevInvokes = ii.getMethods(); } if (!executing) @@ -253,7 +264,7 @@ public class Frame assert to.getInstructions() == method.getCode().getInstructions(); assert method.getCode().getInstructions().getInstructions().contains(to); - if (ctx.hasJumped(this.prevInvokes, from, to)) + if (ctx.hasJumped(prevVertex, from, to)) { executing = false; return; diff --git a/src/main/java/net/runelite/deob/execution/MethodContext.java b/src/main/java/net/runelite/deob/execution/MethodContext.java index d91cbdeccc..5a644748f0 100644 --- a/src/main/java/net/runelite/deob/execution/MethodContext.java +++ b/src/main/java/net/runelite/deob/execution/MethodContext.java @@ -15,24 +15,25 @@ import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instructions.InvokeStatic; import net.runelite.deob.util.IdGen; import org.apache.commons.collections4.map.MultiValueMap; +import org.apache.commons.lang3.mutable.MutableInt; class MIKey { - private List method; + private int prevVertex; private InstructionContext ictx; - public MIKey(List method, InstructionContext ictx) + public MIKey(int prevVertex, InstructionContext ictx) { - this.method = method; + this.prevVertex = prevVertex; this.ictx = ictx; } @Override public int hashCode() { - int hash = 5; - hash = 61 * hash + Objects.hashCode(this.method); - hash = 61 * hash + Objects.hashCode(this.ictx); + int hash = 7; + hash = 97 * hash + this.prevVertex; + hash = 97 * hash + Objects.hashCode(this.ictx); return hash; } @@ -52,7 +53,7 @@ class MIKey return false; } final MIKey other = (MIKey) obj; - if (!Objects.equals(this.method, other.method)) + if (this.prevVertex != other.prevVertex) { return false; } @@ -62,8 +63,6 @@ class MIKey } return true; } - - } public class MethodContext @@ -90,10 +89,10 @@ public class MethodContext return graph; } - protected boolean hasJumped(List fromm, InstructionContext from, Instruction to) + protected boolean hasJumped(MutableInt prevVertex, InstructionContext from, Instruction to) { // with this true, there are so many frames I can't run a full execution without oom. - MIKey key = execution.isBuildGraph() ? new MIKey(fromm, from) : new MIKey(null, from); + MIKey key = execution.isBuildGraph() ? new MIKey(prevVertex.intValue(), from) : new MIKey(-1, from); Collection i = visited.getCollection(key); if (i != null && i.contains(to)) return true; @@ -124,8 +123,8 @@ public class MethodContext if (i instanceof InvokeInstruction) { -// if (i instanceof InvokeStatic) -// return; + if (i instanceof InvokeStatic) + return; InvokeInstruction ii = (InvokeInstruction) i; @@ -145,12 +144,12 @@ public class MethodContext return; } - if (frame.prevVertex == -1) + if (frame.prevVertex.intValue() == -1) { int id = getIdFor(i); //int id = ids.get(); //graph.add(id); - frame.prevVertex = id; + frame.prevVertex.setValue(id); //this.idMap.put(id, i); return; } @@ -160,12 +159,16 @@ public class MethodContext //graph.add(id); //idMap.put(id, i); - if (id == frame.prevVertex) + if (frame.prevVertex.intValue() == id) return; - DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex, id); + InvokeInstruction from = (InvokeInstruction) this.idMap.get(frame.prevVertex.intValue()), to = (InvokeInstruction) this.idMap.get(id); + System.out.println("Added edge " + from.getMethods().get(0).getMethods().getClassFile().getName() + "." + from.getMethods().get(0).getName() + + " to " + to.getMethods().get(0).getMethods().getClassFile().getName() + "." + to.getMethods().get(0).getName()); + + DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex.intValue(), id); graph.add(edge); - frame.prevVertex = id; + frame.prevVertex.setValue(id); } }