From ae82aad25077f82b0175754f64c5da321c43d8ec Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 6 Nov 2015 17:49:24 -0500 Subject: [PATCH] Make method inliner copy instead of move ins. I don't think the way it inlined exceptions before was correct. I had to make it not inline funcs with exception handlers --- src/main/java/net/runelite/deob/Deob.java | 4 +- .../deob/attributes/code/Exception.java | 15 ++- .../deob/attributes/code/Instruction.java | 16 +++- .../deob/attributes/code/Instructions.java | 12 +-- .../attributes/code/instructions/Wide.java | 8 ++ .../deob/deobfuscators/MethodInliner.java | 96 ++++++++++--------- 6 files changed, 97 insertions(+), 54 deletions(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 21643ea391..2672b7d1d2 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -30,6 +30,8 @@ import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator; import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator; import net.runelite.deob.execution.Execution; +// XXX something to detect final fields and evaluate them + public class Deob { public static void main(String[] args) throws IOException @@ -73,7 +75,7 @@ public class Deob // run(group, new UnusedMethods()); run(group, new MethodInliner()); - // now remove unused methods? + run(group, new UnusedMethods()); // inliner might leave unused methods // // broken because rename was removed // //run(group, new MethodMover()); diff --git a/src/main/java/net/runelite/deob/attributes/code/Exception.java b/src/main/java/net/runelite/deob/attributes/code/Exception.java index d7257deb03..e9b4020206 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Exception.java +++ b/src/main/java/net/runelite/deob/attributes/code/Exception.java @@ -8,7 +8,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -public class Exception +public class Exception implements Cloneable { private Exceptions exceptions; @@ -36,6 +36,19 @@ public class Exception assert handler != null; } + @Override + public Exception clone() + { + try + { + return (Exception) super.clone(); + } + catch (CloneNotSupportedException ex) + { + throw new RuntimeException(); + } + } + public void write(DataOutputStream out) throws IOException { ConstantPool pool = exceptions.getCode().getAttributes().getClassFile().getPool(); 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 78fbbf7166..d6a8e05d9e 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instruction.java @@ -9,9 +9,8 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import net.runelite.deob.util.NameMappings; -public abstract class Instruction +public abstract class Instruction implements Cloneable { private Instructions instructions; public Block block; @@ -30,6 +29,19 @@ public abstract class Instruction this.pc = pc; } + @Override + public Instruction clone() + { + try + { + return (Instruction) super.clone(); + } + catch (CloneNotSupportedException ex) + { + throw new RuntimeException(); + } + } + public void load(DataInputStream is) throws IOException { } diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index 84f50bc41f..1dce88b0ea 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -1,8 +1,5 @@ package net.runelite.deob.attributes.code; -import net.runelite.deob.ClassFile; -import net.runelite.deob.Field; -import net.runelite.deob.Method; import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.instruction.types.JumpingInstruction; import net.runelite.deob.block.Block; @@ -14,7 +11,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; -import net.runelite.deob.util.NameMappings; +import net.runelite.deob.attributes.code.instructions.Goto; public class Instructions { @@ -182,6 +179,8 @@ public class Instructions public void write(DataOutputStream out) throws IOException { // trnaslate instructions to specific + this.buildJumpGraph(); + for (Instruction i : new ArrayList<>(instructions)) { Instruction specific = i.makeSpecific(); @@ -271,10 +270,13 @@ public class Instructions int i = instructions.indexOf(oldi); instructions.remove(oldi); + oldi.setInstructions(null); instructions.add(i, newi); for (Instruction ins : oldi.from) { + assert ins.getInstructions() == this; + assert this.getInstructions().contains(ins); assert ins.jump.contains(oldi); ins.jump.remove(oldi); @@ -286,7 +288,5 @@ public class Instructions for (net.runelite.deob.attributes.code.Exception e : code.getExceptions().getExceptions()) e.replace(oldi, newi); - - oldi.setInstructions(null); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java index 4e83058175..c58d4721fb 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java @@ -22,6 +22,14 @@ public class Wide extends Instruction implements LVTInstruction super(instructions, type, pc); } + @Override + public Instruction clone() + { + Wide wide = (Wide) super.clone(); + wide.ins = ins.clone(); + return wide; + } + @Override public void load(DataInputStream is) throws IOException { diff --git a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java index 17f1325aac..9548ab5f01 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java +++ b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java @@ -21,10 +21,9 @@ import net.runelite.deob.attributes.code.instructions.NOP; import net.runelite.deob.signature.Signature; import net.runelite.deob.signature.Type; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.Map.Entry; import net.runelite.deob.attributes.code.Exceptions; public class MethodInliner implements Deobfuscator @@ -84,7 +83,10 @@ public class MethodInliner implements Deobfuscator Method invokedMethod = invokedMethods.get(0); Integer count = calls.get(invokedMethod); - if (count == null || invokedMethod.getCode().getInstructions().getInstructions().size() > 30) + // this can't inline functions with exception handlers because throwing exceptions clears the stack + if (count == null + || !invokedMethod.getCode().getExceptions().getExceptions().isEmpty() + || invokedMethod.getCode().getInstructions().getInstructions().size() > 30) // XXX magic continue; // if (count == null || count != 1) // continue; // only inline methods called once @@ -94,7 +96,7 @@ public class MethodInliner implements Deobfuscator int invokeIdx = ins.getInstructions().indexOf(i); assert invokeIdx != -1; - assert ins.getInstructions().get(invokeIdx).getInstructions() == ins.getInstructions(); + assert ins.getInstructions().get(invokeIdx).getInstructions() == ins; int lvtIndex = code.getMaxLocals(), //startLvtIndex = lvtIndex, @@ -167,7 +169,6 @@ public class MethodInliner implements Deobfuscator code.setMaxStack(maxStack); inline(m, i, invokedMethod, lvtIndex, firstParamStore); - moveExceptions(m, invokedMethod); ++inlineCount; break; } @@ -220,9 +221,43 @@ public class MethodInliner implements Deobfuscator methodInstructions.remove(invokeIns); + Map insMap = new HashMap<>(); for (Instruction i : invokeMethodInstructions.getInstructions()) { - // move instructions over. + Instruction i2 = i.clone(); + i2.setInstructions(null); + insMap.put(i, i2); + } + + for (Instruction i : insMap.values()) + { + for (Entry e : insMap.entrySet()) + { + i.replace(e.getKey(), e.getValue()); + } + } + + Exceptions fromExceptions = invokeMethod.getCode().getExceptions(); + Exceptions toExceptions = method.getCode().getExceptions(); + + for (net.runelite.deob.attributes.code.Exception e : fromExceptions.getExceptions()) + { + e = e.clone(); + e.setExceptions(toExceptions); + + for (Entry en : insMap.entrySet()) + { + e.replace(en.getKey(), en.getValue()); + } + + toExceptions.add(e); + } + + for (Instruction i : invokeMethodInstructions.getInstructions()) + { + Instruction orig = i; + i = insMap.get(i); + // copy instructions over. if (i instanceof ReturnInstruction) { @@ -231,23 +266,16 @@ public class MethodInliner implements Deobfuscator // instead of return, jump to next instruction after the invoke Instruction oldI = i; i = new Goto(methodInstructions, nextInstruction); + assert nextInstruction.getInstructions() == methodInstructions; assert methodInstructions.getInstructions().contains(nextInstruction); - assert oldI != nextInstruction; - i.jump.add(nextInstruction); - nextInstruction.from.add(i); - - assert oldI.jump.isEmpty(); - //i.jump.addAll(oldI.jump); - i.from.addAll(oldI.from); - - for (Instruction i2 : oldI.from) + for (Instruction i2 : insMap.values()) i2.replace(oldI, i); - oldI.from.clear(); - - for (net.runelite.deob.attributes.code.Exception e : invokeMethodCode.getExceptions().getExceptions()) + for (net.runelite.deob.attributes.code.Exception e : toExceptions.getExceptions()) e.replace(oldI, i); + + insMap.put(orig, i); } if (i instanceof LVTInstruction) @@ -261,40 +289,20 @@ public class MethodInliner implements Deobfuscator if (oldI != i) { - assert oldI.jump.isEmpty(); - //i.jump.addAll(oldI.jump); - i.from.addAll(oldI.from); - - for (Instruction i2 : oldI.from) + for (Instruction i2 : insMap.values()) i2.replace(oldI, i); - - oldI.from.clear(); - for (net.runelite.deob.attributes.code.Exception e : invokeMethodCode.getExceptions().getExceptions()) + for (net.runelite.deob.attributes.code.Exception e : toExceptions.getExceptions()) e.replace(oldI, i); + + insMap.put(orig, i); } } - methodInstructions.getInstructions().add(idx++, i); + assert !methodInstructions.getInstructions().contains(i); i.setInstructions(methodInstructions); + methodInstructions.getInstructions().add(idx++, i); } - - // old method goes away - //invokeMethodInstructions.getInstructions().clear(); - //removeMethods.add(invokeMethod); - } - - private void moveExceptions(Method to, Method from) - { - Exceptions exceptions = from.getCode().getExceptions(); - Exceptions toExceptions = to.getCode().getExceptions(); - - for (net.runelite.deob.attributes.code.Exception e : exceptions.getExceptions()) - { - e.setExceptions(toExceptions); - toExceptions.add(e); - } - exceptions.getExceptions().clear(); } @Override