diff --git a/src/main/java/net/runelite/deob/attributes/code/Instruction.java b/src/main/java/net/runelite/deob/attributes/code/Instruction.java index b027e9b21a..974d0ca6c0 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instruction.java @@ -32,7 +32,7 @@ public abstract class Instruction implements Cloneable public String toString() { Method m = this.getInstructions().getCode().getAttributes().getMethod(); - return super.toString() + " in " + m; + return super.toString() + " in " + m + " at pc " + this.getPc(); } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/InstructionType.java b/src/main/java/net/runelite/deob/attributes/code/InstructionType.java index 336cba1620..07b265b596 100644 --- a/src/main/java/net/runelite/deob/attributes/code/InstructionType.java +++ b/src/main/java/net/runelite/deob/attributes/code/InstructionType.java @@ -121,8 +121,20 @@ import net.runelite.deob.attributes.code.instructions.IStore_3; import net.runelite.deob.attributes.code.instructions.ISub; import net.runelite.deob.attributes.code.instructions.IUShR; import net.runelite.deob.attributes.code.instructions.IXor; -import net.runelite.deob.attributes.code.instructions.If; -import net.runelite.deob.attributes.code.instructions.If0; +import net.runelite.deob.attributes.code.instructions.IfCmpEq; +import net.runelite.deob.attributes.code.instructions.IfCmpGe; +import net.runelite.deob.attributes.code.instructions.IfCmpGt; +import net.runelite.deob.attributes.code.instructions.IfCmpLe; +import net.runelite.deob.attributes.code.instructions.IfCmpLt; +import net.runelite.deob.attributes.code.instructions.IfCmpNe; +import net.runelite.deob.attributes.code.instructions.IfEq; +import net.runelite.deob.attributes.code.instructions.IfGe; +import net.runelite.deob.attributes.code.instructions.IfGt; +import net.runelite.deob.attributes.code.instructions.IfLe; +import net.runelite.deob.attributes.code.instructions.IfLt; +import net.runelite.deob.attributes.code.instructions.IfNe; +import net.runelite.deob.attributes.code.instructions.IfNonNull; +import net.runelite.deob.attributes.code.instructions.IfNull; import net.runelite.deob.attributes.code.instructions.InstanceOf; import net.runelite.deob.attributes.code.instructions.InvokeInterface; import net.runelite.deob.attributes.code.instructions.InvokeSpecial; @@ -335,20 +347,20 @@ public enum InstructionType FCMPG(0x96, "fcmpg", FCmpG.class), DCMPL(0x97, "dcmpl", DCmpL.class), DCMPG(0x98, "dcmpg", DCmpG.class), - IFEQ(0x99, "ifeq", If0.class), - IFNE(0x9a, "ifne", If0.class), - IFLT(0x9b, "iflt", If0.class), - IFGE(0x9c, "ifge", If0.class), - IFGT(0x9d, "ifgt", If0.class), - IFLE(0x9e, "ifle", If0.class), - IF_ICMPEQ(0x9f, "if_icmpeq", If.class), - IF_ICMPNE(0xa0, "if_icmpne", If.class), - IF_ICMPLT(0xa1, "if_cmplt", If.class), - IF_ICMPGE(0xa2, "if_icmpge", If.class), - IF_ICMPGT(0xa3, "if_icmpgt", If.class), - IF_ICMPLE(0xa4, "if_icmple", If.class), - IF_ACMPEQ(0xa5, "if_acmpeq", If.class), - IF_ACMPNE(0xa6, "if_acmpne", If.class), + IFEQ(0x99, "ifeq", IfEq.class), + IFNE(0x9a, "ifne", IfNe.class), + IFLT(0x9b, "iflt", IfLt.class), + IFGE(0x9c, "ifge", IfGe.class), + IFGT(0x9d, "ifgt", IfGt.class), + IFLE(0x9e, "ifle", IfLe.class), + IF_ICMPEQ(0x9f, "if_icmpeq", IfCmpEq.class), + IF_ICMPNE(0xa0, "if_icmpne", IfCmpNe.class), + IF_ICMPLT(0xa1, "if_cmplt", IfCmpLt.class), + IF_ICMPGE(0xa2, "if_icmpge", IfCmpGe.class), + IF_ICMPGT(0xa3, "if_icmpgt", IfCmpGt.class), + IF_ICMPLE(0xa4, "if_icmple", IfCmpLe.class), + IF_ACMPEQ(0xa5, "if_acmpeq", IfCmpEq.class), + IF_ACMPNE(0xa6, "if_acmpne", IfCmpNe.class), GOTO(0xa7, "goto", Goto.class), TABLESWITCH(0xaa, "tableswitch", TableSwitch.class), LOOKUPSWITCH(0xab, "lookupswitch", LookupSwitch.class), @@ -377,8 +389,8 @@ public enum InstructionType MONITOREXIT(0xc3, "monitorexit", MonitorExit.class), WIDE(0xc4, "wide", Wide.class), MULTIANEWARRAY(0xc5, "multianewarray", MultiANewArray.class), - IFNULL(0xc6, "ifnull", If0.class), - IFNONNULL(0xc7, "ifnonnull", If0.class), + IFNULL(0xc6, "ifnull", IfNull.class), + IFNONNULL(0xc7, "ifnonnull", IfNonNull.class), GOTO_W(0xc8, "goto_w", GotoW.class); private byte code; diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/If.java b/src/main/java/net/runelite/deob/attributes/code/instructions/If.java index c7e31b8b75..0e6ab0dd30 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/If.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/If.java @@ -73,10 +73,12 @@ public class If extends Instruction implements JumpingInstruction, ComparisonIns ins.pop(one, two); - frame.addInstructionContext(ins); - Frame other = frame.dup(); other.jump(ins, to); + + ins.branch(other); + + frame.addInstructionContext(ins); } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java index 76ff52e671..330ce4e776 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java @@ -74,10 +74,12 @@ public class If0 extends Instruction implements JumpingInstruction, ComparisonIn ins.pop(one); - frame.addInstructionContext(ins); - Frame other = frame.dup(); other.jump(ins, to); + + ins.branch(other); + + frame.addInstructionContext(ins); } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpEq.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpEq.java new file mode 100644 index 0000000000..7cd2710209 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpEq.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.execution.InstructionContext; + +public class IfCmpEq extends If +{ + public IfCmpEq(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpGe.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpGe.java new file mode 100644 index 0000000000..b4080a9685 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpGe.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfCmpGe extends If +{ + public IfCmpGe(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpGt.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpGt.java new file mode 100644 index 0000000000..fc70372dc1 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpGt.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfCmpGt extends If +{ + public IfCmpGt(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpLe.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpLe.java new file mode 100644 index 0000000000..b9c3e012ee --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpLe.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfCmpLe extends If +{ + public IfCmpLe(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpLt.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpLt.java new file mode 100644 index 0000000000..0fdc66ef1b --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpLt.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfCmpLt extends If +{ + public IfCmpLt(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpNe.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpNe.java new file mode 100644 index 0000000000..f1d2eaa1b0 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfCmpNe.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfCmpNe extends If +{ + public IfCmpNe(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfEq.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfEq.java new file mode 100644 index 0000000000..f210fbd0a4 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfEq.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfEq extends If0 +{ + public IfEq(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfGe.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfGe.java new file mode 100644 index 0000000000..386ae5d722 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfGe.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfGe extends If0 +{ + public IfGe(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfGt.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfGt.java new file mode 100644 index 0000000000..fc50740bcb --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfGt.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfGt extends If0 +{ + public IfGt(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfLe.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfLe.java new file mode 100644 index 0000000000..fa2c5a310f --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfLe.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfLe extends If0 +{ + public IfLe(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfLt.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfLt.java new file mode 100644 index 0000000000..c1fcfd7f39 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfLt.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfLt extends If0 +{ + public IfLt(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfNe.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfNe.java new file mode 100644 index 0000000000..817c1aa508 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfNe.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfNe extends If0 +{ + public IfNe(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfNonNull.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfNonNull.java new file mode 100644 index 0000000000..6f3a304065 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfNonNull.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfNonNull extends If0 +{ + public IfNonNull(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IfNull.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IfNull.java new file mode 100644 index 0000000000..c17aeb76ed --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IfNull.java @@ -0,0 +1,13 @@ +package net.runelite.deob.attributes.code.instructions; + +import net.runelite.deob.attributes.code.InstructionType; +import net.runelite.deob.attributes.code.Instructions; + +public class IfNull extends If0 +{ + public IfNull(Instructions instructions, InstructionType type, int pc) + { + super(instructions, type, pc); + } + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java index f7876bab45..a12769b0c6 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java @@ -118,15 +118,17 @@ public class LookupSwitch extends Instruction implements JumpingInstruction StackContext value = stack.pop(); ins.pop(value); - frame.addInstructionContext(ins); - for (Instruction i : branchi) { Frame other = frame.dup(); other.jump(ins, i); + + ins.branch(other); } frame.jump(ins, defi); + + frame.addInstructionContext(ins); } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java b/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java index af97532538..e753a3725b 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java @@ -114,15 +114,17 @@ public class TableSwitch extends Instruction implements JumpingInstruction StackContext value = stack.pop(); ins.pop(value); - frame.addInstructionContext(ins); - for (Instruction i : branchi) { Frame other = frame.dup(); other.jump(ins, i); + + ins.branch(other); } frame.jump(ins, defi); + + frame.addInstructionContext(ins); } @Override diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index ce387ee35f..a23775cff6 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -37,8 +37,6 @@ public class Execution public Set executed = new HashSet<>(); // executed instructions private MultiValueMap invokes = new MultiValueMap<>(); public MultiValueMap contexts = new MultiValueMap<>(); - private boolean buildGraph; // if true the frame graph is built and execution hasJumped also compares previous instructions - private Graph graph = new Graph(); public Execution(ClassGroup group) { @@ -125,7 +123,6 @@ public class Execution public void run() { - initializeGraph(); int fcount = 0; while (!frames.isEmpty()) @@ -147,106 +144,10 @@ public class Execution System.out.println("Processed " + fcount + " frames"); } - public Collection getInstructonContexts(Instruction i) { - return contexts.getCollection(i); - } - - public boolean isBuildGraph() - { - return buildGraph; - } - - public void setBuildGraph(boolean buildGraph) - { - this.buildGraph = buildGraph; + } - private void initializeGraph() { - if (!isBuildGraph()) - return; - - for (ClassFile cf : this.group.getClasses()) - { - //graph.addVertex(cf, VertexType.CLASS); - - for (Method m : cf.getMethods().getMethods()) - { - if (m.isStatic() && !m.getName().equals("")) - continue; - - graph.addVertex(m, VertexType.METHOD); - } - - for (Field f : cf.getFields().getFields()) - { - graph.addVertex(f, VertexType.FIELD); - } - } - } - - protected void buildGraph(Frame frame, Instruction i, InstructionContext ctx) - { - if (!isBuildGraph()) - return; - - assert frame.getMethod() == frame.nonStatic || frame.nonStatic.isStatic() == false; - assert ctx.getInstruction() == i; - - if (i instanceof InvokeInstruction) - { - if (i instanceof InvokeStatic) - return; - - InvokeInstruction ii = (InvokeInstruction) i; - - List methods = ii.getMethods(); - if (methods.isEmpty()) - return; - - for (Method m : methods) - { - graph.addEdge(new Edge(ctx, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(m), EdgeType.INVOKE)); - graph.addEdge(new Edge(ctx, graph.getVertexFor(m), graph.getVertexFor(frame.nonStatic), EdgeType.INVOKED_FROM)); - } - } - else if (i instanceof FieldInstruction) - { - FieldInstruction fi = (FieldInstruction) i; - - if (fi.getMyField() == null) - return; - - EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD; - graph.addEdge(new Edge(ctx, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(fi.getMyField()), type)); - EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM; - graph.addEdge(new Edge(ctx, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(frame.nonStatic), typeRev)); - } - } - - private static List getInsInExpr(InstructionContext ctx, Set set) - { - List l = new ArrayList<>(); - - if (ctx == null || set.contains(ctx.getInstruction())) - return l; - - set.add(ctx.getInstruction()); - - l.add(ctx); - - for (StackContext s : ctx.getPops()) - l.addAll(getInsInExpr(s.getPushed(), set)); - for (StackContext s : ctx.getPushes()) - for (InstructionContext i : s.getPopped()) - l.addAll(getInsInExpr(i, set)); - - return l; - } - - public Graph getGraph() - { - return graph; } } diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index 8f14df1095..4ef7f6be82 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -209,8 +209,6 @@ public class Frame if (!executing) break; - execution.buildGraph(this, oldCur, ictx); - if (oldCur == cur) { int idx = instructions.indexOf(cur); diff --git a/src/main/java/net/runelite/deob/execution/InstructionContext.java b/src/main/java/net/runelite/deob/execution/InstructionContext.java index f0945480e4..480848e327 100644 --- a/src/main/java/net/runelite/deob/execution/InstructionContext.java +++ b/src/main/java/net/runelite/deob/execution/InstructionContext.java @@ -17,6 +17,7 @@ public class InstructionContext private List pushes = new ArrayList<>(); // stack contexts pushed by instruction execution private List reads = new ArrayList<>(); // lvt reads private List invokes = new ArrayList<>(); // invokes + private List branches = new ArrayList<>(); public InstructionContext(Instruction i, Frame f) { @@ -55,6 +56,14 @@ public class InstructionContext invokes.add(method); } + public void branch(Frame frame) + { + assert frame != this.frame; + assert !branches.contains(frame); + + branches.add(frame); + } + public Instruction getInstruction() { return ins; diff --git a/src/main/java/net/runelite/deob/execution/VariableContext.java b/src/main/java/net/runelite/deob/execution/VariableContext.java index d51cd263ce..cd48cae0e7 100644 --- a/src/main/java/net/runelite/deob/execution/VariableContext.java +++ b/src/main/java/net/runelite/deob/execution/VariableContext.java @@ -23,6 +23,7 @@ public class VariableContext public VariableContext(Type type) // for entrypoints { this.type = type; + value = Value.NULL; } public VariableContext(InstructionContext i, VariableContext other)