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

This commit is contained in:
Adam
2015-11-06 17:49:24 -05:00
parent 84fa11c8c8
commit ae82aad250
6 changed files with 97 additions and 54 deletions

View File

@@ -30,6 +30,8 @@ import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator;
import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator; import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator;
import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Execution;
// XXX something to detect final fields and evaluate them
public class Deob public class Deob
{ {
public static void main(String[] args) throws IOException public static void main(String[] args) throws IOException
@@ -73,7 +75,7 @@ public class Deob
// run(group, new UnusedMethods()); // run(group, new UnusedMethods());
run(group, new MethodInliner()); run(group, new MethodInliner());
// now remove unused methods? run(group, new UnusedMethods()); // inliner might leave unused methods
// // broken because rename was removed // // broken because rename was removed
// //run(group, new MethodMover()); // //run(group, new MethodMover());

View File

@@ -8,7 +8,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
public class Exception public class Exception implements Cloneable
{ {
private Exceptions exceptions; private Exceptions exceptions;
@@ -36,6 +36,19 @@ public class Exception
assert handler != null; 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 public void write(DataOutputStream out) throws IOException
{ {
ConstantPool pool = exceptions.getCode().getAttributes().getClassFile().getPool(); ConstantPool pool = exceptions.getCode().getAttributes().getClassFile().getPool();

View File

@@ -9,9 +9,8 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.runelite.deob.util.NameMappings;
public abstract class Instruction public abstract class Instruction implements Cloneable
{ {
private Instructions instructions; private Instructions instructions;
public Block block; public Block block;
@@ -30,6 +29,19 @@ public abstract class Instruction
this.pc = pc; 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 public void load(DataInputStream is) throws IOException
{ {
} }

View File

@@ -1,8 +1,5 @@
package net.runelite.deob.attributes.code; 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;
import net.runelite.deob.attributes.code.instruction.types.JumpingInstruction; import net.runelite.deob.attributes.code.instruction.types.JumpingInstruction;
import net.runelite.deob.block.Block; import net.runelite.deob.block.Block;
@@ -14,7 +11,7 @@ import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.runelite.deob.util.NameMappings; import net.runelite.deob.attributes.code.instructions.Goto;
public class Instructions public class Instructions
{ {
@@ -182,6 +179,8 @@ public class Instructions
public void write(DataOutputStream out) throws IOException public void write(DataOutputStream out) throws IOException
{ {
// trnaslate instructions to specific // trnaslate instructions to specific
this.buildJumpGraph();
for (Instruction i : new ArrayList<>(instructions)) for (Instruction i : new ArrayList<>(instructions))
{ {
Instruction specific = i.makeSpecific(); Instruction specific = i.makeSpecific();
@@ -271,10 +270,13 @@ public class Instructions
int i = instructions.indexOf(oldi); int i = instructions.indexOf(oldi);
instructions.remove(oldi); instructions.remove(oldi);
oldi.setInstructions(null);
instructions.add(i, newi); instructions.add(i, newi);
for (Instruction ins : oldi.from) for (Instruction ins : oldi.from)
{ {
assert ins.getInstructions() == this;
assert this.getInstructions().contains(ins);
assert ins.jump.contains(oldi); assert ins.jump.contains(oldi);
ins.jump.remove(oldi); ins.jump.remove(oldi);
@@ -286,7 +288,5 @@ public class Instructions
for (net.runelite.deob.attributes.code.Exception e : code.getExceptions().getExceptions()) for (net.runelite.deob.attributes.code.Exception e : code.getExceptions().getExceptions())
e.replace(oldi, newi); e.replace(oldi, newi);
oldi.setInstructions(null);
} }
} }

View File

@@ -22,6 +22,14 @@ public class Wide extends Instruction implements LVTInstruction
super(instructions, type, pc); super(instructions, type, pc);
} }
@Override
public Instruction clone()
{
Wide wide = (Wide) super.clone();
wide.ins = ins.clone();
return wide;
}
@Override @Override
public void load(DataInputStream is) throws IOException public void load(DataInputStream is) throws IOException
{ {

View File

@@ -21,10 +21,9 @@ import net.runelite.deob.attributes.code.instructions.NOP;
import net.runelite.deob.signature.Signature; import net.runelite.deob.signature.Signature;
import net.runelite.deob.signature.Type; import net.runelite.deob.signature.Type;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Map.Entry;
import net.runelite.deob.attributes.code.Exceptions; import net.runelite.deob.attributes.code.Exceptions;
public class MethodInliner implements Deobfuscator public class MethodInliner implements Deobfuscator
@@ -84,7 +83,10 @@ public class MethodInliner implements Deobfuscator
Method invokedMethod = invokedMethods.get(0); Method invokedMethod = invokedMethods.get(0);
Integer count = calls.get(invokedMethod); 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; continue;
// if (count == null || count != 1) // if (count == null || count != 1)
// continue; // only inline methods called once // continue; // only inline methods called once
@@ -94,7 +96,7 @@ public class MethodInliner implements Deobfuscator
int invokeIdx = ins.getInstructions().indexOf(i); int invokeIdx = ins.getInstructions().indexOf(i);
assert invokeIdx != -1; assert invokeIdx != -1;
assert ins.getInstructions().get(invokeIdx).getInstructions() == ins.getInstructions(); assert ins.getInstructions().get(invokeIdx).getInstructions() == ins;
int lvtIndex = code.getMaxLocals(), int lvtIndex = code.getMaxLocals(),
//startLvtIndex = lvtIndex, //startLvtIndex = lvtIndex,
@@ -167,7 +169,6 @@ public class MethodInliner implements Deobfuscator
code.setMaxStack(maxStack); code.setMaxStack(maxStack);
inline(m, i, invokedMethod, lvtIndex, firstParamStore); inline(m, i, invokedMethod, lvtIndex, firstParamStore);
moveExceptions(m, invokedMethod);
++inlineCount; ++inlineCount;
break; break;
} }
@@ -220,9 +221,43 @@ public class MethodInliner implements Deobfuscator
methodInstructions.remove(invokeIns); methodInstructions.remove(invokeIns);
Map<Instruction, Instruction> insMap = new HashMap<>();
for (Instruction i : invokeMethodInstructions.getInstructions()) 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<Instruction, Instruction> 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<Instruction, Instruction> 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) if (i instanceof ReturnInstruction)
{ {
@@ -231,23 +266,16 @@ public class MethodInliner implements Deobfuscator
// instead of return, jump to next instruction after the invoke // instead of return, jump to next instruction after the invoke
Instruction oldI = i; Instruction oldI = i;
i = new Goto(methodInstructions, nextInstruction); i = new Goto(methodInstructions, nextInstruction);
assert nextInstruction.getInstructions() == methodInstructions;
assert methodInstructions.getInstructions().contains(nextInstruction); assert methodInstructions.getInstructions().contains(nextInstruction);
assert oldI != nextInstruction; for (Instruction i2 : insMap.values())
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)
i2.replace(oldI, i); i2.replace(oldI, i);
oldI.from.clear(); for (net.runelite.deob.attributes.code.Exception e : toExceptions.getExceptions())
for (net.runelite.deob.attributes.code.Exception e : invokeMethodCode.getExceptions().getExceptions())
e.replace(oldI, i); e.replace(oldI, i);
insMap.put(orig, i);
} }
if (i instanceof LVTInstruction) if (i instanceof LVTInstruction)
@@ -261,40 +289,20 @@ public class MethodInliner implements Deobfuscator
if (oldI != i) if (oldI != i)
{ {
assert oldI.jump.isEmpty(); for (Instruction i2 : insMap.values())
//i.jump.addAll(oldI.jump);
i.from.addAll(oldI.from);
for (Instruction i2 : oldI.from)
i2.replace(oldI, i); 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); e.replace(oldI, i);
insMap.put(orig, i);
} }
} }
methodInstructions.getInstructions().add(idx++, i); assert !methodInstructions.getInstructions().contains(i);
i.setInstructions(methodInstructions); 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 @Override