cleanup
This commit is contained in:
@@ -14,18 +14,13 @@ import net.runelite.asm.attributes.code.instructions.Goto;
|
|||||||
import net.runelite.asm.attributes.code.instructions.If;
|
import net.runelite.asm.attributes.code.instructions.If;
|
||||||
import net.runelite.asm.attributes.code.instructions.If0;
|
import net.runelite.asm.attributes.code.instructions.If0;
|
||||||
import net.runelite.asm.execution.Execution;
|
import net.runelite.asm.execution.Execution;
|
||||||
import net.runelite.asm.execution.Frame;
|
|
||||||
import net.runelite.asm.execution.InstructionContext;
|
import net.runelite.asm.execution.InstructionContext;
|
||||||
import net.runelite.asm.execution.StackContext;
|
import net.runelite.asm.execution.StackContext;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import net.runelite.asm.attributes.Annotations;
|
import net.runelite.asm.attributes.Annotations;
|
||||||
import net.runelite.asm.attributes.Attributes;
|
import net.runelite.asm.attributes.Attributes;
|
||||||
import net.runelite.asm.attributes.annotation.Annotation;
|
import net.runelite.asm.attributes.annotation.Annotation;
|
||||||
@@ -80,20 +75,12 @@ class ConstantMethodParameter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MethodGroup
|
|
||||||
{
|
|
||||||
public List<Method> methods; // methods that can be invoked
|
|
||||||
public Collection<Integer> constantParameters; // parameters which are always constant for all invocations
|
|
||||||
public List<ConstantMethodParameter> cmps = new ArrayList<>(); // cmps for all methods in the group, which hold the values.
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConstantParameter implements Deobfuscator
|
public class ConstantParameter implements Deobfuscator
|
||||||
{
|
{
|
||||||
private List<ConstantMethodParameter> parameters = new ArrayList<>();
|
private List<ConstantMethodParameter> parameters = new ArrayList<>();
|
||||||
private MultiValueMap<Method, ConstantMethodParameter> mparams = new MultiValueMap<>();
|
private MultiValueMap<Method, ConstantMethodParameter> mparams = new MultiValueMap<>();
|
||||||
|
|
||||||
private MultiValueMap<Method, Integer> nonconst = new MultiValueMap<>(); // methods with non const parameters
|
private MultiValueMap<Method, Integer> nonconst = new MultiValueMap<>(); // methods with non const parameters
|
||||||
private List<MethodGroup> methodGroups = new ArrayList<>();
|
|
||||||
|
|
||||||
private void checkMethodsAreConsistent(List<Method> methods)
|
private void checkMethodsAreConsistent(List<Method> methods)
|
||||||
{
|
{
|
||||||
@@ -109,10 +96,8 @@ public class ConstantParameter implements Deobfuscator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ConstantMethodParameter> findConstantParameter(List<Method> methods, InstructionContext invokeCtx)
|
private void findConstantParameter(List<Method> methods, InstructionContext invokeCtx)
|
||||||
{
|
{
|
||||||
List<ConstantMethodParameter> list = new ArrayList<>();
|
|
||||||
|
|
||||||
checkMethodsAreConsistent(methods);
|
checkMethodsAreConsistent(methods);
|
||||||
|
|
||||||
Method method = methods.get(0); // all methods must have the same signature etc
|
Method method = methods.get(0); // all methods must have the same signature etc
|
||||||
@@ -157,8 +142,6 @@ public class ConstantParameter implements Deobfuscator
|
|||||||
parameters.add(cmp);
|
parameters.add(cmp);
|
||||||
for (Method m : methods)
|
for (Method m : methods)
|
||||||
mparams.put(m, cmp);
|
mparams.put(m, cmp);
|
||||||
|
|
||||||
list.add(cmp);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -172,13 +155,10 @@ public class ConstantParameter implements Deobfuscator
|
|||||||
if (c.methods.equals(methods) && c.lvtIndex == lvtOffset)
|
if (c.methods.equals(methods) && c.lvtIndex == lvtOffset)
|
||||||
{
|
{
|
||||||
it.remove();
|
it.remove();
|
||||||
list.remove(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findParameters(InstructionContext ins)
|
private void findParameters(InstructionContext ins)
|
||||||
@@ -191,19 +171,14 @@ public class ConstantParameter implements Deobfuscator
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
findConstantParameter(methods, ins);
|
findConstantParameter(methods, ins);
|
||||||
//findDeadParameters(ins, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ConstantMethodParameter> findParametersForMethod(Method m)
|
private List<ConstantMethodParameter> findParametersForMethod(Method m)
|
||||||
{
|
{
|
||||||
Collection c = mparams.getCollection(m);
|
Collection<ConstantMethodParameter> c = mparams.getCollection(m);
|
||||||
if (c == null) return new ArrayList();
|
if (c == null)
|
||||||
return new ArrayList(c);
|
return new ArrayList<>();
|
||||||
// List<ConstantMethodParameter> list = new ArrayList<>();
|
return new ArrayList<>(c);
|
||||||
// for (ConstantMethodParameter c : parameters)
|
|
||||||
// if (c.methods.contains(m))
|
|
||||||
// list.add(c);
|
|
||||||
// return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findDeadParameters(InstructionContext ins)
|
private void findDeadParameters(InstructionContext ins)
|
||||||
@@ -297,27 +272,9 @@ public class ConstantParameter implements Deobfuscator
|
|||||||
parameter.operations.add(ins);
|
parameter.operations.add(ins);
|
||||||
parameter.result = result;
|
parameter.result = result;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// Boolean b = deadOps.get(ins.getInstruction());
|
|
||||||
// if (b != null)
|
|
||||||
// {
|
|
||||||
// if (b != result)
|
|
||||||
// {
|
|
||||||
// //deadOps.remove(ins.getInstruction());
|
|
||||||
// this.parameters.remove(parameter);
|
|
||||||
// //invalidDeadOps.add(ins.getInstruction());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// deadOps.put(ins.getInstruction(), result);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private Map<Instruction, Boolean> deadOps = new HashMap<>();
|
|
||||||
// private Set<Instruction> invalidDeadOps = new HashSet<>();
|
|
||||||
|
|
||||||
private boolean doLogicalComparison(Object value, ComparisonInstruction comparison, Object otherValue)
|
private boolean doLogicalComparison(Object value, ComparisonInstruction comparison, Object otherValue)
|
||||||
{
|
{
|
||||||
Instruction ins = (Instruction) comparison;
|
Instruction ins = (Instruction) comparison;
|
||||||
@@ -356,227 +313,6 @@ public class ConstantParameter implements Deobfuscator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LogicallyDeadOp
|
|
||||||
{
|
|
||||||
InstructionContext compCtx; // logically dead comparison
|
|
||||||
boolean branch; // branch which is always taken
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final LogicallyDeadOp other = (LogicallyDeadOp) obj;
|
|
||||||
if (!Objects.equals(this.compCtx.getInstruction(), other.compCtx.getInstruction()))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.branch != other.branch)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// find all comparisons of lvtIndex in method and record branch taken
|
|
||||||
// private List<LogicallyDeadOp> isLogicallyDead(Execution execution, Method method, int lvtIndex, Object value)
|
|
||||||
// {
|
|
||||||
// List<LogicallyDeadOp> ops = new ArrayList<>();
|
|
||||||
//
|
|
||||||
// for (Frame frame : execution.processedFrames)
|
|
||||||
// {
|
|
||||||
// if (frame.getMethod() != method)
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// for (InstructionContext ins : frame.getInstructions())
|
|
||||||
// {
|
|
||||||
// if (ins.getInstruction() instanceof LVTInstruction)
|
|
||||||
// {
|
|
||||||
// LVTInstruction lvt = (LVTInstruction) ins.getInstruction();
|
|
||||||
//
|
|
||||||
// if (lvt.getVariableIndex() == lvtIndex && lvt.store())
|
|
||||||
// {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!(ins.getInstruction() instanceof ComparisonInstruction))
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// // assume that this will always be variable index #paramIndex comp with a constant.
|
|
||||||
//
|
|
||||||
// ComparisonInstruction comp = (ComparisonInstruction) ins.getInstruction();
|
|
||||||
//
|
|
||||||
// StackContext one, two = null;
|
|
||||||
//
|
|
||||||
// if (comp instanceof If0)
|
|
||||||
// {
|
|
||||||
// one = ins.getPops().get(0);
|
|
||||||
// }
|
|
||||||
// else if (comp instanceof If)
|
|
||||||
// {
|
|
||||||
// one = ins.getPops().get(0);
|
|
||||||
// two = ins.getPops().get(1);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// throw new RuntimeException("Unknown comp ins");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // find if one is a lvt ins
|
|
||||||
// LVTInstruction lvt = null;
|
|
||||||
// StackContext other = null;
|
|
||||||
//
|
|
||||||
// if (one.getPushed().getInstruction() instanceof LVTInstruction)
|
|
||||||
// {
|
|
||||||
// lvt = (LVTInstruction) one.getPushed().getInstruction();
|
|
||||||
// other = two;
|
|
||||||
// }
|
|
||||||
// else if (two != null && two.getPushed().getInstruction() instanceof LVTInstruction)
|
|
||||||
// {
|
|
||||||
// lvt = (LVTInstruction) two.getPushed().getInstruction();
|
|
||||||
// other = one;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// assert lvt == null || !lvt.store();
|
|
||||||
//
|
|
||||||
// if (lvt == null || lvt.getVariableIndex() != lvtIndex)
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// Object otherValue = null;
|
|
||||||
//
|
|
||||||
// if (two != null) // two is null for if0
|
|
||||||
// {
|
|
||||||
// if (!(other.getPushed().getInstruction() instanceof PushConstantInstruction))
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// PushConstantInstruction pc = (PushConstantInstruction) other.getPushed().getInstruction();
|
|
||||||
// otherValue = pc.getConstant().getObject();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // the result of the comparison doesn't matter, only that it always goes the same direction for every invocation
|
|
||||||
// boolean result = doLogicalComparison(value, comp, otherValue);
|
|
||||||
//
|
|
||||||
// LogicallyDeadOp deadOp = new LogicallyDeadOp();
|
|
||||||
// deadOp.compCtx = ins;
|
|
||||||
// deadOp.branch = result;
|
|
||||||
// ops.add(deadOp);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return ops;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private static class MethodLvtPair
|
|
||||||
{
|
|
||||||
Method method;
|
|
||||||
int lvtIndex;
|
|
||||||
int paramIndex;
|
|
||||||
Object value; // example value, used for @ObfuscatedSignature. Just one possible value.
|
|
||||||
|
|
||||||
public MethodLvtPair(Method method, int lvtIndex, int paramIndex, Object value)
|
|
||||||
{
|
|
||||||
this.method = method;
|
|
||||||
this.lvtIndex = lvtIndex;
|
|
||||||
this.paramIndex = paramIndex;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
int hash = 5;
|
|
||||||
hash = 31 * hash + Objects.hashCode(this.method);
|
|
||||||
hash = 31 * hash + this.lvtIndex;
|
|
||||||
hash = 31 * hash + this.paramIndex;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final MethodLvtPair other = (MethodLvtPair) obj;
|
|
||||||
if (!Objects.equals(this.method, other.method))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.lvtIndex != other.lvtIndex)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.paramIndex != other.paramIndex)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// private Map<MethodLvtPair, List<LogicallyDeadOp> > deadops = new HashMap<>();
|
|
||||||
// private Set<MethodLvtPair> invalidDeadops = new HashSet<>();
|
|
||||||
|
|
||||||
// check every method parameter that we've identified as being passed constants to see if it's logically dead
|
|
||||||
// private void findLogicallyDeadOperations(Execution execution)
|
|
||||||
// {
|
|
||||||
// for (ConstantMethodParameter cmp : parameters)
|
|
||||||
// {
|
|
||||||
// for (Method method : cmp.methods)
|
|
||||||
// {
|
|
||||||
// MethodLvtPair pair = new MethodLvtPair(method, cmp.lvtIndex, cmp.paramIndex, cmp.value);
|
|
||||||
//
|
|
||||||
// if (invalidDeadops.contains(pair))
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// // the dead comparisons must be the same and branch the same way for every call to this method.
|
|
||||||
// List<LogicallyDeadOp> deadOps = isLogicallyDead(execution, method, cmp.lvtIndex, cmp.value);
|
|
||||||
//
|
|
||||||
// if (deadOps == null)
|
|
||||||
// {
|
|
||||||
// deadops.remove(pair);
|
|
||||||
// invalidDeadops.add(pair);
|
|
||||||
// continue; // lvt store
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (deadOps.isEmpty())
|
|
||||||
// continue; // no ops to compare
|
|
||||||
//
|
|
||||||
// // this must be per method,lvtindex
|
|
||||||
// List<LogicallyDeadOp> existing = deadops.get(pair);
|
|
||||||
// if (existing != null)
|
|
||||||
// if (!existing.equals(deadOps))
|
|
||||||
// {
|
|
||||||
// // one of the branches taken differs because of the value, skip it
|
|
||||||
// deadops.remove(pair);
|
|
||||||
// invalidDeadops.add(pair);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// deadops.put(pair, deadOps);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// remove logically dead comparisons
|
// remove logically dead comparisons
|
||||||
private int removeDeadOperations()
|
private int removeDeadOperations()
|
||||||
{
|
{
|
||||||
@@ -671,20 +407,12 @@ public class ConstantParameter implements Deobfuscator
|
|||||||
@Override
|
@Override
|
||||||
public void run(ClassGroup group)
|
public void run(ClassGroup group)
|
||||||
{
|
{
|
||||||
group.buildClassGraph(); // required for getMethods in the invoke stuff by execution...
|
|
||||||
|
|
||||||
Execution execution = new Execution(group);
|
Execution execution = new Execution(group);
|
||||||
execution.addExecutionVisitor((i) -> findParameters(i));
|
execution.addExecutionVisitor((i) -> findParameters(i));
|
||||||
execution.addExecutionVisitor((i) -> findDeadParameters(i));
|
execution.addExecutionVisitor((i) -> findDeadParameters(i));
|
||||||
execution.populateInitialMethods();
|
execution.populateInitialMethods();
|
||||||
execution.run();
|
execution.run();
|
||||||
|
|
||||||
// execution = new Execution(group);
|
|
||||||
// execution.addExecutionVisitor((i) -> findDeadParameters(i));
|
|
||||||
// execution.populateInitialMethods();
|
|
||||||
// execution.run();
|
|
||||||
|
|
||||||
//findLogicallyDeadOperations(execution);
|
|
||||||
int count = removeDeadOperations();
|
int count = removeDeadOperations();
|
||||||
|
|
||||||
System.out.println("Removed " + count + " logically dead conditional jumps");
|
System.out.println("Removed " + count + " logically dead conditional jumps");
|
||||||
|
|||||||
Reference in New Issue
Block a user