From e478a4b1f984f5c8843ccd4bc74d5847dbe6932b Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 22 Aug 2015 17:54:39 -0400 Subject: [PATCH] Store stack context with variable context, and pass up stack contexts when invoking methods. I don't think iirc is right? --- pom.xml | 5 + src/main/java/net/runelite/deob/Deob.java | 120 +++++++++--------- .../attributes/code/instructions/AStore.java | 4 +- .../code/instructions/AStore_0.java | 2 +- .../code/instructions/AStore_1.java | 2 +- .../code/instructions/AStore_2.java | 2 +- .../code/instructions/AStore_3.java | 2 +- .../attributes/code/instructions/DStore.java | 2 +- .../code/instructions/DStore_0.java | 2 +- .../code/instructions/DStore_1.java | 2 +- .../code/instructions/DStore_2.java | 2 +- .../code/instructions/DStore_3.java | 2 +- .../attributes/code/instructions/FStore.java | 2 +- .../code/instructions/FStore_0.java | 2 +- .../code/instructions/FStore_1.java | 2 +- .../code/instructions/FStore_2.java | 2 +- .../code/instructions/FStore_3.java | 2 +- .../attributes/code/instructions/IInc.java | 2 +- .../attributes/code/instructions/IStore.java | 2 +- .../code/instructions/IStore_0.java | 2 +- .../code/instructions/IStore_1.java | 2 +- .../code/instructions/IStore_2.java | 2 +- .../code/instructions/IStore_3.java | 2 +- .../code/instructions/InvokeInterface.java | 11 +- .../code/instructions/InvokeSpecial.java | 11 +- .../code/instructions/InvokeStatic.java | 11 +- .../code/instructions/InvokeVirtual.java | 11 +- .../attributes/code/instructions/LStore.java | 2 +- .../code/instructions/LStore_0.java | 2 +- .../code/instructions/LStore_1.java | 2 +- .../code/instructions/LStore_2.java | 2 +- .../code/instructions/LStore_3.java | 2 +- .../runelite/deob/execution/Execution.java | 68 +++++----- .../net/runelite/deob/execution/Frame.java | 41 +++++- .../deob/execution/InstructionContext.java | 2 +- .../deob/execution/VariableContext.java | 18 ++- 36 files changed, 222 insertions(+), 130 deletions(-) diff --git a/pom.xml b/pom.xml index 9e5f2a3779..bc0a1b08cd 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,11 @@ commons-collections4 4.0 + + com.google.guava + guava + 18.0 + 1.7 diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index e4a2f0e852..c06da885e0 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -47,66 +47,66 @@ public class Deob // bdur = System.currentTimeMillis() - bstart; // System.out.println("rename unique took " + bdur/1000L + " seconds"); -// // remove except RuntimeException -// bstart = System.currentTimeMillis(); -// new RuntimeExceptions().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("runtime exception took " + bdur/1000L + " seconds"); -// -// // remove unused methods -// bstart = System.currentTimeMillis(); -// new UnusedMethods().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused methods took " + bdur/1000L + " seconds"); -// -// new UnreachedCode().run(group); -// -// // remove illegal state exceptions, frees up some parameters -// bstart = System.currentTimeMillis(); -// new IllegalStateExceptions().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("illegal state exception took " + bdur/1000L + " seconds"); -// -// // remove constant logically dead parameters -// bstart = System.currentTimeMillis(); -// new ConstantParameter().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("constant param took " + bdur/1000L + " seconds"); -// -// // remove unhit blocks -// bstart = System.currentTimeMillis(); -// new UnreachedCode().run(group); -// //new UnusedBlocks().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused blocks took " + bdur/1000L + " seconds"); -// -// // remove unused parameters -// bstart = System.currentTimeMillis(); -// new UnusedParameters().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused params took " + bdur/1000L + " seconds"); -// -// // remove jump obfuscation -// //new Jumps().run(group); -// -// // remove unused fields -// bstart = System.currentTimeMillis(); -// new UnusedFields().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused fields took " + bdur/1000L + " seconds"); -// -// // remove unused methods, again? -// bstart = System.currentTimeMillis(); -// new UnusedMethods().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused methods took " + bdur/1000L + " seconds"); -// -// -// new MethodInliner().run(group); -// -// new MethodMover().run(group); -// -// new FieldInliner().run(group); + // remove except RuntimeException + bstart = System.currentTimeMillis(); + new RuntimeExceptions().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("runtime exception took " + bdur/1000L + " seconds"); + + // remove unused methods + bstart = System.currentTimeMillis(); + new UnusedMethods().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused methods took " + bdur/1000L + " seconds"); + + new UnreachedCode().run(group); + + // remove illegal state exceptions, frees up some parameters + bstart = System.currentTimeMillis(); + new IllegalStateExceptions().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("illegal state exception took " + bdur/1000L + " seconds"); + + // remove constant logically dead parameters + bstart = System.currentTimeMillis(); + new ConstantParameter().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("constant param took " + bdur/1000L + " seconds"); + + // remove unhit blocks + bstart = System.currentTimeMillis(); + new UnreachedCode().run(group); + //new UnusedBlocks().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused blocks took " + bdur/1000L + " seconds"); + + // remove unused parameters + bstart = System.currentTimeMillis(); + new UnusedParameters().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused params took " + bdur/1000L + " seconds"); + + // remove jump obfuscation + //new Jumps().run(group); + + // remove unused fields + bstart = System.currentTimeMillis(); + new UnusedFields().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused fields took " + bdur/1000L + " seconds"); + + // remove unused methods, again? + bstart = System.currentTimeMillis(); + new UnusedMethods().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused methods took " + bdur/1000L + " seconds"); + + + new MethodInliner().run(group); + + new MethodMover().run(group); + + new FieldInliner().run(group); // XXX this is broken because when moving clinit around, some fields can depend on other fields // (like multianewarray) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java index c9be0e2871..bc60499d24 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java @@ -1,6 +1,5 @@ package net.runelite.deob.attributes.code.instructions; -import net.runelite.deob.ClassFile; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -12,7 +11,6 @@ import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; import net.runelite.deob.execution.VariableContext; import net.runelite.deob.execution.Variables; -import net.runelite.deob.pool.Class; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -55,7 +53,7 @@ public class AStore extends Instruction implements LVTInstruction, WideInstructi StackContext object = stack.pop(); ins.pop(object); - variables.set(index, new VariableContext(ins, object.getType())); + variables.set(index, new VariableContext(ins, object)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_0.java index b50facc376..35398c1d24 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_0.java @@ -30,7 +30,7 @@ public class AStore_0 extends Instruction implements LVTInstruction StackContext object = stack.pop(); ins.pop(object); - variables.set(0, new VariableContext(ins, object.getType())); + variables.set(0, new VariableContext(ins, object)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_1.java index cdf7eef8bf..d84cb9c720 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_1.java @@ -30,7 +30,7 @@ public class AStore_1 extends Instruction implements LVTInstruction StackContext object = stack.pop(); ins.pop(object); - variables.set(1, new VariableContext(ins, object.getType())); + variables.set(1, new VariableContext(ins, object)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_2.java index 0fe269e06c..64ac69d01a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_2.java @@ -30,7 +30,7 @@ public class AStore_2 extends Instruction implements LVTInstruction StackContext object = stack.pop(); ins.pop(object); - variables.set(2, new VariableContext(ins, object.getType())); + variables.set(2, new VariableContext(ins, object)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_3.java index 83a68173d3..7c23783764 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore_3.java @@ -30,7 +30,7 @@ public class AStore_3 extends Instruction implements LVTInstruction StackContext object = stack.pop(); ins.pop(object); - variables.set(3, new VariableContext(ins, object.getType())); + variables.set(3, new VariableContext(ins, object)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java index 86aa156eb2..a42a618723 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java @@ -53,7 +53,7 @@ public class DStore extends Instruction implements LVTInstruction, WideInstructi StackContext value = stack.pop(); ins.pop(value); - variables.set(index, new VariableContext(ins, value.getType())); + variables.set(index, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_0.java index ebf6d23823..3322e85d71 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_0.java @@ -30,7 +30,7 @@ public class DStore_0 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(0, new VariableContext(ins, value.getType())); + variables.set(0, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_1.java index 820414446c..cdfde5640f 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_1.java @@ -30,7 +30,7 @@ public class DStore_1 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(1, new VariableContext(ins, value.getType())); + variables.set(1, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_2.java index e36647d59d..3788b920ca 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_2.java @@ -30,7 +30,7 @@ public class DStore_2 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(2, new VariableContext(ins, value.getType())); + variables.set(2, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_3.java index 6cf08eb68a..67d3bf2bec 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore_3.java @@ -30,7 +30,7 @@ public class DStore_3 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(3, new VariableContext(ins, value.getType())); + variables.set(3, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java index 1d5fab31b6..53f08a4966 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java @@ -53,7 +53,7 @@ public class FStore extends Instruction implements LVTInstruction, WideInstructi StackContext value = stack.pop(); ins.pop(value); - variables.set(index, new VariableContext(ins, value.getType())); + variables.set(index, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_0.java index 3b0da59b63..a3dab0aa92 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_0.java @@ -30,7 +30,7 @@ public class FStore_0 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(0, new VariableContext(ins, value.getType())); + variables.set(0, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_1.java index d0736386ed..98d60c641a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_1.java @@ -30,7 +30,7 @@ public class FStore_1 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(1, new VariableContext(ins, value.getType())); + variables.set(1, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_2.java index 84793108d6..d5523c228b 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_2.java @@ -30,7 +30,7 @@ public class FStore_2 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(2, new VariableContext(ins, value.getType())); + variables.set(2, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_3.java index 5c66bb1749..7bc1cf4360 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore_3.java @@ -30,7 +30,7 @@ public class FStore_3 extends Instruction implements LVTInstruction StackContext value = stack.pop(); ins.pop(value); - variables.set(3, new VariableContext(ins, value.getType())); + variables.set(3, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java index 027623c711..0ab042b8af 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java @@ -58,7 +58,7 @@ public class IInc extends Instruction implements LVTInstruction, WideInstruction assert vctx.getType().equals(new Type(int.class.getCanonicalName())); ins.read(vctx); - vctx = new VariableContext(ins, vctx.getType()); + vctx = new VariableContext(ins, vctx.getStackContext()); // XXX this is probably not right. var.set(index, vctx); frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java index 8361f18a08..df295480f0 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java @@ -64,7 +64,7 @@ public class IStore extends Instruction implements LVTInstruction, WideInstructi assert value.getType().equals(new Type(int.class.getName())); ins.pop(value); - variables.set(index, new VariableContext(ins, value.getType())); + variables.set(index, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java index f15f07b2db..7b006d99a8 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java @@ -32,7 +32,7 @@ public class IStore_0 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(int.class.getName())); ins.pop(value); - variables.set(0, new VariableContext(ins, value.getType())); + variables.set(0, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java index 418de02b5b..1479303179 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java @@ -32,7 +32,7 @@ public class IStore_1 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(int.class.getName())); ins.pop(value); - variables.set(1, new VariableContext(ins, value.getType())); + variables.set(1, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java index a8676da489..446174772d 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java @@ -32,7 +32,7 @@ public class IStore_2 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(int.class.getName())); ins.pop(value); - variables.set(2, new VariableContext(ins, value.getType())); + variables.set(2, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_3.java index b267b2e363..5577669d07 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_3.java @@ -32,7 +32,7 @@ public class IStore_3 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(int.class.getName())); ins.pop(value); - variables.set(3, new VariableContext(ins, value.getType())); + variables.set(3, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java index f6a02de4ae..316a96b001 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java @@ -23,6 +23,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import net.runelite.deob.execution.Execution; public class InvokeInterface extends Instruction implements InvokeInstruction { @@ -102,8 +103,16 @@ public class InvokeInterface extends Instruction implements InvokeInstruction for (net.runelite.deob.Method method : getMethods()) { ins.invoke(method); + + if (method.getCode() == null) + { + frame.getExecution().methods.add(method); + continue; + } + // add possible method call to execution - frame.getExecution().addMethod(method); + Execution execution = frame.getExecution(); + execution.invoke(ins, method); } frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java index f5d08d2547..4620440f14 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java @@ -22,6 +22,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import net.runelite.deob.execution.Execution; public class InvokeSpecial extends Instruction implements InvokeInstruction { @@ -88,8 +89,16 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction for (net.runelite.deob.Method method : getMethods()) { ins.invoke(method); + + if (method.getCode() == null) + { + frame.getExecution().methods.add(method); + continue; + } + // add possible method call to execution - frame.getExecution().addMethod(method); + Execution execution = frame.getExecution(); + execution.invoke(ins, method); } frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java index 8b5532d352..6c3b057f73 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java @@ -22,6 +22,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import net.runelite.deob.execution.Execution; public class InvokeStatic extends Instruction implements InvokeInstruction { @@ -85,8 +86,16 @@ public class InvokeStatic extends Instruction implements InvokeInstruction for (net.runelite.deob.Method method : getMethods()) { ins.invoke(method); + + if (method.getCode() == null) + { + frame.getExecution().methods.add(method); + continue; + } + // add possible method call to execution - frame.getExecution().addMethod(method); + Execution execution = frame.getExecution(); + execution.invoke(ins, method); } frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java index 4f1637fa4e..8a33320d8e 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java @@ -22,6 +22,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import net.runelite.deob.execution.Execution; public class InvokeVirtual extends Instruction implements InvokeInstruction { @@ -71,8 +72,16 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction for (net.runelite.deob.Method method : getMethods()) { ins.invoke(method); + + if (method.getCode() == null) + { + frame.getExecution().methods.add(method); + continue; + } + // add possible method call to execution - frame.getExecution().addMethod(method); + Execution execution = frame.getExecution(); + execution.invoke(ins, method); } frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java index b8b95937b8..7f519055e2 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java @@ -55,7 +55,7 @@ public class LStore extends Instruction implements LVTInstruction, WideInstructi assert value.getType().equals(new Type(long.class.getName())); ins.pop(value); - variables.set(index, new VariableContext(ins, value.getType())); + variables.set(index, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_0.java index 2f7032d8c1..c8078a299e 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_0.java @@ -32,7 +32,7 @@ public class LStore_0 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(long.class.getName())); ins.pop(value); - variables.set(0, new VariableContext(ins, value.getType())); + variables.set(0, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_1.java index 798be7d83d..37abaf59e1 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_1.java @@ -32,7 +32,7 @@ public class LStore_1 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(long.class.getName())); ins.pop(value); - variables.set(1, new VariableContext(ins, value.getType())); + variables.set(1, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_2.java index 879c116d9b..943cd3adef 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_2.java @@ -32,7 +32,7 @@ public class LStore_2 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(long.class.getName())); ins.pop(value); - variables.set(2, new VariableContext(ins, value.getType())); + variables.set(2, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_3.java index ba25d5acaf..67f80040c7 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore_3.java @@ -32,7 +32,7 @@ public class LStore_3 extends Instruction implements LVTInstruction assert value.getType().equals(new Type(long.class.getName())); ins.pop(value); - variables.set(3, new VariableContext(ins, value.getType())); + variables.set(3, new VariableContext(ins, value)); frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index 9cfad7e2a7..0aa5489201 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -7,18 +7,20 @@ import net.runelite.deob.Method; import net.runelite.deob.attributes.code.Instruction; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; +import org.apache.commons.collections4.map.MultiValueMap; public class Execution { private ClassGroup group; public List frames = new ArrayList<>(), processedFrames = new ArrayList<>(); - private List pendingMethods = new ArrayList<>(); // pending methods public Set methods = new HashSet<>(); // all methods public Set executed = new HashSet<>(); // executed instructions + private MultiValueMap invokes = new MultiValueMap<>(); public Execution(ClassGroup group) { @@ -30,58 +32,62 @@ public class Execution for (ClassFile cf : group.getClasses()) { for (Method m : cf.getMethods().getMethods()) - { + { if (!Deob.isObfuscated(m.getName()) && !m.getName().equals("")) { - addMethod(m); // I guess this method name is overriding a jre interface (init, run, ?). + if (m.getCode() == null) + { + methods.add(m); + continue; + } + + Frame frame = new Frame(this, m); + frame.initialize(); + addFrame(frame); // I guess this method name is overriding a jre interface (init, run, ?). } } } } - public void addMethod(Method method) + private boolean hasInvoked(InstructionContext from, Method to) { - assert method != null; + Collection methods = invokes.getCollection(from); + if (methods != null && methods.contains(to)) + return true; - if (methods.contains(method)) - return; // already processed + invokes.put(from, to); + return false; + } + + private void addFrame(Frame frame) + { + frames.add(frame); + } + + public void invoke(InstructionContext from, Method to) + { + if (hasInvoked(from, to)) + return; - pendingMethods.add(method); - methods.add(method); + Frame f = new Frame(this, to); + f.initialize(from); + this.addFrame(f); } public void run() - { - int count = 0, fcount = 0; - while (!pendingMethods.isEmpty()) - { - Method method = pendingMethods.remove(0); - - if (method.getCode() == null) - continue; - - Frame f = new Frame(this, method); - frames.add(f); - - fcount += this.runFrames(); - ++count; - } - - System.out.println("Processed " + count + " methods and " + fcount + " paths"); - } - - private int runFrames() { int fcount = 0; - while (!frames.isEmpty()) { Frame frame = frames.remove(0); + + methods.add(frame.getMethod()); + ++fcount; frame.execute(); processedFrames.add(frame); } - return fcount; + System.out.println("Processed " + fcount + " frames"); } } diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index efb9ecc243..9761555f08 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -1,5 +1,6 @@ package net.runelite.deob.execution; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -15,6 +16,7 @@ import net.runelite.deob.attributes.code.instructions.TableSwitch; import net.runelite.deob.pool.NameAndType; import java.util.HashSet; import java.util.Set; +import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import org.apache.commons.collections4.MultiMap; import org.apache.commons.collections4.map.MultiValueMap; @@ -38,19 +40,52 @@ public class Frame stack = new Stack(code.getMaxStack()); variables = new Variables(code.getMaxLocals()); - + } + + public void initialize() + { // initialize LVT int pos = 0; if (!method.isStatic()) - variables.set(pos++, new VariableContext(null, new Type(method.getMethods().getClassFile().getName()))); + variables.set(pos++, new VariableContext(new Type(method.getMethods().getClassFile().getName()))); NameAndType nat = method.getNameAndType(); for (int i = 0; i < nat.getNumberOfArgs(); ++i) { - variables.set(pos, new VariableContext(null, new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType())); + variables.set(pos, new VariableContext(new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType())); pos += nat.getDescriptor().getTypeOfArg(i).getSlots(); } + Code code = method.getCode(); + cur = code.getInstructions().getInstructions().get(0); + } + + public void initialize(InstructionContext ctx) + { + // initialize frame from invoking context + assert ctx.getInstruction() instanceof InvokeInstruction; + + // 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 + + int lvtOffset = 0; + if (!method.isStatic()) + variables.set(lvtOffset++, new VariableContext(ctx, pops.remove(0))); + + NameAndType nat = method.getNameAndType(); + + for (int i = 0; i < nat.getNumberOfArgs(); ++i) + { + StackContext argument = pops.remove(0); + + variables.set(lvtOffset, new VariableContext(ctx, argument));//new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType())); + lvtOffset += nat.getDescriptor().getTypeOfArg(i).getSlots(); + } + + assert pops.isEmpty(); + + Code code = method.getCode(); cur = code.getInstructions().getInstructions().get(0); } diff --git a/src/main/java/net/runelite/deob/execution/InstructionContext.java b/src/main/java/net/runelite/deob/execution/InstructionContext.java index 07a6126c0a..903cdbd837 100644 --- a/src/main/java/net/runelite/deob/execution/InstructionContext.java +++ b/src/main/java/net/runelite/deob/execution/InstructionContext.java @@ -102,7 +102,7 @@ public class InstructionContext Stack ours = new Stack(this.getStack()), // copy stacks since we destroy them theirs = new Stack(ic.getStack()); - if (ours.getSize() != theirs.getSize()) + if (ours.getSize() != theirs.getSize()) // is this possible? return false; while (ours.getSize() > 0) diff --git a/src/main/java/net/runelite/deob/execution/VariableContext.java b/src/main/java/net/runelite/deob/execution/VariableContext.java index 737f49713f..3e6a0f9fd6 100644 --- a/src/main/java/net/runelite/deob/execution/VariableContext.java +++ b/src/main/java/net/runelite/deob/execution/VariableContext.java @@ -2,13 +2,25 @@ package net.runelite.deob.execution; public class VariableContext { - private InstructionContext ic; + private StackContext ctx; // the value stored + private InstructionContext ic; // the instruction which stored it. also ctx.popped? private Type type; - public VariableContext(InstructionContext i, Type t) + public VariableContext(InstructionContext i, StackContext ctx) { ic = i; - type = t; + this.ctx = ctx; + type = ctx.getType(); + } + + public VariableContext(Type type) // for entrypoints + { + this.type = type; + } + + public StackContext getStackContext() + { + return ctx; } public Type getType()