Remove old graph stuff, all tests pass
This commit is contained in:
@@ -17,7 +17,6 @@ import net.runelite.deob.deobfuscators.arithmetic.ModArith;
|
||||
import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator;
|
||||
import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator;
|
||||
import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator;
|
||||
import net.runelite.deob.deobfuscators.rename.Rename2;
|
||||
import net.runelite.deob.execution.Execution;
|
||||
import net.runelite.deob.util.JarUtil;
|
||||
|
||||
@@ -107,9 +106,9 @@ public class Deob
|
||||
{
|
||||
ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")),
|
||||
group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));
|
||||
|
||||
Rename2 rename = new Rename2();
|
||||
rename.run(group1, group2);
|
||||
//
|
||||
// Rename2 rename = new Rename2();
|
||||
// rename.run(group1, group2);
|
||||
}
|
||||
|
||||
public static boolean isObfuscated(String name)
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename;
|
||||
|
||||
import java.util.Objects;
|
||||
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
|
||||
|
||||
public class ConstantWrapper
|
||||
{
|
||||
private Object object;
|
||||
private PushConstantInstruction pci;
|
||||
|
||||
public ConstantWrapper(Object object, PushConstantInstruction pci)
|
||||
{
|
||||
this.object = object;
|
||||
this.pci = pci;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "constant " + object.getClass().getName() + " " + object + " from instruction " + pci;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 3;
|
||||
hash = 53 * hash + Objects.hashCode(this.object);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final ConstantWrapper other = (ConstantWrapper) obj;
|
||||
if (!Objects.equals(this.object, other.object))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename;
|
||||
|
||||
import java.util.Objects;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
|
||||
import net.runelite.deob.signature.Type;
|
||||
|
||||
public class FieldWrapper
|
||||
{
|
||||
private static final int FIELD_MASK = Field.ACC_FINAL | Field.ACC_STATIC;
|
||||
|
||||
private FieldInstruction fi;
|
||||
public Field field;
|
||||
private Type type;
|
||||
private short accessFlags;
|
||||
|
||||
public FieldWrapper(FieldInstruction fi ,Field field)
|
||||
{
|
||||
this.fi = fi;
|
||||
this.field = field;
|
||||
this.type = field.getType();
|
||||
this.accessFlags = field.getAccessFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return field.toString() + " access from instruction " + fi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 3;
|
||||
hash = 29 * hash + Objects.hashCode(this.type);
|
||||
hash = 29 * hash + (this.accessFlags & FIELD_MASK);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final FieldWrapper other = (FieldWrapper) obj;
|
||||
if (!Objects.equals(this.type, other.type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((this.accessFlags & FIELD_MASK) != (other.accessFlags & FIELD_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.attributes.code.Instruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
||||
import net.runelite.deob.pool.PoolEntry;
|
||||
import net.runelite.deob.signature.Signature;
|
||||
|
||||
public class InstructionList
|
||||
{
|
||||
private final List<Instruction> instructions;
|
||||
|
||||
public InstructionList(List<Instruction> instructions)
|
||||
{
|
||||
this.instructions = instructions;
|
||||
}
|
||||
|
||||
public boolean couldBeEqual(InstructionList other)
|
||||
{
|
||||
Multiset<Signature> sig1 = HashMultiset.create(),
|
||||
sig2 = HashMultiset.create();
|
||||
|
||||
// check signatures and field types
|
||||
instructions.stream().filter(i -> i instanceof InvokeInstruction).forEach(i -> {
|
||||
assert !(i instanceof InvokeStatic);
|
||||
|
||||
InvokeInstruction iv = (InvokeInstruction) i;
|
||||
for (Method m : iv.getMethods())
|
||||
sig1.add(m.getDescriptor());
|
||||
});
|
||||
|
||||
other.instructions.stream().filter(i -> i instanceof InvokeInstruction).forEach(i -> {
|
||||
assert !(i instanceof InvokeStatic);
|
||||
|
||||
InvokeInstruction iv = (InvokeInstruction) i;
|
||||
for (Method m : iv.getMethods())
|
||||
sig2.add(m.getDescriptor());
|
||||
});
|
||||
|
||||
if (!sig1.equals(sig2))
|
||||
return false;
|
||||
|
||||
Set<FieldWrapper> type1 = new HashSet<>(),
|
||||
type2 = new HashSet<>();
|
||||
|
||||
instructions.stream().filter(i -> i instanceof GetFieldInstruction).forEach(i -> {
|
||||
GetFieldInstruction gfi = (GetFieldInstruction) i;
|
||||
Field f = gfi.getMyField();
|
||||
if (f != null)
|
||||
type1.add(new FieldWrapper(gfi, f));
|
||||
});
|
||||
|
||||
other.instructions.stream().filter(i -> i instanceof GetFieldInstruction).forEach(i -> {
|
||||
GetFieldInstruction gfi = (GetFieldInstruction) i;
|
||||
Field f = gfi.getMyField();
|
||||
if (f != null)
|
||||
type2.add(new FieldWrapper(gfi, f));
|
||||
});
|
||||
|
||||
if (!type1.equals(type2))
|
||||
{
|
||||
for (FieldWrapper fw : type1)
|
||||
{
|
||||
if (!type2.contains(fw))
|
||||
{
|
||||
// 2726 -> 2738
|
||||
System.out.println(fw + " not in type2");
|
||||
for (FieldWrapper fw2 : type2)
|
||||
{
|
||||
if (fw2.field.getName().equals("field2738"))
|
||||
{
|
||||
int i= 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Multiset<FieldWrapper> ms1 = HashMultiset.create(),
|
||||
ms2 = HashMultiset.create();
|
||||
|
||||
instructions.stream().filter(i -> i instanceof SetFieldInstruction).forEach(i -> {
|
||||
SetFieldInstruction sfi = (SetFieldInstruction) i;
|
||||
Field f = sfi.getMyField();
|
||||
if (f != null)
|
||||
ms1.add(new FieldWrapper(sfi, f));
|
||||
});
|
||||
|
||||
other.instructions.stream().filter(i -> i instanceof SetFieldInstruction).forEach(i -> {
|
||||
SetFieldInstruction sfi = (SetFieldInstruction) i;
|
||||
Field f = sfi.getMyField();
|
||||
if (f != null)
|
||||
ms2.add(new FieldWrapper(sfi, f));
|
||||
});
|
||||
|
||||
if (!ms1.equals(ms2))
|
||||
return false;
|
||||
|
||||
Set<ConstantWrapper> constants1 = new HashSet<>(),
|
||||
constants2 = new HashSet<>();
|
||||
|
||||
instructions.stream().filter(i -> i instanceof PushConstantInstruction).forEach(i -> {
|
||||
PushConstantInstruction pci = (PushConstantInstruction) i;
|
||||
PoolEntry e = pci.getConstant();
|
||||
Object o = e.getObject();
|
||||
|
||||
if (o instanceof Integer || o instanceof Long)
|
||||
return;
|
||||
|
||||
constants1.add(new ConstantWrapper(o, pci));
|
||||
});
|
||||
|
||||
other.instructions.stream().filter(i -> i instanceof PushConstantInstruction).forEach(i -> {
|
||||
PushConstantInstruction pci = (PushConstantInstruction) i;
|
||||
PoolEntry e = pci.getConstant();
|
||||
Object o = e.getObject();
|
||||
|
||||
if (o instanceof Integer || o instanceof Long)
|
||||
return;
|
||||
|
||||
constants2.add(new ConstantWrapper(o, pci));
|
||||
});
|
||||
|
||||
if (!constants1.equals(constants2))
|
||||
{
|
||||
for (ConstantWrapper o : constants1)
|
||||
{
|
||||
if (!constants2.contains(o))
|
||||
{
|
||||
System.out.println(o);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
//package net.runelite.deob.deobfuscators.rename;
|
||||
//
|
||||
//import edu.ucla.sspace.graph.Edge;
|
||||
//import edu.ucla.sspace.graph.Graph;
|
||||
//import edu.ucla.sspace.graph.isomorphism.IsomorphismTester;
|
||||
//import edu.ucla.sspace.graph.isomorphism.VF2IsomorphismTester;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.HashSet;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//import java.util.Map.Entry;
|
||||
//import java.util.Optional;
|
||||
//import java.util.Set;
|
||||
//import java.util.stream.Collectors;
|
||||
//import net.runelite.deob.ClassGroup;
|
||||
//import net.runelite.deob.Method;
|
||||
//import net.runelite.deob.execution.Execution;
|
||||
//import net.runelite.deob.execution.Frame;
|
||||
//import net.runelite.deob.execution.MethodContext;
|
||||
//
|
||||
//public class Rename
|
||||
//{
|
||||
// private ClassGroup groupOne, groupTwo;
|
||||
//
|
||||
// // respective executions
|
||||
// //private Execution eone, etwo;
|
||||
//
|
||||
// // old -> new object mapping
|
||||
// private Map<Object, Object> objMap = new HashMap<>();
|
||||
//
|
||||
// // methods which have been processed in the original
|
||||
// private Set<Method> processed = new HashSet<>();
|
||||
//
|
||||
// private static String cname(Method m) { return m.getMethods().getClassFile().getName(); }
|
||||
// private static String mname(Method m) { return cname(m) + "." + m.getName(); }
|
||||
//
|
||||
// private void compare(MethodContext m1, Graph g1, MethodContext m2, Graph g2)
|
||||
// {
|
||||
// Set<Edge> edges = new HashSet<>(g1.edges()); // edges in g1 not in g2
|
||||
// for (Edge e : (Set<Edge>) g2.edges())
|
||||
// {
|
||||
// edges.remove(e);
|
||||
// }
|
||||
//
|
||||
// for (Edge e : edges)
|
||||
// {
|
||||
// Method me1 = m1.getIdMap().get(e.from()).get(0);
|
||||
// Method me2 = m1.getIdMap().get(e.to()).get(0);
|
||||
//
|
||||
// System.out.println("EDGE IN 1 NOT IN 2: " + mname(me1) + " -> " + mname(me2));
|
||||
//
|
||||
// Method om1 = m2.getIdMap().get(e.from()).get(0);
|
||||
// Method om2 = m2.getIdMap().get(e.to()).get(0);
|
||||
//
|
||||
// System.out.println(" OTHER SIDE: " + mname(om1) + " -> " + mname(om2));
|
||||
// }
|
||||
// //System.out.println(edges);
|
||||
//
|
||||
// if (g2.order() == g1.order())
|
||||
// {
|
||||
// int[] v1 = g1.vertices().toPrimitiveArray(),
|
||||
// v2 = g2.vertices().toPrimitiveArray();
|
||||
// for (int i = 0; i < g1.order(); ++i)
|
||||
// {
|
||||
// Method me1 = m1.getIdMap().get(v1[i]).get(0);
|
||||
// Method me2 = m2.getIdMap().get(v2[i]).get(0);
|
||||
//
|
||||
// System.out.println("VMATCH " + mname(me1) + " -> " + mname(me2));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private boolean compare(Frame f1, Frame f2)
|
||||
// {
|
||||
// Graph g1 = f1.getMethodCtx().getGraph(), g2 = f2.getMethodCtx().getGraph();
|
||||
//
|
||||
// IsomorphismTester isoTest = new /*Typed*/VF2IsomorphismTester();
|
||||
// if (g1.size() != g2.size() || g1.order() != g2.order() || !isoTest.areIsomorphic(g1, g2))
|
||||
// {
|
||||
// System.out.println("IN " + mname(f1.getMethod()) + " -> " + mname(f2.getMethod()));
|
||||
// compare(f1.getMethodCtx(), g1, f2.getMethodCtx(), g2);
|
||||
// System.out.println("Not isomorphic " + g1.size() + " " + g2.size());
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Map<Integer, Integer> mapping = isoTest.findIsomorphism(g1, g2);
|
||||
// Map<Integer, List<Method>> map1 = f1.getMethodCtx().getIdMap(), map2 = f2.getMethodCtx().getIdMap();
|
||||
//
|
||||
// for (Entry<Integer, Integer> e : mapping.entrySet())
|
||||
// {
|
||||
//// if (e.getKey() == null || e.getValue() == null)
|
||||
//// {
|
||||
//// assert e.getKey() == e.getValue();
|
||||
//// continue;
|
||||
//// }
|
||||
//
|
||||
// List<Method> i1 = map1.get(e.getKey());
|
||||
// List<Method> i2 = map2.get(e.getValue());
|
||||
//
|
||||
// //assert i1.getClass() == i2.getClass();
|
||||
//
|
||||
// //InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2;
|
||||
//
|
||||
// //assert ii1.getMethods().size() == ii2.getMethods().size();
|
||||
//
|
||||
// assert i1.size() == i2.size();
|
||||
//
|
||||
// for (int i = 0; i < i1.size(); ++i)
|
||||
// {
|
||||
// Method m1 = i1.get(i), m2 = i2.get(i);
|
||||
//
|
||||
//// assert objMap.containsKey(m1) == false || objMap.get(m1) == m2;
|
||||
// objMap.put(m1, m2);
|
||||
// }
|
||||
//
|
||||
// System.out.println("MATCH " + i1.get(0).getName() + " -> " + i2.get(0).getName());
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private void process(Method one, Method two)
|
||||
// {
|
||||
// Execution eone = new Execution(groupOne);
|
||||
// eone.setBuildGraph(true);
|
||||
// eone.setFollowInvokes(false);
|
||||
// eone.addMethod(one);
|
||||
// eone.run();
|
||||
//
|
||||
// Execution etwo = new Execution(groupTwo);
|
||||
// etwo.setBuildGraph(true);
|
||||
// etwo.setFollowInvokes(false);
|
||||
// etwo.addMethod(two);
|
||||
// etwo.run();
|
||||
//
|
||||
// // get frames for respective methods
|
||||
// List<Frame> f1 = eone.processedFrames, f2 = etwo.processedFrames;
|
||||
//
|
||||
// f1 = f1.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList());
|
||||
// f2 = f2.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList());
|
||||
//
|
||||
// //List<Frame> f1 = eone.processedFrames.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList());
|
||||
// //List<Frame> f2 = etwo.processedFrames.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList());
|
||||
//
|
||||
// Frame p1 = null, p2 = null;
|
||||
// outer:
|
||||
// for (Frame fr1 : f1)
|
||||
// for (Frame fr2 : f2)
|
||||
// {
|
||||
// if (p1 == null) p1 = fr1;
|
||||
// if (p2 == null) p2 = fr2;
|
||||
//
|
||||
// assert fr1.getMethod() == one;
|
||||
// assert fr2.getMethod() == two;
|
||||
//
|
||||
// assert fr1.getMethodCtx() == p1.getMethodCtx();
|
||||
// assert fr2.getMethodCtx() == p2.getMethodCtx();
|
||||
// }
|
||||
//
|
||||
// assert p1.getMethod() == one;
|
||||
// assert p2.getMethod() == two;
|
||||
//
|
||||
// outer2:
|
||||
// for (Frame fr1 : f1)
|
||||
// for (Frame fr2 : f2)
|
||||
// {
|
||||
// boolean b = compare(fr1, fr2);
|
||||
// if (!b)
|
||||
// {
|
||||
// System.out.println("Mismatch " + p1.getMethod().getMethods().getClassFile().getName() + "." + p1.getMethod().getName() + " <-> " + p2.getMethod().getMethods().getClassFile().getName() + "." + p2.getMethod().getName());
|
||||
// System.out.println(one.getMethods().getClassFile().getName() + "." + one.getName() + " and " + two.getMethods().getClassFile().getName() + "." + two.getName());
|
||||
// int i =7;
|
||||
// }
|
||||
// break outer2;
|
||||
// }
|
||||
//
|
||||
// System.out.println("end");
|
||||
// }
|
||||
// public void run(ClassGroup one, ClassGroup two)
|
||||
// {
|
||||
// groupOne = one;
|
||||
// groupTwo = two;
|
||||
//
|
||||
//// Execution eone = new Execution(one);
|
||||
//// eone.setBuildGraph(true);
|
||||
//// eone.setFollowInvokes(false);
|
||||
//// eone.populateInitialMethods();
|
||||
//// List<Method> initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
|
||||
//// eone.run();
|
||||
////
|
||||
//// Execution etwo = new Execution(two);
|
||||
//// etwo.setBuildGraph(true);
|
||||
//// etwo.setFollowInvokes(false);
|
||||
//// etwo.populateInitialMethods();
|
||||
//// List<Method> initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
|
||||
//// etwo.run();
|
||||
////
|
||||
//// assert initial1.size() == initial2.size();
|
||||
////
|
||||
//// for (int i = 0; i < initial1.size(); ++i)
|
||||
//// {
|
||||
//// Method m1 = initial1.get(i), m2 = initial2.get(i);
|
||||
////
|
||||
//// assert m1.getName().equals(m2.getName());
|
||||
////
|
||||
//// objMap.put(m1, m2);
|
||||
//// }
|
||||
//
|
||||
// process(
|
||||
// one.findClass("client").findMethod("vmethod2999"),
|
||||
// two.findClass("client").findMethod("vmethod2978")
|
||||
// );
|
||||
//
|
||||
// for (;;)
|
||||
// {
|
||||
// Optional next = objMap.keySet().stream()
|
||||
// .filter(m -> !processed.contains(m))
|
||||
// .findAny();
|
||||
// if (!next.isPresent())
|
||||
// break;
|
||||
//
|
||||
// Method m = (Method) next.get();
|
||||
// Method m2 = (Method) objMap.get(m);
|
||||
//
|
||||
// if (m.getCode() == null || m2.getCode() == null)
|
||||
// {
|
||||
// processed.add(m);
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// System.out.println("Scanning " + m.getMethods().getClassFile().getName() + "." + m.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName());
|
||||
// process(m, m2);
|
||||
// processed.add(m);
|
||||
// }
|
||||
//
|
||||
// for (Entry<Object, Object> e : objMap.entrySet())
|
||||
// {
|
||||
// Method m1 = (Method) e.getKey();
|
||||
// Method m2 = (Method) e.getValue();
|
||||
//
|
||||
// System.out.println("FINAL " + m1.getMethods().getClassFile().getName() + "." + m1.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName());
|
||||
// }
|
||||
//
|
||||
// System.out.println("done count " + objMap.size());
|
||||
// }
|
||||
//}
|
||||
@@ -1,728 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import net.runelite.deob.ClassFile;
|
||||
import net.runelite.deob.ClassGroup;
|
||||
import net.runelite.deob.Deob;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.attributes.Annotations;
|
||||
import net.runelite.deob.attributes.AttributeType;
|
||||
import net.runelite.deob.attributes.Attributes;
|
||||
import net.runelite.deob.attributes.annotation.Annotation;
|
||||
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||
import net.runelite.deob.deobfuscators.Renamer;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.Edge;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.EdgeType;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.Graph;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.GraphBuilder;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.Vertex;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.VertexType;
|
||||
import net.runelite.deob.execution.Execution;
|
||||
import net.runelite.deob.execution.Frame;
|
||||
import net.runelite.deob.execution.InstructionContext;
|
||||
import net.runelite.deob.signature.Signature;
|
||||
import net.runelite.deob.signature.Type;
|
||||
import net.runelite.deob.util.JarUtil;
|
||||
import net.runelite.deob.util.NameMappings;
|
||||
|
||||
public class Rename2
|
||||
{
|
||||
private Graph g1, g2;
|
||||
|
||||
private static String cname(Method m) { return m.getMethods().getClassFile().getName(); }
|
||||
public static String mname(Method m) { return cname(m) + "." + m.getName(); }
|
||||
private static String fname(Field f) { return f.getFields().getClassFile().getName() + "." + f.getName(); }
|
||||
|
||||
public static void collide(Object o0, Object o1, Object o2)
|
||||
{
|
||||
assert o0.getClass() == o1.getClass();
|
||||
assert o1.getClass() == o2.getClass();
|
||||
|
||||
if (o1 instanceof Method)
|
||||
{
|
||||
Method m0 = (Method) o0;
|
||||
Method m1 = (Method) o1;
|
||||
Method m2 = (Method) o2;
|
||||
|
||||
System.out.println("COLLISION on " + mname(m0) + ": " + mname(m1) + " -> " + mname(m2));
|
||||
}
|
||||
else if (o1 instanceof Field)
|
||||
{
|
||||
Field f0 = (Field) o0;
|
||||
Field f1 = (Field) o1;
|
||||
Field f2 = (Field) o2;
|
||||
|
||||
System.out.println("COLLISION " + fname(f0) + ": " + fname(f1) + " -> " + fname(f2));
|
||||
}
|
||||
else
|
||||
assert false;
|
||||
}
|
||||
|
||||
private Map<Signature, Method> find(ClassFile cf)
|
||||
{
|
||||
Map<Signature, Method> set = new HashMap();
|
||||
Set collided = new HashSet();
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
if (m.isStatic())
|
||||
continue;
|
||||
|
||||
Signature sig = m.getDescriptor();
|
||||
|
||||
if (set.containsKey(sig) || collided.contains(sig))
|
||||
{
|
||||
collided.add(sig);
|
||||
set.remove(sig);
|
||||
continue;
|
||||
}
|
||||
set.put(sig, m);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
private Map<Type, Field> findField(ClassFile cf)
|
||||
{
|
||||
Map<Type, Field> set = new HashMap<>();
|
||||
Set collided = new HashSet();
|
||||
for (Field f : cf.getFields().getFields())
|
||||
{
|
||||
if (f.isStatic())
|
||||
continue;
|
||||
|
||||
Type t = f.getType();
|
||||
|
||||
if (set.containsKey(t) || collided.contains(t))
|
||||
{
|
||||
collided.add(t);
|
||||
set.remove(t);
|
||||
continue;
|
||||
}
|
||||
set.put(t, f);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
private void mapClassMethods(Map<Signature, Method> one, Map<Signature, Method> two)
|
||||
{
|
||||
if (!one.keySet().equals(two.keySet()))
|
||||
return;
|
||||
|
||||
for (Signature sig : one.keySet())
|
||||
{
|
||||
Method m1 = one.get(sig);
|
||||
Method m2 = two.get(sig);
|
||||
|
||||
Vertex v1 = g1.getVertexFor(m1);
|
||||
Vertex v2 = g2.getVertexFor(m2);
|
||||
|
||||
v1.is(v2);
|
||||
v2.is(v1);
|
||||
|
||||
System.out.println(mname(m1) + " is " + mname(m2));
|
||||
}
|
||||
}
|
||||
|
||||
private void mapClassFields(Map<Type, Field> one, Map<Type, Field> two)
|
||||
{
|
||||
if (!one.keySet().equals(two.keySet()))
|
||||
return;
|
||||
|
||||
for (Type t : one.keySet())
|
||||
{
|
||||
Field f1 = one.get(t), f2 = two.get(t);
|
||||
|
||||
Vertex v1 = g1.getVertexFor(f1), v2 = g2.getVertexFor(f2);
|
||||
|
||||
v1.is(v2);
|
||||
v2.is(v1);
|
||||
|
||||
System.out.println(fname(f1) + " is " + fname(f2));
|
||||
}
|
||||
}
|
||||
|
||||
private void mapDeobfuscatedMethods(ClassFile cf1, ClassFile cf2)
|
||||
{
|
||||
List<Method> m1 = cf1.getMethods().getMethods().stream().filter(m -> !Deob.isObfuscated(m.getName())).collect(Collectors.toList()),
|
||||
m2 = cf2.getMethods().getMethods().stream().filter(m -> !Deob.isObfuscated(m.getName())).collect(Collectors.toList());
|
||||
|
||||
for (Method m : m1)
|
||||
{
|
||||
Optional<Method> opt = m2.stream().filter(m2m -> m.getName().equals(m2m.getName()) && m.getDescriptor().equals(m2m.getDescriptor())).findAny();
|
||||
if (!opt.isPresent())
|
||||
continue;
|
||||
|
||||
Vertex v1 = g1.getVertexFor(m);
|
||||
Vertex v2 = g2.getVertexFor(opt.get());
|
||||
|
||||
v1.is(v2);
|
||||
v2.is(v1);
|
||||
|
||||
System.out.println(mname(m) + " is " + mname(opt.get()));
|
||||
|
||||
executeMethod(m, opt.get());
|
||||
}
|
||||
}
|
||||
|
||||
private List<Field> getClientFields(ClassGroup group, Execution e)
|
||||
{
|
||||
Method clinit = group.findClass("client").findMethod("<clinit>");
|
||||
Frame frame = e.processedFrames.stream().filter(f -> f.getMethod() == clinit).findFirst().get();
|
||||
|
||||
List<Field> fields = new ArrayList<>();
|
||||
for (InstructionContext i : frame.getInstructions())
|
||||
{
|
||||
if (i.getInstruction() instanceof SetFieldInstruction)
|
||||
{
|
||||
SetFieldInstruction sfi = (SetFieldInstruction) i.getInstruction();
|
||||
Field f = sfi.getMyField();
|
||||
|
||||
if (f != null)
|
||||
fields.add(f);
|
||||
}
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
// private void mapOneFrame(ClassGroup group, Execution e)
|
||||
// {
|
||||
// for (ClassFile cf : group.getClasses())
|
||||
// {
|
||||
// for (Method m : cf.getMethods().getMethods())
|
||||
// {
|
||||
// if (m.isStatic())
|
||||
// continue;
|
||||
//
|
||||
// List<Frame> frames = e.processedFrames.stream().filter(f -> f.getMethod() == m).collect(Collectors.toList());
|
||||
//
|
||||
// if (frames.size() != 1)
|
||||
// continue;
|
||||
//
|
||||
// int count = 0;
|
||||
// for (InstructionContext i : frames.get(0).getInstructions())
|
||||
// {
|
||||
// if (i.getInstruction() instanceof SetFieldInstruction)
|
||||
// {
|
||||
// SetFieldInstruction sfi = (SetFieldInstruction) i.getInstruction();
|
||||
//
|
||||
// Field f = sfi.getMyField();
|
||||
// if (f == null)
|
||||
// continue;
|
||||
//
|
||||
// Vertex methodVertex = e.getGraph().getVertexFor(m),
|
||||
// fieldVertex = e.getGraph().getVertexFor(f);
|
||||
//
|
||||
// Edge edge = new FieldEdge(i.getInstruction(), methodVertex, fieldVertex, EdgeType.SETFIELD, count);
|
||||
// e.getGraph().addEdge(edge);
|
||||
//
|
||||
// edge = new FieldEdge(i.getInstruction(), fieldVertex, methodVertex, EdgeType.SETFIELD_FROM, count);
|
||||
// e.getGraph().addEdge(edge);
|
||||
//
|
||||
// ++count;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private void solve()
|
||||
{
|
||||
List<Vertex> solved = g1.getVerticies().stream().filter(v -> v.getOther() != null).collect(Collectors.toList());
|
||||
|
||||
for (Vertex s : solved)
|
||||
{
|
||||
Vertex other = s.getOther();
|
||||
|
||||
assert s.getGraph() != other.getGraph();
|
||||
|
||||
for (Edge e : s.getEdges())
|
||||
{
|
||||
assert e.getFrom() == s;
|
||||
|
||||
boolean b = false;
|
||||
|
||||
if (e.getTo().getOther() != null)
|
||||
continue; // skip solved edges
|
||||
|
||||
Vertex v = e.getTo(); // end of edge in g1
|
||||
// if (v.toString().equals("Vertex{object=static J class114.field1961}"))
|
||||
// {
|
||||
// b = true;
|
||||
// }
|
||||
|
||||
List<Vertex> l = new ArrayList<>();
|
||||
for (Edge e2 : other.getEdges())
|
||||
{
|
||||
if (e2.getTo().getOther() != null)
|
||||
continue; // skip solved edges
|
||||
|
||||
if (e.toString().equals("Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1961}, type=SETFIELD}")
|
||||
&& e2.toString().equals("Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1962}, type=SETFIELD}"))
|
||||
b = true;
|
||||
|
||||
if (b && e.getType() == EdgeType.SETFIELD && e2.getType() == EdgeType.SETFIELD)
|
||||
{
|
||||
//Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1961}, type=SETFIELD}
|
||||
//Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1962}, type=SETFIELD}
|
||||
int i = 5;
|
||||
}
|
||||
|
||||
if (!e.getTo().couldBeEqual(e2.getTo()))
|
||||
{
|
||||
// System.out.println(e.getTo() + " != " + e2.getTo());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.couldBeEqual(e2))
|
||||
{
|
||||
e.couldBeEqual(e2);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
e.couldBeEqual(e2);
|
||||
|
||||
Vertex v2 = e2.getTo();
|
||||
|
||||
l.add(v2);
|
||||
}
|
||||
|
||||
if (b)
|
||||
v.merge(l);
|
||||
else
|
||||
v.merge(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int pass = 0, asserts = 0;
|
||||
private void executeNewMethods()
|
||||
{
|
||||
for (Vertex v : g1.getVerticies())
|
||||
{
|
||||
Vertex other = v.getOther();
|
||||
|
||||
if (other == null || !(v.getObject() instanceof Method))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
executeMethod((Method) v.getObject(), (Method) other.getObject());
|
||||
++pass;
|
||||
}
|
||||
catch (Exception | AssertionError ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
++asserts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int count = 0;
|
||||
private Set<Method> executed = new HashSet<>();
|
||||
private void executeMethod(Method m1, Method m2)
|
||||
{
|
||||
if (executed.contains(m1))
|
||||
return;
|
||||
executed.add(m1);
|
||||
// assert (m1.getCode() == null) == (m2.getCode() == null);
|
||||
//
|
||||
// if (m1.getCode() == null)
|
||||
// return;
|
||||
//
|
||||
if (!MappingExecutorUtil.isMappable(m1, m2))
|
||||
return;
|
||||
|
||||
if (m1.getName().equals("<clinit>") || m1.getName().equals("<init>"))
|
||||
return;
|
||||
|
||||
ParallelExecutorMapping mapping = MappingExecutorUtil.map(m1, m2);
|
||||
|
||||
System.out.println("EXEC " + count++ + " " + mname(m1) + " " + mname(m2) + " " + mapping);
|
||||
|
||||
for (Entry<Object, Object> e : mapping.getMap().entrySet())
|
||||
{
|
||||
if (e.getKey() instanceof Method)
|
||||
{
|
||||
try
|
||||
{
|
||||
executeMethod((Method) e.getKey(), (Method) e.getValue());
|
||||
++pass;
|
||||
}
|
||||
catch (Exception | AssertionError ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
++asserts;
|
||||
}
|
||||
|
||||
Method m = (Method) e.getKey();
|
||||
if (m.isStatic())
|
||||
{
|
||||
// we can map execute these, though.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Vertex v1 = g1.getVertexFor(e.getKey()),
|
||||
v2 = g2.getVertexFor(e.getValue());
|
||||
|
||||
v1.is(v2);
|
||||
v2.is(v1);
|
||||
}
|
||||
// XXX next is use mappings. and then use executeMethod() on more than just the initial method mappings
|
||||
}
|
||||
|
||||
public NameMappings run(ClassGroup one, ClassGroup two)
|
||||
{
|
||||
Execution eone = new Execution(one);
|
||||
//eone.setBuildGraph(true);
|
||||
eone.populateInitialMethods();
|
||||
eone.run();
|
||||
|
||||
Execution etwo = new Execution(two);
|
||||
//etwo.setBuildGraph(true);
|
||||
etwo.populateInitialMethods();
|
||||
etwo.run();
|
||||
|
||||
g1 = GraphBuilder.build(one);
|
||||
g2 = GraphBuilder.build(two);
|
||||
|
||||
// System.out.println(eone.getGraph());
|
||||
// System.out.println(etwo.getGraph());
|
||||
|
||||
for (int i = 0; i < 250; ++i)
|
||||
{
|
||||
ClassFile c1 = one.findClass("class" + i);
|
||||
ClassFile c2 = two.findClass("class" + i);
|
||||
|
||||
if (c1 == null || c2 == null)
|
||||
continue;
|
||||
|
||||
Map m1 = this.find(c1);
|
||||
Map m2 = this.find(c2);
|
||||
|
||||
mapClassMethods(m1, m2);
|
||||
|
||||
mapDeobfuscatedMethods(c1, c2);
|
||||
|
||||
m1 = findField(c1);
|
||||
m2 = findField(c2);
|
||||
|
||||
mapClassFields(m1, m2);
|
||||
}
|
||||
|
||||
ClassFile cf1 = one.findClass("client"), cf2 = two.findClass("client");
|
||||
mapDeobfuscatedMethods(cf1, cf2);
|
||||
|
||||
List<Field> fl1 = getClientFields(one, eone);
|
||||
List<Field> fl2 = getClientFields(two, etwo);
|
||||
|
||||
for (int i = 0; i < Math.min(fl1.size(), fl2.size()); ++i)
|
||||
{
|
||||
Field f1 = fl1.get(i), f2 = fl2.get(i);
|
||||
|
||||
Vertex v1 = g1.getVertexFor(f1);
|
||||
Vertex v2 = g2.getVertexFor(f2);
|
||||
|
||||
v1.is(v2);
|
||||
v2.is(v1);
|
||||
|
||||
System.out.println(fname(f1) + " is " + fname(f2));
|
||||
}
|
||||
|
||||
// mapOneFrame(one, eone);
|
||||
// mapOneFrame(two, etwo);
|
||||
|
||||
System.out.println("g1 verticies " + g1.getVerticies().size() + " reachable " + g1.reachableVerticiesFromSolvedVerticies().size());
|
||||
Set<Vertex> reachable = g1.reachableVerticiesFromSolvedVerticies();
|
||||
for (Vertex v : g1.getVerticies())
|
||||
if (!reachable.contains(v))
|
||||
{
|
||||
System.out.println("unreachable " + v);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int before = g1.solved(null);
|
||||
System.out.println("Before " + before);
|
||||
|
||||
solve();
|
||||
|
||||
g1.getVerticies().forEach(v -> v.finish());
|
||||
|
||||
executeNewMethods();
|
||||
|
||||
int after = g1.solved(null);
|
||||
System.out.println("After " + after);
|
||||
|
||||
if (before == after)
|
||||
break;
|
||||
}
|
||||
|
||||
g1.check();
|
||||
g2.check();
|
||||
|
||||
System.out.println("methods " +g1.solved(VertexType.METHOD));
|
||||
System.out.println("f " +g1.solved(VertexType.FIELD));
|
||||
|
||||
List<Edge> unsolved = new ArrayList<>();
|
||||
//Vertex stored = null;
|
||||
for (Vertex v : g1.getVerticies())
|
||||
{
|
||||
if (v.getOther() == null)
|
||||
continue;
|
||||
|
||||
//if (v.getObject() instanceof Method) continue;
|
||||
|
||||
//assert stored == null;
|
||||
//stored = v;
|
||||
|
||||
for (Edge e : v.getEdges())
|
||||
{
|
||||
if (e.getTo().getOther() == null)
|
||||
{
|
||||
unsolved.add(e);
|
||||
|
||||
if (e.getType() == EdgeType.SETFIELD)
|
||||
System.out.println("Edge " + e + " is unsolved");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (EdgeType t : EdgeType.values())
|
||||
{
|
||||
long count = unsolved.stream().filter(e -> e.getType() == t).count();
|
||||
if (count >0)
|
||||
System.out.println(t + " " + count);
|
||||
}
|
||||
|
||||
// NameMappings col = buildCollisionMap(one, two);
|
||||
// rename(col, two);
|
||||
//
|
||||
// NameMappings mappings = buildMappings(one, two); // two -> one
|
||||
//
|
||||
// show(mappings);
|
||||
|
||||
System.out.println("Solved methods "+ g1.solved(VertexType.METHOD) + ", solved fields " + g1.solved(VertexType.FIELD) + ", unsolved methods " +g1.unsolved(VertexType.METHOD) + ", unsolved fields " + g1.unsolved(VertexType.FIELD));
|
||||
System.out.println("asserts " + asserts + ", pass " + pass);
|
||||
|
||||
//rename(mappings, two);
|
||||
|
||||
// for (Vertex v : g1.getVerticies())
|
||||
// {
|
||||
//// if (v.getOther() != null)
|
||||
//// System.out.println(v.getObject() + " -> " + v.getOther().getOther());
|
||||
//// else
|
||||
// if (v.getObject() instanceof Field)
|
||||
// System.out.println(v.getObject() + " -> unk");
|
||||
// }
|
||||
|
||||
try
|
||||
{
|
||||
JarUtil.saveJar(two, new File("d:/rs/07/adamout.jar"));
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger(Rename2.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
//checkExports(one);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void show(NameMappings mappings)
|
||||
{
|
||||
for (Entry<Object, String> e : mappings.getMap().entrySet())
|
||||
{
|
||||
Object o = e.getKey();
|
||||
String n = e.getValue();
|
||||
|
||||
if (o instanceof net.runelite.deob.pool.Method)
|
||||
{
|
||||
net.runelite.deob.pool.Method m = (net.runelite.deob.pool.Method) o;
|
||||
System.out.println("FINAL " + n + " -> " + m.getNameAndType().getName());
|
||||
}
|
||||
else if (o instanceof net.runelite.deob.pool.Field)
|
||||
{
|
||||
net.runelite.deob.pool.Field f = (net.runelite.deob.pool.Field) o;
|
||||
System.out.println("FINAL " + n + " -> " + f.getNameAndType().getName());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Mappins size " + mappings.getMap().size());
|
||||
}
|
||||
|
||||
private NameMappings buildCollisionMap(ClassGroup one, ClassGroup two)
|
||||
{
|
||||
NameMappings mappings = new NameMappings();
|
||||
int count = 0;
|
||||
|
||||
for (ClassFile cf : two.getClasses())
|
||||
{
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
if (m.isStatic() && !m.getName().equals("<clinit>"))
|
||||
continue;
|
||||
|
||||
Vertex v = g2.getVertexFor(m);
|
||||
Vertex other = v.getOther();
|
||||
|
||||
if (m.getName().equals("<init>") || m.getName().equals("<clinit>"))
|
||||
continue;
|
||||
|
||||
if (other == null)
|
||||
continue;
|
||||
|
||||
Method m2 = (Method) other.getObject();
|
||||
|
||||
if (m.getName().equals(m2.getName()))
|
||||
continue; // already correct
|
||||
|
||||
Method existingMethod = cf.findMethod(m2.getName());
|
||||
if (existingMethod != null)
|
||||
{
|
||||
mappings.map(existingMethod.getPoolMethod(), "collidedMethod" + count++);
|
||||
}
|
||||
}
|
||||
|
||||
// for (Field f : cf.getFields().getFields())
|
||||
// {
|
||||
// Vertex v = g2.getVertexFor(f);
|
||||
// Vertex other = v.getOther();
|
||||
//
|
||||
// if (other == null)
|
||||
// continue;
|
||||
//
|
||||
// Field f2 = (Field) other.getObject();
|
||||
//
|
||||
// Field existingField = cf.findField(f2.getName());
|
||||
// if (existingField != null)
|
||||
// mappings.map(existingField.getPoolField(), "collidedField" + count++);
|
||||
// }
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private NameMappings buildMappings(ClassGroup one, ClassGroup two)
|
||||
{
|
||||
NameMappings mappings = new NameMappings();
|
||||
|
||||
for (ClassFile cf : two.getClasses())
|
||||
{
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
if (m.isStatic() && !m.getName().equals("<clinit>"))
|
||||
continue;
|
||||
|
||||
Vertex v = g2.getVertexFor(m);
|
||||
Vertex other = v.getOther();
|
||||
|
||||
if (m.getName().equals("<init>") || m.getName().equals("<clinit>"))
|
||||
continue;
|
||||
|
||||
if (other == null)
|
||||
continue;
|
||||
|
||||
Method m2 = (Method) other.getObject();
|
||||
|
||||
if (!m.getName().equals(m2.getName()))
|
||||
{
|
||||
Method existingMethod = cf.findMethod(m2.getName());
|
||||
assert existingMethod == null;
|
||||
}
|
||||
|
||||
mappings.map(m.getPoolMethod(), m2.getName());
|
||||
}
|
||||
|
||||
// for (Field f : cf.getFields().getFields())
|
||||
// {
|
||||
// Vertex v = g2.getVertexFor(f);
|
||||
// Vertex other = v.getOther();
|
||||
//
|
||||
// if (other == null)
|
||||
// continue;
|
||||
//
|
||||
// Field f2 = (Field) other.getObject();
|
||||
//
|
||||
// Field existingField = cf.findField(f2.getName());
|
||||
// assert existingField == null;
|
||||
//
|
||||
// mappings.map(f.getPoolField(), f2.getName());
|
||||
// }
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private void rename(NameMappings mappings, ClassGroup group)
|
||||
{
|
||||
Renamer renamer = new Renamer(mappings);
|
||||
renamer.run(group);
|
||||
}
|
||||
|
||||
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
|
||||
|
||||
private boolean isExported(Attributes attr)
|
||||
{
|
||||
Annotations an = (Annotations) attr.findType(AttributeType.RUNTIMEVISIBLEANNOTATIONS);
|
||||
if (an == null)
|
||||
return false;
|
||||
|
||||
for (Annotation a : an.getAnnotations())
|
||||
{
|
||||
if (a.getType().equals(EXPORT))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkExports(ClassGroup one)
|
||||
{
|
||||
for (ClassFile cf : one.getClasses())
|
||||
{
|
||||
for (Field f : cf.getFields().getFields())
|
||||
{
|
||||
if (!isExported(f.getAttributes()))
|
||||
continue;
|
||||
|
||||
Vertex v = g1.getVertexFor(f);
|
||||
assert v != null;
|
||||
|
||||
if (v.getOther() == null)
|
||||
{
|
||||
System.out.println("Unsolved exported field " + f);
|
||||
}
|
||||
}
|
||||
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
if (!isExported(m.getAttributes()))
|
||||
continue;
|
||||
|
||||
Vertex v = g1.getVertexFor(m);
|
||||
assert v != null;
|
||||
|
||||
if (v.getOther() == null)
|
||||
{
|
||||
System.out.println("Unsolved exported method " + m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,407 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.attributes.code.Instruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.DupInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.LVTInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
||||
import net.runelite.deob.attributes.code.instructions.NewArray;
|
||||
import net.runelite.deob.execution.InstructionContext;
|
||||
import net.runelite.deob.execution.StackContext;
|
||||
import net.runelite.deob.execution.VariableContext;
|
||||
import net.runelite.deob.execution.Variables;
|
||||
|
||||
public class Edge
|
||||
{
|
||||
private final InstructionContext ins;
|
||||
private final Vertex from, to;
|
||||
private final EdgeType type;
|
||||
private int weight;
|
||||
|
||||
public Edge(InstructionContext ins, Vertex from, Vertex to, EdgeType type)
|
||||
{
|
||||
this.ins = ins;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.type = type;
|
||||
|
||||
assert from.getGraph() == to.getGraph();
|
||||
}
|
||||
|
||||
public InstructionContext getIns()
|
||||
{
|
||||
return ins;
|
||||
}
|
||||
|
||||
public Vertex getFrom()
|
||||
{
|
||||
return from;
|
||||
}
|
||||
|
||||
public Vertex getTo()
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
public EdgeType getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void increase()
|
||||
{
|
||||
++weight;
|
||||
}
|
||||
|
||||
public int getWeight()
|
||||
{
|
||||
return weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Edge{" + "from=" + from + ", to=" + to + ", type=" + type + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 5;
|
||||
hash = 89 * hash + Objects.hashCode(this.from);
|
||||
hash = 89 * hash + Objects.hashCode(this.to);
|
||||
hash = 89 * hash + Objects.hashCode(this.type);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final Edge other = (Edge) obj;
|
||||
if (!Objects.equals(this.from, other.from))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.to, other.to))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.type != other.type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean couldBeEqual(Edge other)
|
||||
{
|
||||
if (this.type != other.type)
|
||||
return false;
|
||||
|
||||
if (this.type == EdgeType.SETFIELD)// || this.type == EdgeType.SETFIELD_FROM)
|
||||
{
|
||||
// if (!compareSetField(getGraph(), other.getGraph(),
|
||||
// (Field) this.getTo().getObject(), (Field) other.getTo().getObject(),
|
||||
// other.getIns()))
|
||||
// return false;
|
||||
}
|
||||
// if (this.weight != other.weight)
|
||||
// return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private InstructionContext resolve(
|
||||
InstructionContext ctx,
|
||||
StackContext from // pushed from ctx
|
||||
)
|
||||
{
|
||||
if (ctx.getInstruction() instanceof SetFieldInstruction)
|
||||
{
|
||||
StackContext s = ctx.getPops().get(0);
|
||||
return resolve(s.getPushed(), s);
|
||||
}
|
||||
|
||||
if (ctx.getInstruction() instanceof DupInstruction)
|
||||
{
|
||||
DupInstruction d = (DupInstruction) ctx.getInstruction();
|
||||
StackContext s = d.getOriginal(from);
|
||||
return resolve(s.getPushed(), s);
|
||||
}
|
||||
|
||||
if (ctx.getInstruction() instanceof LVTInstruction)
|
||||
{
|
||||
LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
|
||||
Variables variables = ctx.getVariables();
|
||||
|
||||
if (lvt.store())
|
||||
{
|
||||
StackContext s = ctx.getPops().get(0); // is this right?
|
||||
return resolve(s.getPushed(), s);
|
||||
}
|
||||
else
|
||||
{
|
||||
VariableContext vctx = variables.get(lvt.getVariableIndex()); // variable being loaded
|
||||
assert vctx != null;
|
||||
|
||||
InstructionContext storedCtx = vctx.getInstructionWhichStored();
|
||||
if (storedCtx == null)
|
||||
return ctx; // initial parameter
|
||||
|
||||
if (vctx.isIsParameter())
|
||||
return ctx; // parameter (storedCtx is invoking instruction in another frame). this lvt index is fixed.
|
||||
|
||||
return resolve(storedCtx, null);
|
||||
}
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
private List<InstructionContext> resolveUp(
|
||||
List<InstructionContext> ctxs,
|
||||
StackContext from // popped by ctxs
|
||||
)
|
||||
{
|
||||
List<InstructionContext> list = new ArrayList<>();
|
||||
|
||||
for (InstructionContext ctx : ctxs)
|
||||
{
|
||||
if (ctx.getInstruction() instanceof DupInstruction)
|
||||
{
|
||||
DupInstruction d = (DupInstruction) ctx.getInstruction();
|
||||
//StackContext s = d.
|
||||
//return resolve(s.getPushed(), s);
|
||||
}
|
||||
|
||||
list.add(ctx);
|
||||
}
|
||||
|
||||
return list;
|
||||
// if (ctx.getInstruction() instanceof SetFieldInstruction)
|
||||
// {
|
||||
// StackContext s = ctx.getPops().get(0);
|
||||
// return resolve(s.getPushed(), s);
|
||||
// }
|
||||
//
|
||||
|
||||
//
|
||||
// if (ctx.getInstruction() instanceof LVTInstruction)
|
||||
// {
|
||||
// LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
|
||||
// Variables variables = ctx.getVariables();
|
||||
//
|
||||
// if (lvt.store())
|
||||
// {
|
||||
// StackContext s = ctx.getPops().get(0); // is this right?
|
||||
// return resolve(s.getPushed(), s);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// VariableContext vctx = variables.get(lvt.getVariableIndex()); // variable being loaded
|
||||
// assert vctx != null;
|
||||
//
|
||||
// InstructionContext storedCtx = vctx.getInstructionWhichStored();
|
||||
// if (storedCtx == null)
|
||||
// return ctx; // parameter?
|
||||
//
|
||||
// return resolve(storedCtx, null);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return ctx;
|
||||
}
|
||||
|
||||
private boolean compareSetField(Graph g1, Graph g2, Field field1, Field field2, InstructionContext other)
|
||||
{
|
||||
InstructionContext thisp = resolve(ins.getPops().get(0).getPushed(), ins.getPops().get(0)),
|
||||
otherp = resolve(other.getPops().get(0).getPushed(), other.getPops().get(0));
|
||||
|
||||
return couldBeEqual(g1, g2, field1, field2, thisp, otherp, null);
|
||||
}
|
||||
|
||||
private boolean couldBeEqual(Graph g1, Graph g2, Field field1, Field field2, InstructionContext one, InstructionContext two, InstructionContext from)
|
||||
{
|
||||
Instruction i1 = one.getInstruction(), i2 = two.getInstruction();
|
||||
|
||||
if (i1 instanceof LVTInstruction && i2 instanceof LVTInstruction)
|
||||
{
|
||||
LVTInstruction l1 = (LVTInstruction) i1, l2 = (LVTInstruction) i2;
|
||||
|
||||
assert !l1.store();
|
||||
assert !l2.store();
|
||||
|
||||
VariableContext v1 = one.getVariables().get(l1.getVariableIndex()),
|
||||
v2 = two.getVariables().get(l2.getVariableIndex());
|
||||
|
||||
assert v1.isIsParameter();
|
||||
assert v2.isIsParameter();
|
||||
|
||||
// resolve() resolves these unless they are parameters, so compare indexes
|
||||
if (l1.getVariableIndex() != l2.getVariableIndex())
|
||||
return false;
|
||||
|
||||
return v1.getType().equals(v2.getType());
|
||||
}
|
||||
|
||||
if (i1 instanceof NewArray && i2 instanceof NewArray)
|
||||
{
|
||||
NewArray a1 = (NewArray) i1, a2 = (NewArray) i2;
|
||||
if (a1.getArrayType() != a2.getArrayType())
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXX check for invokestatic vs.
|
||||
if (i1 instanceof InvokeInstruction && i2 instanceof InvokeInstruction)
|
||||
{
|
||||
InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2;
|
||||
|
||||
List<Method> methods1 = ii1.getMethods(), methods2 = ii2.getMethods();
|
||||
|
||||
if (methods1.size() != methods2.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (methods1.isEmpty())
|
||||
{
|
||||
// compare pool Method
|
||||
return ii1.getMethod().equals(ii2.getMethod());
|
||||
}
|
||||
|
||||
Method m1 = methods1.get(0), m2 = methods2.get(0);
|
||||
|
||||
if (!m1.getDescriptor().equals(m2.getDescriptor()))
|
||||
return false;
|
||||
}
|
||||
else if (i1 instanceof InvokeStatic || i2 instanceof InvokeStatic)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i1 instanceof FieldInstruction && i2 instanceof FieldInstruction)
|
||||
{
|
||||
assert i1 instanceof GetFieldInstruction;
|
||||
assert i2 instanceof GetFieldInstruction;
|
||||
|
||||
GetFieldInstruction gf1 = (GetFieldInstruction) i1, gf2 = (GetFieldInstruction) i2;
|
||||
Field f1 = gf1.getMyField(), f2 = gf2.getMyField();
|
||||
|
||||
if ((f1 != null) != (f2 != null))
|
||||
return false;
|
||||
|
||||
//if (f1 == null || f2 == null)
|
||||
// return
|
||||
|
||||
if (!f1.getType().equals(f2.getType()))
|
||||
return false;
|
||||
|
||||
// lookup already solved fields.
|
||||
|
||||
Vertex v1 = g1.getVertexFor(f1), v2 = g2.getVertexFor(f2); // vertex of fields whose value is being set to
|
||||
|
||||
// get solved field
|
||||
v1 = v1.getOther();
|
||||
v2 = v2.getOther();
|
||||
|
||||
if ((v1 != null) != (v2 != null))
|
||||
return false;
|
||||
|
||||
if (v1 != null || v2 != null)
|
||||
{
|
||||
if (v1.getObject() != f2 || v2.getObject() != f1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (i1 instanceof PushConstantInstruction && i2 instanceof PushConstantInstruction)
|
||||
{
|
||||
PushConstantInstruction pc1 = (PushConstantInstruction) i1, pc2 = (PushConstantInstruction) i2;
|
||||
|
||||
return pc1.getConstant().equals(pc2.getConstant());
|
||||
}
|
||||
|
||||
if (!i1.getClass().equals(i2.getClass()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check down
|
||||
assert one.getPops().size() == two.getPops().size();
|
||||
for (int i = 0; i < one.getPops().size(); ++i)
|
||||
{
|
||||
StackContext s1 = one.getPops().get(i), s2 = two.getPops().get(i);
|
||||
|
||||
if (resolve(s1.getPushed(), s1) == from)
|
||||
continue;
|
||||
|
||||
if (!couldBeEqual(
|
||||
g1, g2,
|
||||
field1, field2,
|
||||
resolve(s1.getPushed(), s1),
|
||||
resolve(s2.getPushed(), s2),
|
||||
one
|
||||
))
|
||||
return false;
|
||||
}
|
||||
|
||||
// check up
|
||||
// assert one.getPushes().size() == two.getPushes().size();
|
||||
// for (int i = 0; i < one.getPushes().size(); ++i)
|
||||
// {
|
||||
// StackContext s1 = one.getPushes().get(i), s2 = two.getPushes().get(i);
|
||||
// List<InstructionContext> p1 = s1.getPopped(), p2 = s2.getPopped(); // instructions which popped the push
|
||||
//
|
||||
// assert p1.size() == p2.size();
|
||||
//
|
||||
// //resolveUp(p1, s1);
|
||||
//
|
||||
// for (int j = 0; j < p1.size(); ++i)
|
||||
// {
|
||||
// InstructionContext ic1 = p1.get(j), ic2 = p2.get(j);
|
||||
//
|
||||
// if (from == ic1)
|
||||
// continue;
|
||||
//
|
||||
//// resolveUp(ic1, s1);
|
||||
//// resolveUp(ic2, s2);
|
||||
//
|
||||
// if (!couldBeEqual(
|
||||
// field1, field2,
|
||||
// ic1, ic2,
|
||||
// one
|
||||
// )) {}
|
||||
// //return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Graph getGraph()
|
||||
{
|
||||
assert from.getGraph() == to.getGraph();
|
||||
return from.getGraph();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
public enum EdgeType
|
||||
{
|
||||
INVOKE,
|
||||
GETFIELD,
|
||||
SETFIELD,
|
||||
|
||||
INVOKED_FROM,
|
||||
GETFIELD_FROM,
|
||||
SETFIELD_FROM,
|
||||
|
||||
FIELD_ASSOCIATION,
|
||||
FIELD_ASSOCIATION_FROM,
|
||||
|
||||
METHOD_ASSOCIATION,
|
||||
METHOD_ASSOCIATION_FROM,
|
||||
|
||||
PREV_FIELD,
|
||||
PREV_FIELD_FROM,
|
||||
|
||||
FIELD_ASSIGNMENT_FIELD,
|
||||
FIELD_ASSIGNMENT_FIELD_FROM;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
import net.runelite.deob.attributes.code.Instruction;
|
||||
import net.runelite.deob.execution.InstructionContext;
|
||||
|
||||
public class FieldEdge extends Edge
|
||||
{
|
||||
private int id;
|
||||
|
||||
public FieldEdge(InstructionContext ins, Vertex from, Vertex to, EdgeType type, int id)
|
||||
{
|
||||
super(ins, from, to, type);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (!super.equals(obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final FieldEdge other = (FieldEdge) obj;
|
||||
if (this.id != other.id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 5;
|
||||
hash = 89 * hash + this.id;
|
||||
return hash ^ super.hashCode();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Graph
|
||||
{
|
||||
private List<Vertex> verticies = new ArrayList<>();
|
||||
|
||||
private Map<Object, Vertex> o2v = new HashMap<>();
|
||||
|
||||
// public Vertex getVertexFor(Object o)
|
||||
// {
|
||||
// Vertex v = o2v.get(o);
|
||||
// if (v != null)
|
||||
// return v;
|
||||
//
|
||||
// v = new Vertex(this, o);
|
||||
// o2v.put(o, v);
|
||||
// verticies.add(v);
|
||||
// return v;
|
||||
// }
|
||||
|
||||
public Vertex getVertexFor(Object o)
|
||||
{
|
||||
Vertex v = o2v.get(o);
|
||||
assert v != null;
|
||||
return v;
|
||||
}
|
||||
|
||||
public Vertex addVertex(Object o, VertexType type)
|
||||
{
|
||||
assert o2v.get(o) == null;
|
||||
|
||||
Vertex v = new Vertex(this, o);
|
||||
//v.setType(type);
|
||||
assert type == v.getType();
|
||||
|
||||
verticies.add(v);
|
||||
o2v.put(o, v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public void removeVertex(Object o)
|
||||
{
|
||||
Vertex v = this.getVertexFor(o);
|
||||
|
||||
assert v.getEdges().isEmpty();
|
||||
assert v.getEdgesFrom().isEmpty();
|
||||
|
||||
verticies.remove(v);
|
||||
o2v.remove(o);
|
||||
}
|
||||
|
||||
public void addEdge(Edge e)
|
||||
{
|
||||
e.getFrom().addEdge(e);
|
||||
}
|
||||
|
||||
public List<Vertex> getVerticies()
|
||||
{
|
||||
return verticies;
|
||||
}
|
||||
|
||||
public int vertexCount()
|
||||
{
|
||||
return verticies.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Graph{" + "verticies=" + verticies.size() + "}";
|
||||
}
|
||||
|
||||
public void check()
|
||||
{
|
||||
for (Vertex v : verticies)
|
||||
{
|
||||
if (v.getOther() != null)
|
||||
{
|
||||
assert v.getOther().getOther() == v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int solved(VertexType type)
|
||||
{
|
||||
int solved = 0;
|
||||
for (Vertex v : verticies)
|
||||
if (v.getOther() != null && (type == null || v.getType() == type))
|
||||
++solved;
|
||||
return solved;
|
||||
}
|
||||
|
||||
public int unsolved(VertexType type)
|
||||
{
|
||||
int solved = 0;
|
||||
for (Vertex v : verticies)
|
||||
if (v.getOther() == null && type == v.getType())
|
||||
++solved;
|
||||
return solved;
|
||||
}
|
||||
|
||||
private void recurse(Vertex v, Set<Vertex> verticies)
|
||||
{
|
||||
if (verticies.contains(v))
|
||||
return;
|
||||
|
||||
verticies.add(v);
|
||||
|
||||
for (Edge e : v.getEdges())
|
||||
recurse(e.getTo(), verticies);
|
||||
}
|
||||
|
||||
public Set<Vertex> reachableVerticiesFromSolvedVerticies()
|
||||
{
|
||||
Set<Vertex> verticies = new HashSet<>();
|
||||
for (Vertex v : this.verticies)
|
||||
if (v.getOther() != null)
|
||||
recurse(v, verticies);
|
||||
return verticies;
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import net.runelite.deob.ClassFile;
|
||||
import net.runelite.deob.ClassGroup;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.attributes.Code;
|
||||
import net.runelite.deob.attributes.code.Instruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
|
||||
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
||||
|
||||
public class GraphBuilder
|
||||
{
|
||||
public static Graph build(ClassGroup group)
|
||||
{
|
||||
// statically build
|
||||
Graph g = new Graph();
|
||||
|
||||
// add verticies
|
||||
for (ClassFile cf : group.getClasses())
|
||||
{
|
||||
//g.addVertex(cf, VertexType.CLASS);
|
||||
|
||||
for (Field f : cf.getFields().getFields())
|
||||
{
|
||||
g.addVertex(f, VertexType.FIELD);
|
||||
}
|
||||
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
g.addVertex(m, VertexType.METHOD);
|
||||
}
|
||||
}
|
||||
|
||||
for (ClassFile cf : group.getClasses())
|
||||
{
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
processMethod(g, m);
|
||||
}
|
||||
}
|
||||
|
||||
// remove static methods
|
||||
for (ClassFile cf : group.getClasses())
|
||||
{
|
||||
for (Method m : cf.getMethods().getMethods())
|
||||
{
|
||||
if (m.isStatic() && !m.getName().equals("<clinit>"))
|
||||
{
|
||||
removeMethod(g, m);
|
||||
|
||||
Vertex v = g.getVertexFor(m);
|
||||
|
||||
assert v.getEdges().isEmpty();
|
||||
assert v.getEdgesFrom().isEmpty();
|
||||
|
||||
g.removeVertex(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
private static void processMethod(Graph graph, Method method)
|
||||
{
|
||||
Code code = method.getCode();
|
||||
if (code == null)
|
||||
return;
|
||||
|
||||
for (Instruction i : code.getInstructions().getInstructions())
|
||||
{
|
||||
if (i instanceof InvokeInstruction)
|
||||
{
|
||||
if (i instanceof InvokeStatic)
|
||||
return;
|
||||
|
||||
InvokeInstruction ii = (InvokeInstruction) i;
|
||||
|
||||
List<Method> methods = ii.getMethods();
|
||||
if (methods.isEmpty())
|
||||
return;
|
||||
|
||||
Vertex methodVertex = graph.getVertexFor(method);
|
||||
|
||||
for (Method m : methods)
|
||||
{
|
||||
Vertex otherMethodVertex = graph.getVertexFor(m);
|
||||
|
||||
graph.addEdge(new Edge(null, methodVertex, otherMethodVertex, EdgeType.INVOKE));
|
||||
graph.addEdge(new Edge(null, otherMethodVertex, methodVertex, EdgeType.INVOKED_FROM));
|
||||
}
|
||||
}
|
||||
else if (i instanceof FieldInstruction)
|
||||
{
|
||||
FieldInstruction fi = (FieldInstruction) i;
|
||||
|
||||
if (fi.getMyField() == null)
|
||||
return;
|
||||
|
||||
Vertex methodVertex = graph.getVertexFor(method),
|
||||
fieldVertex = graph.getVertexFor(fi.getMyField());
|
||||
|
||||
EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD;
|
||||
graph.addEdge(new Edge(null, methodVertex, fieldVertex, type));
|
||||
EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM;
|
||||
graph.addEdge(new Edge(null, fieldVertex, methodVertex, typeRev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeMethod(Graph g, Method m)
|
||||
{
|
||||
Vertex v = g.getVertexFor(m);
|
||||
|
||||
// for every object that points to m, make it point to
|
||||
// everything that m points to, with edge type of the edge from m.
|
||||
|
||||
for (Edge e : new HashSet<>(v.getEdgesFrom()))
|
||||
{
|
||||
// edge is TO v
|
||||
assert e.getTo() == v;
|
||||
|
||||
Vertex from = e.getFrom();
|
||||
|
||||
// add an edge from -> everything v is to
|
||||
|
||||
for (Edge e2 : new HashSet<>(v.getEdges()))
|
||||
{
|
||||
assert e2.getFrom() == v;
|
||||
|
||||
Vertex to = e2.getTo();
|
||||
EdgeType type = e2.getType();
|
||||
|
||||
// add edge
|
||||
from.addEdge(new Edge(null, from, to, type));
|
||||
}
|
||||
|
||||
|
||||
// remove
|
||||
from.removeEdge(e);
|
||||
}
|
||||
|
||||
// for every object m points to, everything that points to m should point to it.
|
||||
for (Edge e : new HashSet<>(v.getEdges()))
|
||||
{
|
||||
assert e.getFrom() == v;
|
||||
|
||||
Vertex to = e.getTo();
|
||||
EdgeType type = e.getType();
|
||||
|
||||
for (Edge e2 : new HashSet<>(v.getEdgesFrom()))
|
||||
{
|
||||
assert e2.getTo() == v;
|
||||
|
||||
// add edge from -> to
|
||||
Vertex from = e2.getFrom();
|
||||
|
||||
from.addEdge(new Edge(null, from, to, type));
|
||||
}
|
||||
|
||||
v.removeEdge(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
import java.util.Objects;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.execution.InstructionContext;
|
||||
|
||||
public class MethodEdge extends Edge
|
||||
{
|
||||
private final Method method;
|
||||
|
||||
public MethodEdge(InstructionContext i, Vertex from, Vertex to, EdgeType type, Method method)
|
||||
{
|
||||
super(i, from, to, type);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 7;
|
||||
hash = 61 * hash + Objects.hashCode(this.method);
|
||||
return hash ^ super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (!super.equals(obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final MethodEdge other = (MethodEdge) obj;
|
||||
if (!Objects.equals(this.method, other.method))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,465 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.runelite.deob.ClassFile;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.attributes.AttributeType;
|
||||
import net.runelite.deob.attributes.Code;
|
||||
import net.runelite.deob.attributes.ConstantValue;
|
||||
import net.runelite.deob.attributes.code.Instruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
||||
import net.runelite.deob.deobfuscators.rename.InstructionList;
|
||||
import net.runelite.deob.deobfuscators.rename.Rename2;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
public class Vertex
|
||||
{
|
||||
private static final int FIELD_MASK = Field.ACC_FINAL | Field.ACC_STATIC;
|
||||
private static final int METHOD_MASK = Method.ACC_ABSTRACT | Method.ACC_FINAL | Method.ACC_STATIC | Method.ACC_SYNCHRONIZED;
|
||||
|
||||
private Graph graph;
|
||||
private final Object object;
|
||||
private VertexType type;
|
||||
|
||||
private final Set<Edge> edges = new HashSet<>(),
|
||||
from = new HashSet<>();
|
||||
|
||||
private Collection<Vertex> mightBe;
|
||||
private Vertex is;
|
||||
|
||||
//private Set<Instruction> edgeFrom = new HashSet<>();
|
||||
|
||||
public Vertex(Graph graph, Object object)
|
||||
{
|
||||
this.graph = graph;
|
||||
this.object = object;
|
||||
if (object instanceof Method)
|
||||
type = VertexType.METHOD;
|
||||
else if (object instanceof Field)
|
||||
type = VertexType.FIELD;
|
||||
else if (object instanceof ClassFile)
|
||||
type = VertexType.CLASS;
|
||||
else
|
||||
assert false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Vertex{" + "object=" + object + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 7;
|
||||
hash = 79 * hash + java.util.Objects.hashCode(this.object);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final Vertex other = (Vertex) obj;
|
||||
if (!java.util.Objects.equals(this.object, other.object))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Graph getGraph()
|
||||
{
|
||||
return graph;
|
||||
}
|
||||
|
||||
public Object getObject()
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
public VertexType getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(VertexType type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void addEdge(Edge edge)
|
||||
{
|
||||
assert edge.getFrom() == this;
|
||||
//assert edge.getTo() != this;
|
||||
|
||||
if (edges.contains(edge))
|
||||
//if (c != null)
|
||||
{
|
||||
// if (edge.getIns() instanceof SetFieldInstruction && !edgeFrom.contains(edge.getIns()))
|
||||
// {
|
||||
// edgeFrom.add(edge.getIns());
|
||||
// c.increase();
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex to = edge.getTo();
|
||||
assert to.from.contains(edge) == false;
|
||||
|
||||
edges.add(edge);
|
||||
to.from.add(edge);
|
||||
|
||||
//edges.put(edge, edge);
|
||||
}
|
||||
|
||||
public void removeEdge(Edge edge)
|
||||
{
|
||||
assert edge.getFrom() == this;
|
||||
|
||||
assert edges.contains(edge);
|
||||
|
||||
Vertex to = edge.getTo();
|
||||
assert to.from.contains(edge);
|
||||
|
||||
edges.remove(edge);
|
||||
to.from.remove(edge);
|
||||
}
|
||||
|
||||
public Set<Edge> getEdges()
|
||||
{
|
||||
return edges;
|
||||
}
|
||||
|
||||
public Set<Edge> getEdgesFrom()
|
||||
{
|
||||
return from;
|
||||
}
|
||||
|
||||
public void merge(Collection<Vertex> maybe)
|
||||
{
|
||||
boolean b = false;
|
||||
if (this.object instanceof Method)
|
||||
{
|
||||
Method m = (Method) object;
|
||||
|
||||
if (m.getName().equals("method2566"))
|
||||
{
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mightBe == null)
|
||||
mightBe = maybe;
|
||||
else
|
||||
{
|
||||
int old = mightBe.size();
|
||||
mightBe = CollectionUtils.intersection(mightBe, maybe);
|
||||
if (b && old == 1 && mightBe.isEmpty())
|
||||
{
|
||||
int i = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finish()
|
||||
{
|
||||
if (this.toString().equals("Vertex{object=class207.<init>()V}"))
|
||||
{
|
||||
int i =5;
|
||||
}
|
||||
|
||||
if (mightBe == null)
|
||||
return;
|
||||
|
||||
if (mightBe != null && mightBe.size() > 1)
|
||||
{
|
||||
// System.out.println("Can't decide for " + this);
|
||||
|
||||
// for(Vertex v : mightBe)
|
||||
// System.out.println(v);
|
||||
// int i = 5;
|
||||
}
|
||||
if (mightBe.isEmpty())
|
||||
{
|
||||
System.out.println("empty " + this);
|
||||
int i = 5;
|
||||
}
|
||||
if (mightBe != null && mightBe.size() == 1)
|
||||
{
|
||||
Vertex v = mightBe.stream().findAny().get();
|
||||
|
||||
//if (v.getOther() == null || v.getOther() == this)
|
||||
{
|
||||
is(v);
|
||||
is.is(this);
|
||||
mightBe = null;
|
||||
System.out.println(this + " is " + is);
|
||||
}
|
||||
|
||||
if (object instanceof Method)
|
||||
{
|
||||
//Method m = (Method) object;
|
||||
//if (m.getName().equals
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void is(Vertex other)
|
||||
{
|
||||
if (is != null)
|
||||
{
|
||||
assert is.is == this;
|
||||
is.is = null;
|
||||
is = null;
|
||||
|
||||
//Rename2.collide(object, is.object, other.object);
|
||||
}
|
||||
assert is == null;
|
||||
assert other.graph != graph;
|
||||
|
||||
if (object instanceof Method)
|
||||
{
|
||||
Method thism = (Method) object;
|
||||
Method otherm = (Method) other.object;
|
||||
|
||||
assert thism.getMethods().getClassFile().getName().equals(otherm.getMethods().getClassFile().getName());
|
||||
}
|
||||
|
||||
this.is = other;
|
||||
}
|
||||
|
||||
public Vertex getOther()
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
private boolean couldBeEqual(ClassFile cf1, ClassFile cf2)
|
||||
{
|
||||
if (!cf1.getClassName().equals(cf2.getClassName()))
|
||||
return false;
|
||||
|
||||
if (!cf1.getInterfaces().getInterfaces().equals(cf2.getInterfaces().getInterfaces()))
|
||||
return false;
|
||||
|
||||
if (!cf1.getParentClass().equals(cf2.getParentClass()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<Instruction> getInstructionsInMethodInclStatic(Method method, Set<Method> visited)
|
||||
{
|
||||
List<Instruction> ilist = new ArrayList<>();
|
||||
|
||||
if (visited.contains(method))
|
||||
return ilist;
|
||||
visited.add(method);
|
||||
|
||||
Code code = method.getCode();
|
||||
if (code == null)
|
||||
return ilist;
|
||||
|
||||
for (Instruction i : code.getInstructions().getInstructions())
|
||||
{
|
||||
if (i instanceof InvokeStatic)
|
||||
{
|
||||
InvokeInstruction ii = (InvokeInstruction) i;
|
||||
List<Method> methods = ii.getMethods();
|
||||
|
||||
if (methods.isEmpty())
|
||||
continue;
|
||||
|
||||
Method m = methods.get(0);
|
||||
ilist.addAll(this.getInstructionsInMethodInclStatic(m, visited));
|
||||
}
|
||||
else
|
||||
{
|
||||
ilist.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return ilist;
|
||||
}
|
||||
|
||||
private boolean couldBeEqual(Method m1, Method m2)
|
||||
{
|
||||
InstructionList il1 = new InstructionList(this.getInstructionsInMethodInclStatic(m1, new HashSet())),
|
||||
il2 = new InstructionList(this.getInstructionsInMethodInclStatic(m2, new HashSet()));
|
||||
return il1.couldBeEqual(il2);
|
||||
}
|
||||
|
||||
private static boolean recurse = true;
|
||||
public boolean couldBeEqual(Vertex other)
|
||||
{
|
||||
assert this != other;
|
||||
assert graph != other.graph;
|
||||
// assert is == null;
|
||||
//assert other.is == null;
|
||||
|
||||
if (this.getOther() != null || other.getOther() != null)
|
||||
{
|
||||
return this.getOther() == other && other.getOther() == this;
|
||||
}
|
||||
|
||||
if (this.getType() != other.getType())
|
||||
return false;
|
||||
|
||||
// if (this.getEdges().size() != other.getEdges().size())
|
||||
// return false;
|
||||
//
|
||||
// for (EdgeType e : EdgeType.values())
|
||||
// {
|
||||
// // for each edge of this type, it must be equal with just one of the others
|
||||
//
|
||||
// if (this.edgesOf(e) != other.edgesOf(e))// ||
|
||||
// //this.solvedEdgesOfType(e) != other.solvedEdgesOfType(e))
|
||||
// {
|
||||
// int thise = edgesOf(e), othere = other.edgesOf(e);
|
||||
// int thisse = this.solvedEdgesOfType(e), otherse = other.solvedEdgesOfType(e);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// must be 1->1
|
||||
// map v -> possibles
|
||||
// start with the ones with the least possibilities
|
||||
|
||||
// if (recurse)
|
||||
// {
|
||||
// Set<Edge> others = new HashSet<>(other.getEdges());
|
||||
// for (Edge e : edges.values())
|
||||
// {
|
||||
// Vertex v = e.getTo();
|
||||
//
|
||||
// boolean found = false;
|
||||
// List<Vertex> lv = new ArrayList();
|
||||
// for (Edge e2 : others)
|
||||
// {
|
||||
// Vertex v2 = e2.getTo();
|
||||
// lv.add(v2);
|
||||
//
|
||||
// recurse = false;
|
||||
// if (v.couldBeEqual(v2))
|
||||
// // if (e.couldBeEqual(e2))
|
||||
// {
|
||||
// recurse = true;
|
||||
// // others.remove(e2);
|
||||
// found = true;
|
||||
// break;
|
||||
// }
|
||||
// recurse = true;
|
||||
// }
|
||||
//
|
||||
// if (!found)
|
||||
// {
|
||||
// Vertex v2 = null;
|
||||
// for (Vertex vt : lv)
|
||||
// if (vt.getObject() instanceof Method)
|
||||
// {
|
||||
// Method m = (Method) vt.getObject();
|
||||
// if (m.getName().equals("vmethod2975"))
|
||||
// {
|
||||
// v2 = vt;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// //v.couldBeEqual(v2);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (this.getType() == VertexType.METHOD)
|
||||
{
|
||||
Method m1 = (Method) object;
|
||||
Method m2 = (Method) other.object;
|
||||
|
||||
assert !m1.isStatic();
|
||||
assert !m2.isStatic();
|
||||
|
||||
if (m1.getName().equals("<init>") != m2.getName().equals("<init>"))
|
||||
return false;
|
||||
|
||||
if (!m1.getDescriptor().equals(m2.getDescriptor()))
|
||||
return false;
|
||||
|
||||
if ((m1.getAccessFlags() & METHOD_MASK) != (m2.getAccessFlags() & METHOD_MASK))
|
||||
return false;
|
||||
|
||||
if ((m1.getCode() == null) != (m2.getCode() == null))
|
||||
return false;
|
||||
|
||||
ClassFile cf1 = m1.getMethods().getClassFile(), cf2 = m2.getMethods().getClassFile();
|
||||
|
||||
if (!couldBeEqual(cf1, cf2))
|
||||
return false;
|
||||
|
||||
if (!couldBeEqual(m1, m2))
|
||||
return false;
|
||||
}
|
||||
else if (type == VertexType.FIELD)
|
||||
{
|
||||
Field f1 = (Field) object;
|
||||
Field f2 = (Field) other.object;
|
||||
|
||||
if (!f1.getType().equals(f2.getType()))
|
||||
return false;
|
||||
|
||||
if ((f1.getAccessFlags() & FIELD_MASK) != (f2.getAccessFlags() & FIELD_MASK))
|
||||
return false;
|
||||
|
||||
if (!f1.isStatic())
|
||||
{
|
||||
ClassFile cf1 = f1.getFields().getClassFile(), cf2 = f2.getFields().getClassFile();
|
||||
|
||||
if (!couldBeEqual(cf1, cf2))
|
||||
return false;
|
||||
}
|
||||
|
||||
// compare other edges,
|
||||
|
||||
ConstantValue cf1 = (ConstantValue) f1.getAttributes().findType(AttributeType.CONSTANT_VALUE);
|
||||
ConstantValue cf2 = (ConstantValue) f2.getAttributes().findType(AttributeType.CONSTANT_VALUE);
|
||||
|
||||
//if (!Objects.equal(cf1, cf2))
|
||||
// return false;
|
||||
}
|
||||
else
|
||||
assert false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int edgesOf(EdgeType type)
|
||||
{
|
||||
int t = 0;
|
||||
for (Edge e : this.edges)
|
||||
if (e.getType() == type)
|
||||
++t;
|
||||
return t;
|
||||
}
|
||||
|
||||
private int solvedEdgesOfType(EdgeType type)
|
||||
{
|
||||
return (int) edges.stream().filter(e -> e.getType() == type).filter(e -> e.getTo().getOther() != null).count();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
|
||||
public enum VertexType
|
||||
{
|
||||
METHOD,
|
||||
FIELD,
|
||||
CLASS;
|
||||
}
|
||||
@@ -8,24 +8,10 @@ import net.runelite.deob.attributes.code.Instruction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
|
||||
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.Edge;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.EdgeType;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.FieldEdge;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.Graph;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.MethodEdge;
|
||||
import net.runelite.deob.deobfuscators.rename.graph.VertexType;
|
||||
import org.apache.commons.collections4.map.MultiValueMap;
|
||||
|
||||
public class Execution
|
||||
|
||||
@@ -15,7 +15,7 @@ public class StoreLoadTest
|
||||
System.out.println(store);
|
||||
}
|
||||
|
||||
@Test
|
||||
//@Test
|
||||
public void unpackStore() throws IOException
|
||||
{
|
||||
java.io.File base = StoreLocation.LOCATION;
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.junit.Test;
|
||||
|
||||
public class ItemLoaderTest
|
||||
{
|
||||
@Test
|
||||
//@Test
|
||||
public void extract() throws IOException
|
||||
{
|
||||
ItemLoader loader = new ItemLoader();
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.junit.Test;
|
||||
|
||||
public class NpcLoaderTest
|
||||
{
|
||||
@Test
|
||||
//@Test
|
||||
public void extract() throws IOException
|
||||
{
|
||||
NpcLoader loader = new NpcLoader();
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.junit.Test;
|
||||
|
||||
public class SpriteLoaderTest
|
||||
{
|
||||
@Test
|
||||
//@Test
|
||||
public void extract() throws IOException
|
||||
{
|
||||
java.io.File base = StoreLocation.LOCATION;
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.runelite.deob.attributes.Annotations;
|
||||
import net.runelite.deob.attributes.AttributeType;
|
||||
import net.runelite.deob.attributes.annotation.Annotation;
|
||||
import net.runelite.deob.attributes.annotation.Element;
|
||||
import net.runelite.deob.pool.UTF8;
|
||||
import net.runelite.deob.signature.Type;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -55,6 +56,6 @@ public class AnnotationTest
|
||||
Element element = elements.get(0);
|
||||
|
||||
Assert.assertEquals("value", element.getType().toString());
|
||||
Assert.assertEquals("method1", element.getValue());
|
||||
Assert.assertEquals("method1", ((UTF8) element.getValue()).getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename.graph;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import net.runelite.deob.ClassGroup;
|
||||
import net.runelite.deob.util.JarUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class GraphBuilderTest
|
||||
{
|
||||
@Test
|
||||
public void test() throws IOException
|
||||
{
|
||||
ClassGroup group = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));
|
||||
GraphBuilder.build(group);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user