diff --git a/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java b/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java index 29ebf63952..43bdc7b1cd 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java +++ b/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java @@ -14,9 +14,11 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import net.runelite.deob.attributes.Attributes; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instructions.Goto; import net.runelite.deob.attributes.code.instructions.PutStatic; import net.runelite.deob.attributes.code.instructions.VReturn; import net.runelite.deob.execution.Execution; @@ -207,9 +209,10 @@ public class FieldMover implements Deobfuscator { // find instruction in execution and remove it InstructionContext setCtx = null; + Frame frame = null; List ctxs = null; - for (Frame frame : execution.processedFrames) - for (InstructionContext ctx : frame.getInstructions()) + for (Frame f : execution.processedFrames) + for (InstructionContext ctx : f.getInstructions()) { if (ctx.getInstruction() != setInstruction) continue; @@ -220,6 +223,7 @@ public class FieldMover implements Deobfuscator //List oldIns = new ArrayList<>(frame.getMethod().getCode().getInstructions().getInstructions()); ctxs = ctx.removeStack(0); //remove + frame = f; //List newIns = new ArrayList<>(frame.getMethod().getCode().getInstructions().getInstructions()); @@ -234,6 +238,83 @@ public class FieldMover implements Deobfuscator } // insert instructions into method + + // convert stack info to instruction ctx + List ictxs = getContexts(setCtx); + + // order instructions based on the order they execute in the frame + Map orderedIns = new TreeMap<>(); + for (InstructionContext i : ictxs) + { + assert frame.getInstructions().indexOf(i) != -1; + orderedIns.put(frame.getInstructions().indexOf(i), i.getInstruction()); + } + + to.getCode().getInstructions().buildJumpGraph(); + frame.getMethod().getCode().getInstructions().buildInstructionGraph(); + + for (Instruction i : orderedIns.values()) + { + moveJumps(i); + i.getInstructions().remove(i); + + i.setInstructions(to.getCode().getInstructions()); + } + + // insert instructions into method + to.getCode().getInstructions().getInstructions().addAll(0, orderedIns.values()); + } + + private void moveJumps(Instruction i) + { + List list = i.getInstructions().getInstructions(); + + int idx = list.indexOf(i); + + Instruction next = list.get(idx + 1); + + for (Instruction i2 : i.from) + { + i2.jump.remove(i); + + i2.replace(i, next); + + next.from.add(i2); + i2.jump.add(next); + } + i.from.clear(); + } + + private void getContexts(List list, InstructionContext ctx) + { + assert !(ctx.getInstruction() instanceof Goto); + + if (list.contains(ctx)) + return; + + list.add(ctx); + + for (StackContext s : ctx.getPops()) + { + assert s.getPopped() == ctx; + + getContexts(list, s.getPushed()); + } + + for (StackContext s : ctx.getPushes()) + { + assert s.getPushed() == ctx; + + getContexts(list, s.getPopped()); + } + } + + // get instruction contexts for stack contexts + private List getContexts(InstructionContext ctx) + { + List list = new ArrayList<>(); + getContexts(list, ctx); + return list; } @Override