Begin moving code to do mapping to core. Write out annotation mapper.
This commit is contained in:
@@ -146,4 +146,9 @@ public class Attributes
|
||||
element.setValue(value);
|
||||
annotation.addElement(element);
|
||||
}
|
||||
|
||||
public Annotations getAnnotations()
|
||||
{
|
||||
return (Annotations) findType(AttributeType.RUNTIMEVISIBLEANNOTATIONS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package net.runelite.deob.deobfuscators.rename;
|
||||
|
||||
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.Attributes;
|
||||
import net.runelite.deob.attributes.annotation.Annotation;
|
||||
import net.runelite.deob.attributes.annotation.Element;
|
||||
import net.runelite.deob.signature.Type;
|
||||
|
||||
public class AnnotationMapper
|
||||
{
|
||||
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
|
||||
private static final Type IMPLEMENTS = new Type("Lnet/runelite/mapping/Implements;");
|
||||
|
||||
private final ClassGroup source, target;
|
||||
private final ParallelExecutorMapping mapping;
|
||||
|
||||
public AnnotationMapper(ClassGroup source, ClassGroup target, ParallelExecutorMapping mapping)
|
||||
{
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (ClassFile c : source.getClasses())
|
||||
{
|
||||
ClassFile other = target.findClass(c.getName());
|
||||
|
||||
if (other == null)
|
||||
continue;
|
||||
|
||||
count += run(c, other);
|
||||
}
|
||||
|
||||
System.out.println("Copied " + count + " annotations");
|
||||
}
|
||||
|
||||
private int run(ClassFile from, ClassFile to)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
count += copyAnnotations(from.getAttributes(), to.getAttributes());
|
||||
|
||||
for (Field f : from.getFields().getFields())
|
||||
{
|
||||
if (!hasCopyableAnnotation(f.getAttributes()))
|
||||
continue;
|
||||
|
||||
Field other = (Field) mapping.get(f);
|
||||
if (other == null)
|
||||
{
|
||||
assert false;
|
||||
}
|
||||
|
||||
count += copyAnnotations(f.getAttributes(), other.getAttributes());
|
||||
}
|
||||
|
||||
for (Method m : to.getMethods().getMethods())
|
||||
{
|
||||
if (!hasCopyableAnnotation(m.getAttributes()))
|
||||
continue;
|
||||
|
||||
Method other = (Method) mapping.get(m);
|
||||
if (other == null)
|
||||
{
|
||||
assert false;
|
||||
}
|
||||
|
||||
count += copyAnnotations(m.getAttributes(), other.getAttributes());
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private int copyAnnotations(Attributes from, Attributes to)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (from.getAnnotations() == null)
|
||||
return count;
|
||||
|
||||
for (Annotation a : from.getAnnotations().getAnnotations())
|
||||
{
|
||||
if (isCopyable(a))
|
||||
{
|
||||
assert a.getElements().size() == 1;
|
||||
Element e = a.getElements().get(0);
|
||||
|
||||
to.addAnnotation(a.getType(), e.getType().toString(), e.getValue().copy());
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private boolean hasCopyableAnnotation(Attributes a)
|
||||
{
|
||||
if (a.getAnnotations() == null)
|
||||
return false;
|
||||
|
||||
for (Annotation an : a.getAnnotations().getAnnotations())
|
||||
if (isCopyable(an))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isCopyable(Annotation a)
|
||||
{
|
||||
return a.getType().equals(EXPORT) || a.getType().equals(IMPLEMENTS);
|
||||
}
|
||||
}
|
||||
199
src/main/java/net/runelite/deob/deobfuscators/rename/Mapper.java
Normal file
199
src/main/java/net/runelite/deob/deobfuscators/rename/Mapper.java
Normal file
@@ -0,0 +1,199 @@
|
||||
package net.runelite.deob.deobfuscators.rename;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.runelite.deob.ClassFile;
|
||||
import net.runelite.deob.ClassGroup;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.attributes.code.Instruction;
|
||||
import net.runelite.deob.execution.ParallellMappingExecutor;
|
||||
|
||||
public class Mapper
|
||||
{
|
||||
private static final int MAX_CLASSES = 250;
|
||||
|
||||
private final ClassGroup source, target;
|
||||
private ParallelExecutorMapping mapping;
|
||||
|
||||
public Mapper(ClassGroup source, ClassGroup target)
|
||||
{
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public ParallelExecutorMapping getMapping()
|
||||
{
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
ParallelExecutorMapping finalm = new ParallelExecutorMapping(source, target);
|
||||
|
||||
finalm.merge(mapStaticMethods(source, target));
|
||||
finalm.merge(mapMethods(source, target));
|
||||
finalm.merge(mapPackets(source, target));
|
||||
|
||||
mapping = finalm;
|
||||
}
|
||||
|
||||
private ParallelExecutorMapping mapMethods(ClassGroup one, ClassGroup two)
|
||||
{
|
||||
List<ParallelExecutorMapping> pmes = new ArrayList<>();
|
||||
for (int i = -1; i < MAX_CLASSES; ++i)
|
||||
{
|
||||
ClassFile c1, c2;
|
||||
|
||||
if (i == -1)
|
||||
{
|
||||
c1 = one.findClass("client");
|
||||
c2 = two.findClass("client");
|
||||
}
|
||||
else
|
||||
{
|
||||
c1 = one.findClass("class" + i);
|
||||
c2 = two.findClass("class" + i);
|
||||
}
|
||||
|
||||
if (c1 == null || c2 == null)
|
||||
continue;
|
||||
|
||||
MethodSignatureMapper msm = new MethodSignatureMapper();
|
||||
msm.map(c1, c2);
|
||||
|
||||
Multimap<Method, Method> map = msm.getMap();
|
||||
for (Method m : map.keySet())
|
||||
{
|
||||
Collection<Method> methods = map.get(m);
|
||||
|
||||
for (Method other : methods)
|
||||
{
|
||||
HashMap<Object, Object> all = new HashMap();
|
||||
map(all, pmes, m, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParallelExecutorMapping finalm = new ParallelExecutorMapping(one, two);
|
||||
for (ParallelExecutorMapping pme : pmes)
|
||||
finalm.merge(pme);
|
||||
|
||||
return finalm;
|
||||
}
|
||||
|
||||
private ParallelExecutorMapping mapStaticMethods(ClassGroup one, ClassGroup two)
|
||||
{
|
||||
StaticMethodSignatureMapper smsm = new StaticMethodSignatureMapper();
|
||||
smsm.map(one, two);
|
||||
|
||||
List<ParallelExecutorMapping> pmes = new ArrayList<>();
|
||||
|
||||
for (Method m : smsm.getMap().keySet())
|
||||
{
|
||||
Collection<Method> methods = smsm.getMap().get(m);
|
||||
|
||||
for (Method other : methods)
|
||||
{
|
||||
HashMap<Object, Object> all = new HashMap();
|
||||
map(all, pmes, m, other);
|
||||
}
|
||||
}
|
||||
|
||||
ParallelExecutorMapping finalm = new ParallelExecutorMapping(one, two);
|
||||
for (ParallelExecutorMapping pme : pmes)
|
||||
finalm.merge(pme);
|
||||
|
||||
return finalm;
|
||||
}
|
||||
|
||||
private void map(Map<Object, Object> all, List<ParallelExecutorMapping> result, Method m1, Method m2)
|
||||
{
|
||||
if (all.containsKey(m1))
|
||||
return;
|
||||
all.put(m1, m2);
|
||||
|
||||
assert (m1.getCode() == null) == (m2.getCode() == null);
|
||||
|
||||
if (m1.getCode() == null)
|
||||
return;
|
||||
|
||||
ParallelExecutorMapping mappings = MappingExecutorUtil.map(m1, m2);
|
||||
|
||||
if (mappings.getMap().isEmpty() && mappings.crashed)
|
||||
return;
|
||||
|
||||
mappings.map(m1, m2);
|
||||
result.add(mappings);
|
||||
|
||||
for (Map.Entry<Object, Object> e : mappings.getMap().entrySet())
|
||||
{
|
||||
if (e.getKey() instanceof Method)
|
||||
{
|
||||
Method n1 = (Method) e.getKey(),
|
||||
n2 = (Method) e.getValue();
|
||||
|
||||
map(all, result, n1, n2);
|
||||
}
|
||||
else
|
||||
{
|
||||
all.put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ParallelExecutorMapping mapPackets(ClassGroup group1, ClassGroup group2)
|
||||
{
|
||||
// XXX PULL THESE FROM PREVIOUS MAPPINGS
|
||||
group1.findClass("client").findField("field446").packetHandler = true;
|
||||
group2.findClass("client").findField("field324").packetHandler = true;
|
||||
|
||||
Method m1 = group1.findClass("client").findMethod("vmethod3096");
|
||||
Method m2 = group2.findClass("client").findMethod("vmethod2975");
|
||||
|
||||
ParallelExecutorMapping mappings = MappingExecutorUtil.map(m1, m2);
|
||||
|
||||
System.out.println(mappings.packetHandler1.size() + " vs " + mappings.packetHandler2.size() + " handlers");
|
||||
|
||||
assert mappings.packetHandler1.size() == mappings.packetHandler2.size();
|
||||
|
||||
ParallellMappingExecutor.enable = true;
|
||||
ParallelExecutorMapping all = new ParallelExecutorMapping(group1, group2);
|
||||
|
||||
for (int i = 0; i < mappings.packetHandler1.size(); ++i)
|
||||
{
|
||||
PacketHandler if1 = mappings.packetHandler1.get(i);
|
||||
|
||||
PacketHandler highestHandler = null;
|
||||
ParallelExecutorMapping highest = null;
|
||||
|
||||
for (int j = 0; j < mappings.packetHandler2.size(); ++j)
|
||||
{
|
||||
PacketHandler if2 = mappings.packetHandler2.get(j);
|
||||
|
||||
Instruction i1 = if1.getFirstInsOfHandler(),
|
||||
i2 = if2.getFirstInsOfHandler();
|
||||
|
||||
ParallelExecutorMapping mapping = MappingExecutorUtil.mapFrame(group1, group2, i1, i2);
|
||||
|
||||
if (mapping.getMap().isEmpty())
|
||||
continue;
|
||||
|
||||
if (highest == null || mapping.getMap().size() > highest.getMap().size())
|
||||
{
|
||||
highest = mapping;
|
||||
highestHandler = if2;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(if1 + " <-> " + highestHandler + " <-> " + highest.getMap().size() + " " + highest.crashed);
|
||||
all.merge(highest);
|
||||
}
|
||||
|
||||
ParallellMappingExecutor.enable = false;
|
||||
return all;
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package net.runelite.deob.deobfuscators.rename;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.runelite.deob.ClassFile;
|
||||
import net.runelite.deob.ClassGroup;
|
||||
import net.runelite.deob.Field;
|
||||
import net.runelite.deob.Method;
|
||||
import net.runelite.deob.util.JarUtil;
|
||||
|
||||
public class Rename
|
||||
{
|
||||
private static final int MAX_CLASSES = 250;
|
||||
|
||||
private ClassGroup source, target;
|
||||
private ParallelExecutorMapping mapping;
|
||||
|
||||
public Rename(ClassGroup source, ClassGroup target)
|
||||
{
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public ParallelExecutorMapping getMapping()
|
||||
{
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
ParallelExecutorMapping finalm = new ParallelExecutorMapping(source, target);
|
||||
|
||||
finalm.merge(staticMethodSignatureMapper());
|
||||
finalm.merge(methodSignatureMapper());
|
||||
|
||||
for (int i = -1; i < MAX_CLASSES; ++i)
|
||||
{
|
||||
ClassFile c1;
|
||||
|
||||
if (i == -1)
|
||||
{
|
||||
c1 = source.findClass("client");
|
||||
}
|
||||
else
|
||||
{
|
||||
c1 = source.findClass("class" + i);
|
||||
}
|
||||
|
||||
if (c1 == null)
|
||||
continue;
|
||||
|
||||
for (Method m : c1.getMethods().getMethods())
|
||||
{
|
||||
if (!finalm.getMap().containsKey(m))
|
||||
System.out.println("missing " + m);
|
||||
}
|
||||
for (Field m : c1.getFields().getFields())
|
||||
{
|
||||
if (!finalm.getMap().containsKey(m))
|
||||
System.out.println("missing " + m);
|
||||
}
|
||||
}
|
||||
|
||||
mapping = finalm;
|
||||
}
|
||||
|
||||
private ParallelExecutorMapping methodSignatureMapper()
|
||||
{
|
||||
List<ParallelExecutorMapping> pmes = new ArrayList<>();
|
||||
|
||||
for (int i = -1; i < MAX_CLASSES; ++i)
|
||||
{
|
||||
ClassFile c1, c2;
|
||||
|
||||
if (i == -1)
|
||||
{
|
||||
c1 = source.findClass("client");
|
||||
c2 = target.findClass("client");
|
||||
}
|
||||
else
|
||||
{
|
||||
c1 = source.findClass("class" + i);
|
||||
c2 = target.findClass("class" + i);
|
||||
}
|
||||
|
||||
if (c1 == null || c2 == null)
|
||||
continue;
|
||||
|
||||
MethodSignatureMapper msm = new MethodSignatureMapper();
|
||||
msm.map(c1, c2);
|
||||
|
||||
Multimap<Method, Method> map = msm.getMap();
|
||||
for (Method m : map.keySet())
|
||||
{
|
||||
Collection<Method> methods = map.get(m);
|
||||
|
||||
for (Method other : methods)
|
||||
{
|
||||
HashMap<Object, Object> all = new HashMap();
|
||||
map(all, pmes, m, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParallelExecutorMapping finalm = new ParallelExecutorMapping(source, target);
|
||||
for (ParallelExecutorMapping pme : pmes)
|
||||
finalm.merge(pme);
|
||||
|
||||
return finalm;
|
||||
}
|
||||
|
||||
private ParallelExecutorMapping staticMethodSignatureMapper()
|
||||
{
|
||||
StaticMethodSignatureMapper smsm = new StaticMethodSignatureMapper();
|
||||
smsm.map(source, target);
|
||||
|
||||
List<ParallelExecutorMapping> pmes = new ArrayList<>();
|
||||
|
||||
for (Method m : smsm.getMap().keySet())
|
||||
{
|
||||
Collection<Method> methods = smsm.getMap().get(m);
|
||||
|
||||
for (Method other : methods)
|
||||
{
|
||||
HashMap<Object, Object> all = new HashMap();
|
||||
map(all, pmes, m, other);
|
||||
}
|
||||
}
|
||||
|
||||
ParallelExecutorMapping finalm = new ParallelExecutorMapping(source, target);
|
||||
for (ParallelExecutorMapping pme : pmes)
|
||||
finalm.merge(pme);
|
||||
|
||||
return finalm;
|
||||
}
|
||||
|
||||
private void map(Map<Object, Object> all, List<ParallelExecutorMapping> result, Method m1, Method m2)
|
||||
{
|
||||
if (all.containsKey(m1))
|
||||
return;
|
||||
all.put(m1, m2);
|
||||
|
||||
assert (m1.getCode() == null) == (m2.getCode() == null);
|
||||
|
||||
if (m1.getCode() == null)
|
||||
return;
|
||||
|
||||
ParallelExecutorMapping mappings = MappingExecutorUtil.map(m1, m2);
|
||||
|
||||
if (mappings.getMap().isEmpty() && mappings.crashed)
|
||||
return;
|
||||
|
||||
mappings.map(m1, m2);
|
||||
result.add(mappings);
|
||||
|
||||
for (Map.Entry<Object, Object> e : mappings.getMap().entrySet())
|
||||
{
|
||||
if (e.getKey() instanceof Method)
|
||||
{
|
||||
Method n1 = (Method) e.getKey(),
|
||||
n2 = (Method) e.getValue();
|
||||
|
||||
map(all, result, n1, n2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,12 @@ public class Class extends PoolEntry
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class copy()
|
||||
{
|
||||
return new Class(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(ConstantPool pool)
|
||||
|
||||
@@ -24,6 +24,12 @@ public class Double extends PoolEntry
|
||||
|
||||
value = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double copy()
|
||||
{
|
||||
return new Double(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
|
||||
@@ -27,6 +27,12 @@ public class Field extends PoolEntry
|
||||
this.clazz = clazz;
|
||||
this.nat = nat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field copy()
|
||||
{
|
||||
return new Field(clazz.copy(), nat.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(ConstantPool pool)
|
||||
|
||||
@@ -24,6 +24,12 @@ public class Float extends PoolEntry
|
||||
|
||||
value = f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float copy()
|
||||
{
|
||||
return new Float(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
|
||||
@@ -24,6 +24,12 @@ public class Integer extends PoolEntry
|
||||
|
||||
value = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer copy()
|
||||
{
|
||||
return new Integer(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
|
||||
@@ -28,6 +28,12 @@ public class InterfaceMethod extends PoolEntry
|
||||
classIndex = is.readUnsignedShort();
|
||||
natIndex = is.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterfaceMethod copy()
|
||||
{
|
||||
return new InterfaceMethod(clazz.copy(), nat.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(ConstantPool pool)
|
||||
|
||||
@@ -24,6 +24,12 @@ public class Long extends PoolEntry
|
||||
|
||||
value = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long copy()
|
||||
{
|
||||
return new Long(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
|
||||
@@ -29,6 +29,12 @@ public class Method extends PoolEntry
|
||||
natIndex = is.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method copy()
|
||||
{
|
||||
return new Method(clazz.copy(), nat.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.lang.String toString()
|
||||
{
|
||||
|
||||
@@ -41,6 +41,24 @@ public class NameAndType extends PoolEntry
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameAndType copy()
|
||||
{
|
||||
if (signature != null)
|
||||
{
|
||||
return new NameAndType(name, new Signature(signature));
|
||||
}
|
||||
else if (type != null)
|
||||
{
|
||||
return new NameAndType(name, new Type(type));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(ConstantPool pool)
|
||||
|
||||
@@ -31,6 +31,8 @@ public abstract class PoolEntry
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
public abstract PoolEntry copy();
|
||||
|
||||
public abstract void write(DataOutputStream out) throws IOException;
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@ public class String extends PoolEntry
|
||||
|
||||
string = str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String copy()
|
||||
{
|
||||
return new String(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(ConstantPool pool)
|
||||
|
||||
@@ -24,6 +24,12 @@ public class UTF8 extends PoolEntry
|
||||
|
||||
string = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UTF8 copy()
|
||||
{
|
||||
return new UTF8(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
|
||||
Reference in New Issue
Block a user