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.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());

View File

@@ -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();

View File

@@ -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
{
}

View File

@@ -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);
}
}

View File

@@ -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
{

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.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<Instruction, Instruction> 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<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)
{
@@ -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