requires some work to move static field initializers
This commit is contained in:
@@ -193,6 +193,11 @@ public class ClassFile
|
|||||||
return methods.findMethod(nat);
|
return methods.findMethod(nat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Method findMethod(String name)
|
||||||
|
{
|
||||||
|
return methods.findMethod(name);
|
||||||
|
}
|
||||||
|
|
||||||
public Method findMethodDeep(String name)
|
public Method findMethodDeep(String name)
|
||||||
{
|
{
|
||||||
Method m = methods.findMethod(name);
|
Method m = methods.findMethod(name);
|
||||||
|
|||||||
@@ -46,72 +46,72 @@ public class Deob
|
|||||||
// bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
// System.out.println("rename unique took " + bdur/1000L + " seconds");
|
// System.out.println("rename unique took " + bdur/1000L + " seconds");
|
||||||
|
|
||||||
// remove except RuntimeException
|
// // remove except RuntimeException
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new RuntimeExceptions().run(group);
|
// new RuntimeExceptions().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("runtime exception took " + bdur/1000L + " seconds");
|
// System.out.println("runtime exception took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
// remove unused methods
|
// // remove unused methods
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new UnusedMethods().run(group);
|
// new UnusedMethods().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("unused methods took " + bdur/1000L + " seconds");
|
// System.out.println("unused methods took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
new UnreachedCode().run(group);
|
// new UnreachedCode().run(group);
|
||||||
|
//
|
||||||
// remove illegal state exceptions, frees up some parameters
|
// // remove illegal state exceptions, frees up some parameters
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new IllegalStateExceptions().run(group);
|
// new IllegalStateExceptions().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("illegal state exception took " + bdur/1000L + " seconds");
|
// System.out.println("illegal state exception took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
// remove constant logically dead parameters
|
// // remove constant logically dead parameters
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new ConstantParameter().run(group);
|
// new ConstantParameter().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("constant param took " + bdur/1000L + " seconds");
|
// System.out.println("constant param took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
// remove unhit blocks
|
// // remove unhit blocks
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new UnreachedCode().run(group);
|
// new UnreachedCode().run(group);
|
||||||
//new UnusedBlocks().run(group);
|
// //new UnusedBlocks().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("unused blocks took " + bdur/1000L + " seconds");
|
// System.out.println("unused blocks took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
// remove unused parameters
|
// // remove unused parameters
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new UnusedParameters().run(group);
|
// new UnusedParameters().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("unused params took " + bdur/1000L + " seconds");
|
// System.out.println("unused params took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
// remove jump obfuscation
|
// // remove jump obfuscation
|
||||||
//new Jumps().run(group);
|
// //new Jumps().run(group);
|
||||||
|
//
|
||||||
// remove unused fields
|
// // remove unused fields
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new UnusedFields().run(group);
|
// new UnusedFields().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("unused fields took " + bdur/1000L + " seconds");
|
// System.out.println("unused fields took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
// remove unused methods, again?
|
// // remove unused methods, again?
|
||||||
bstart = System.currentTimeMillis();
|
// bstart = System.currentTimeMillis();
|
||||||
new UnusedMethods().run(group);
|
// new UnusedMethods().run(group);
|
||||||
bdur = System.currentTimeMillis() - bstart;
|
// bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("unused methods took " + bdur/1000L + " seconds");
|
// System.out.println("unused methods took " + bdur/1000L + " seconds");
|
||||||
|
//
|
||||||
|
//
|
||||||
new MethodInliner().run(group);
|
// new MethodInliner().run(group);
|
||||||
|
|
||||||
// new ModularArithmeticDeobfuscation().run(group);
|
// new ModularArithmeticDeobfuscation().run(group);
|
||||||
|
//
|
||||||
new MethodMover().run(group);
|
// new MethodMover().run(group);
|
||||||
|
|
||||||
new FieldMover().run(group);
|
new FieldMover().run(group);
|
||||||
|
//
|
||||||
|
// new FieldInliner().run(group);
|
||||||
|
|
||||||
new FieldInliner().run(group);
|
//new UnusedClass().run(group);
|
||||||
|
|
||||||
new UnusedClass().run(group);
|
|
||||||
|
|
||||||
saveJar(group, args[1]);
|
saveJar(group, args[1]);
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,15 @@ public class Method
|
|||||||
name = pool.getUTF8(is.readUnsignedShort());
|
name = pool.getUTF8(is.readUnsignedShort());
|
||||||
arguments = new Signature(pool.getUTF8(is.readUnsignedShort()));
|
arguments = new Signature(pool.getUTF8(is.readUnsignedShort()));
|
||||||
attributes = new Attributes(this);
|
attributes = new Attributes(this);
|
||||||
|
attributes.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method(Methods methods, String name, Signature signature)
|
||||||
|
{
|
||||||
|
this.methods = methods;
|
||||||
|
this.name = name;
|
||||||
|
this.arguments = signature;
|
||||||
|
attributes = new Attributes(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(DataOutputStream out) throws IOException
|
public void write(DataOutputStream out) throws IOException
|
||||||
@@ -62,6 +71,11 @@ public class Method
|
|||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Attributes getAttributes()
|
||||||
|
{
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
|
|||||||
@@ -11,20 +11,16 @@ public abstract class Attribute
|
|||||||
private AttributeType type;
|
private AttributeType type;
|
||||||
private int length;
|
private int length;
|
||||||
|
|
||||||
Attribute(Attributes attr, AttributeType type) throws IOException
|
Attribute(Attributes attr, AttributeType type)
|
||||||
{
|
{
|
||||||
this.attributes = attr;
|
this.attributes = attr;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
DataInputStream is = attr.getStream();
|
|
||||||
this.length = is.readInt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute(Attributes attr, AttributeType type, int length)
|
public void load() throws IOException
|
||||||
{
|
{
|
||||||
this.attributes = attr;
|
DataInputStream is = attributes.getStream();
|
||||||
this.type = type;
|
this.length = is.readInt();
|
||||||
this.length = length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void write(DataOutputStream out) throws IOException
|
public final void write(DataOutputStream out) throws IOException
|
||||||
|
|||||||
@@ -33,11 +33,9 @@ public class Attributes
|
|||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Attributes(Method m) throws IOException
|
public Attributes(Method m)
|
||||||
{
|
{
|
||||||
method = m;
|
method = m;
|
||||||
|
|
||||||
load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Attributes(Code c) throws IOException
|
public Attributes(Code c) throws IOException
|
||||||
@@ -82,7 +80,7 @@ public class Attributes
|
|||||||
return getClassFile().getStream();
|
return getClassFile().getStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void load() throws IOException
|
public void load() throws IOException
|
||||||
{
|
{
|
||||||
DataInputStream is = getStream();
|
DataInputStream is = getStream();
|
||||||
|
|
||||||
@@ -97,6 +95,7 @@ public class Attributes
|
|||||||
{
|
{
|
||||||
Constructor<? extends Attribute> con = type.getAttributeClass().getConstructor(new Class[] { Attributes.class });
|
Constructor<? extends Attribute> con = type.getAttributeClass().getConstructor(new Class[] { Attributes.class });
|
||||||
Attribute attr = con.newInstance(this);
|
Attribute attr = con.newInstance(this);
|
||||||
|
attr.load();
|
||||||
|
|
||||||
if (type != AttributeType.UNKNOWN)
|
if (type != AttributeType.UNKNOWN)
|
||||||
attributes.add(attr);
|
attributes.add(attr);
|
||||||
|
|||||||
@@ -17,16 +17,23 @@ public class Code extends Attribute
|
|||||||
private Exceptions exceptions;
|
private Exceptions exceptions;
|
||||||
private Attributes attributes;
|
private Attributes attributes;
|
||||||
|
|
||||||
public Code(Attributes attributes) throws IOException
|
public Code(Attributes attributes)
|
||||||
{
|
{
|
||||||
super(attributes, AttributeType.CODE);
|
super(attributes, AttributeType.CODE);
|
||||||
|
}
|
||||||
|
|
||||||
DataInputStream is = attributes.getStream();
|
@Override
|
||||||
|
public void load() throws IOException
|
||||||
|
{
|
||||||
|
super.load();
|
||||||
|
|
||||||
|
DataInputStream is = this.getAttributes().getStream();
|
||||||
|
|
||||||
maxStack = is.readUnsignedShort();
|
maxStack = is.readUnsignedShort();
|
||||||
is.skip(2); // max locals
|
is.skip(2); // max locals
|
||||||
|
|
||||||
instructions = new Instructions(this);
|
instructions = new Instructions(this);
|
||||||
|
instructions.load();
|
||||||
|
|
||||||
exceptions = new Exceptions(this);
|
exceptions = new Exceptions(this);
|
||||||
this.attributes = new Attributes(this);
|
this.attributes = new Attributes(this);
|
||||||
@@ -96,6 +103,11 @@ public class Code extends Attribute
|
|||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInstructions(Instructions instructions)
|
||||||
|
{
|
||||||
|
this.instructions = instructions;
|
||||||
|
}
|
||||||
|
|
||||||
public void buildInstructionGraph()
|
public void buildInstructionGraph()
|
||||||
{
|
{
|
||||||
instructions.buildInstructionGraph();
|
instructions.buildInstructionGraph();
|
||||||
|
|||||||
@@ -10,21 +10,27 @@ public class ConstantValue extends Attribute
|
|||||||
{
|
{
|
||||||
private PoolEntry value;
|
private PoolEntry value;
|
||||||
|
|
||||||
public ConstantValue(Attributes attributes) throws IOException
|
public ConstantValue(Attributes attributes)
|
||||||
{
|
{
|
||||||
super(attributes, AttributeType.CONSTANT_VALUE);
|
super(attributes, AttributeType.CONSTANT_VALUE);
|
||||||
|
|
||||||
DataInputStream is = attributes.getStream();
|
|
||||||
value = this.getAttributes().getClassFile().getPool().getEntry(is.readUnsignedShort());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConstantValue(Attributes attributes, PoolEntry value)
|
public ConstantValue(Attributes attributes, PoolEntry value)
|
||||||
{
|
{
|
||||||
super(attributes, AttributeType.CONSTANT_VALUE, -1);
|
super(attributes, AttributeType.CONSTANT_VALUE);
|
||||||
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load() throws IOException
|
||||||
|
{
|
||||||
|
super.load();
|
||||||
|
|
||||||
|
DataInputStream is = this.getAttributes().getStream();
|
||||||
|
value = this.getAttributes().getClassFile().getPool().getEntry(is.readUnsignedShort());
|
||||||
|
}
|
||||||
|
|
||||||
public PoolEntry getValue()
|
public PoolEntry getValue()
|
||||||
{
|
{
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@@ -13,16 +13,22 @@ public class Exceptions extends Attribute
|
|||||||
{
|
{
|
||||||
private List<Class> classes = new ArrayList<>();
|
private List<Class> classes = new ArrayList<>();
|
||||||
|
|
||||||
public Exceptions(Attributes attributes) throws IOException
|
public Exceptions(Attributes attributes)
|
||||||
{
|
{
|
||||||
super(attributes, AttributeType.EXCEPTIONS);
|
super(attributes, AttributeType.EXCEPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
DataInputStream is = attributes.getStream();
|
@Override
|
||||||
|
public void load() throws IOException
|
||||||
|
{
|
||||||
|
super.load();
|
||||||
|
|
||||||
|
DataInputStream is = this.getAttributes().getStream();
|
||||||
|
|
||||||
int count = is.readUnsignedShort();
|
int count = is.readUnsignedShort();
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
Class clazz = attributes.getClassFile().getPool().getClass(is.readUnsignedShort());
|
Class clazz = this.getAttributes().getClassFile().getPool().getClass(is.readUnsignedShort());
|
||||||
classes.add(clazz);
|
classes.add(clazz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,18 @@ public class Unknown extends Attribute
|
|||||||
{
|
{
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
|
|
||||||
public Unknown(Attributes attributes) throws IOException
|
public Unknown(Attributes attributes)
|
||||||
{
|
{
|
||||||
super(attributes, AttributeType.UNKNOWN);
|
super(attributes, AttributeType.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load() throws IOException
|
||||||
|
{
|
||||||
|
super.load();
|
||||||
|
|
||||||
int len = this.getLength();
|
int len = this.getLength();
|
||||||
DataInputStream is = attributes.getStream();
|
DataInputStream is = this.getAttributes().getStream();
|
||||||
|
|
||||||
data = new byte[len];
|
data = new byte[len];
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,13 @@ public class Instructions
|
|||||||
private List<Instruction> instructions = new ArrayList<>();
|
private List<Instruction> instructions = new ArrayList<>();
|
||||||
private List<Block> blocks = new ArrayList<>();
|
private List<Block> blocks = new ArrayList<>();
|
||||||
|
|
||||||
public Instructions(Code code) throws IOException
|
public Instructions(Code code)
|
||||||
{
|
{
|
||||||
this.code = code;
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load() throws IOException
|
||||||
|
{
|
||||||
DataInputStream is = code.getAttributes().getStream();
|
DataInputStream is = code.getAttributes().getStream();
|
||||||
|
|
||||||
int length = is.readInt();
|
int length = is.readInt();
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import net.runelite.deob.attributes.code.instruction.types.ReturnInstruction;
|
|||||||
import net.runelite.deob.execution.Frame;
|
import net.runelite.deob.execution.Frame;
|
||||||
import net.runelite.deob.execution.InstructionContext;
|
import net.runelite.deob.execution.InstructionContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class VReturn extends Instruction implements ReturnInstruction
|
public class VReturn extends Instruction implements ReturnInstruction
|
||||||
{
|
{
|
||||||
public VReturn(Instructions instructions, InstructionType type, int pc) throws IOException
|
public VReturn(Instructions instructions, InstructionType type, int pc)
|
||||||
{
|
{
|
||||||
super(instructions, type, pc);
|
super(instructions, type, pc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,15 +11,29 @@ import net.runelite.deob.attributes.code.Instruction;
|
|||||||
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
|
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
|
||||||
import net.runelite.deob.pool.NameAndType;
|
import net.runelite.deob.pool.NameAndType;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
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.PutStatic;
|
||||||
|
import net.runelite.deob.attributes.code.instructions.VReturn;
|
||||||
|
import net.runelite.deob.execution.Execution;
|
||||||
|
import net.runelite.deob.execution.Frame;
|
||||||
|
import net.runelite.deob.execution.InstructionContext;
|
||||||
|
import net.runelite.deob.execution.StackContext;
|
||||||
|
import net.runelite.deob.signature.Signature;
|
||||||
import org.apache.commons.collections4.map.MultiValueMap;
|
import org.apache.commons.collections4.map.MultiValueMap;
|
||||||
|
|
||||||
public class FieldMover implements Deobfuscator
|
public class FieldMover implements Deobfuscator
|
||||||
{
|
{
|
||||||
private static final String mainClass = "client";
|
private static final String mainClass = "client";
|
||||||
|
|
||||||
|
private Execution execution;
|
||||||
private ClassGroup group;
|
private ClassGroup group;
|
||||||
private MultiValueMap<Field, ClassFile> fields = new MultiValueMap<>();
|
private MultiValueMap<Field, ClassFile> fields = new MultiValueMap<>();
|
||||||
|
private Map<Field, PutStatic> clinits = new HashMap<>();
|
||||||
|
|
||||||
private void findUses()
|
private void findUses()
|
||||||
{
|
{
|
||||||
@@ -48,14 +62,22 @@ public class FieldMover implements Deobfuscator
|
|||||||
if (!field.isStatic())
|
if (!field.isStatic())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (fields.containsKey(field))
|
if (m.getName().equals("<clinit>"))
|
||||||
{
|
{
|
||||||
Collection<ClassFile> col = fields.getCollection(field);
|
if (fi instanceof PutStatic)
|
||||||
if (!col.contains(cf))
|
clinits.put(field, (PutStatic) fi);
|
||||||
fields.put(field, cf);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fields.put(field, cf);
|
{
|
||||||
|
if (fields.containsKey(field))
|
||||||
|
{
|
||||||
|
Collection<ClassFile> col = fields.getCollection(field);
|
||||||
|
if (!col.contains(cf))
|
||||||
|
fields.put(field, cf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fields.put(field, cf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,13 +114,12 @@ public class FieldMover implements Deobfuscator
|
|||||||
if (list.size() == 1)
|
if (list.size() == 1)
|
||||||
return list.get(0);
|
return list.get(0);
|
||||||
|
|
||||||
// ClassFile cf = getBase(list.get(0), list.get(1));
|
ClassFile cf = getBase(list.get(0), list.get(1));
|
||||||
//
|
|
||||||
// for (int i = 2; i < list.size(); ++i)
|
for (int i = 2; i < list.size(); ++i)
|
||||||
// cf = getBase(cf, list.get(i));
|
cf = getBase(cf, list.get(i));
|
||||||
//
|
|
||||||
// return cf;
|
return cf;
|
||||||
return null; // to do this, would have to move static initializer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int moveFields()
|
private int moveFields()
|
||||||
@@ -111,9 +132,8 @@ public class FieldMover implements Deobfuscator
|
|||||||
|
|
||||||
ClassFile to = findCommonBase(cfs);
|
ClassFile to = findCommonBase(cfs);
|
||||||
if (to == null)
|
if (to == null)
|
||||||
continue;
|
|
||||||
// no common base, move to entry class
|
// no common base, move to entry class
|
||||||
//to = group.findClass(mainClass);
|
to = group.findClass(mainClass);
|
||||||
|
|
||||||
assert to != null;
|
assert to != null;
|
||||||
|
|
||||||
@@ -154,12 +174,77 @@ public class FieldMover implements Deobfuscator
|
|||||||
field.getFields().getFields().remove(field);
|
field.getFields().getFields().remove(field);
|
||||||
to.getFields().getFields().add(field);
|
to.getFields().getFields().add(field);
|
||||||
field.setFields(to.getFields());
|
field.setFields(to.getFields());
|
||||||
|
|
||||||
|
// move initializer
|
||||||
|
PutStatic setField = clinits.get(field);
|
||||||
|
if (setField == null)
|
||||||
|
return; // no initializer
|
||||||
|
|
||||||
|
Method toClinit = to.findMethod("<clinit>");
|
||||||
|
if (toClinit == null)
|
||||||
|
{
|
||||||
|
// make clinit
|
||||||
|
|
||||||
|
Signature sig = new Signature("()V");
|
||||||
|
toClinit = new Method(to.getMethods(), "<clinit>", sig);
|
||||||
|
|
||||||
|
Attributes attributes = toClinit.getAttributes();
|
||||||
|
Code code = new Code(attributes);
|
||||||
|
|
||||||
|
attributes.addAttribute(code);
|
||||||
|
|
||||||
|
// make instructions
|
||||||
|
Instructions instructions = new Instructions(code);
|
||||||
|
code.setInstructions(instructions);
|
||||||
|
|
||||||
|
instructions.getInstructions().add(new VReturn(instructions, InstructionType.RETURN, 0)); // add return
|
||||||
|
}
|
||||||
|
|
||||||
|
moveInitializer(setField, toClinit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveInitializer(PutStatic setInstruction, Method to)
|
||||||
|
{
|
||||||
|
// find instruction in execution and remove it
|
||||||
|
InstructionContext setCtx = null;
|
||||||
|
List<StackContext> ctxs = null;
|
||||||
|
for (Frame frame : execution.processedFrames)
|
||||||
|
for (InstructionContext ctx : frame.getInstructions())
|
||||||
|
{
|
||||||
|
if (ctx.getInstruction() != setInstruction)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
setCtx = ctx;
|
||||||
|
|
||||||
|
// get instructions before recursive stack removal
|
||||||
|
//List<Instruction> oldIns = new ArrayList<>(frame.getMethod().getCode().getInstructions().getInstructions());
|
||||||
|
|
||||||
|
ctxs = ctx.removeStack(0); //remove
|
||||||
|
|
||||||
|
//List<Instruction> newIns = new ArrayList<>(frame.getMethod().getCode().getInstructions().getInstructions());
|
||||||
|
|
||||||
|
//changedIns = CollectionUtils.disjunction(oldIns, newIns);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setCtx == null)
|
||||||
|
{
|
||||||
|
System.err.println("Unable to locate context for putstatic when moving field initializer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert instructions into method
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ClassGroup group)
|
public void run(ClassGroup group)
|
||||||
{
|
{
|
||||||
group.buildClassGraph();
|
group.buildClassGraph();
|
||||||
|
|
||||||
|
execution = new Execution(group);
|
||||||
|
execution.populateInitialMethods();
|
||||||
|
execution.run();
|
||||||
|
|
||||||
this.group = group;
|
this.group = group;
|
||||||
findUses();
|
findUses();
|
||||||
int count = moveFields();
|
int count = moveFields();
|
||||||
|
|||||||
@@ -75,15 +75,14 @@ public class InstructionContext
|
|||||||
return invokes;
|
return invokes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeStack(int idx)
|
public List<StackContext> removeStack(int idx)
|
||||||
{
|
{
|
||||||
// idx 0 is top of the stack, 1 is one under
|
// idx 0 is top of the stack, 1 is one under
|
||||||
// stack contexts are added to 'pops' in the order that they are popped from the stack,
|
// stack contexts are added to 'pops' in the order that they are popped from the stack,
|
||||||
// so just remove at index idx
|
StackContext ctx = pops.get(idx);
|
||||||
StackContext ctx = pops.remove(idx);
|
|
||||||
|
|
||||||
// start recursively removing
|
// start recursively removing
|
||||||
ctx.removeStack();
|
return ctx.removeStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package net.runelite.deob.execution;
|
package net.runelite.deob.execution;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class StackContext
|
public class StackContext
|
||||||
{
|
{
|
||||||
public InstructionContext pushed; // instruction which pushed this
|
public InstructionContext pushed; // instruction which pushed this
|
||||||
@@ -45,16 +48,22 @@ public class StackContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove this object from the stack
|
// remove this object from the stack
|
||||||
public void removeStack()
|
public List<StackContext> removeStack()
|
||||||
{
|
{
|
||||||
|
List<StackContext> list = new ArrayList<>();
|
||||||
|
|
||||||
|
list.add(this);
|
||||||
|
|
||||||
// remove the instruction which pushed this
|
// remove the instruction which pushed this
|
||||||
if (!pushed.getInstruction().removeStack())
|
if (!pushed.getInstruction().removeStack())
|
||||||
// dup will return false as the other objects on the stack below this are necessary
|
// dup will return false as the other objects on the stack below this are necessary
|
||||||
// for the other branch.
|
// for the other branch.
|
||||||
return;
|
return list;
|
||||||
|
|
||||||
// remove from the stack things this instruction read
|
// remove from the stack things this instruction read
|
||||||
for (StackContext ctx : pushed.getPops())
|
for (StackContext ctx : pushed.getPops())
|
||||||
ctx.removeStack();
|
list.addAll(ctx.removeStack());
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user