Add annotation integrity checker, if execution mapper can't decide return null
This commit is contained in:
@@ -0,0 +1,113 @@
|
|||||||
|
package net.runelite.deob.deobfuscators.mapping;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import net.runelite.asm.ClassFile;
|
||||||
|
import net.runelite.asm.ClassGroup;
|
||||||
|
import net.runelite.asm.Field;
|
||||||
|
import net.runelite.asm.Method;
|
||||||
|
import net.runelite.asm.attributes.Annotations;
|
||||||
|
import net.runelite.asm.attributes.Attributes;
|
||||||
|
import net.runelite.asm.signature.Type;
|
||||||
|
|
||||||
|
public class AnnotationIntegrityChecker
|
||||||
|
{
|
||||||
|
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
|
||||||
|
|
||||||
|
private ClassGroup one, two;
|
||||||
|
private ParallelExecutorMapping mapping;
|
||||||
|
|
||||||
|
public AnnotationIntegrityChecker(ClassGroup one, ClassGroup two, ParallelExecutorMapping mapping)
|
||||||
|
{
|
||||||
|
this.one = one;
|
||||||
|
this.two = two;
|
||||||
|
this.mapping = mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
for (ClassFile cf : one.getClasses())
|
||||||
|
{
|
||||||
|
ClassFile other = (ClassFile) mapping.get(cf);
|
||||||
|
|
||||||
|
List<Field> exf1 = getExportedFields(cf);
|
||||||
|
List<Method> exm1 = getExportedMethods(cf);
|
||||||
|
|
||||||
|
for (Field f1 : exf1)
|
||||||
|
{
|
||||||
|
if (f1.isStatic())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Field f2 = findExportedField(other, getExportedName(f1.getAttributes()));
|
||||||
|
|
||||||
|
if (f2 == null)
|
||||||
|
{
|
||||||
|
System.out.println("Missing exported field on " + other + " named " + getExportedName(f1.getAttributes()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Method m1 : exm1)
|
||||||
|
{
|
||||||
|
if (m1.isStatic())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Method m2 = findExportedMethod(other, getExportedName(m1.getAttributes()));
|
||||||
|
|
||||||
|
if (m2 == null)
|
||||||
|
{
|
||||||
|
System.out.println("Missing exported method on " + other + " named " + getExportedName(m1.getAttributes()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Field> getExportedFields(ClassFile clazz)
|
||||||
|
{
|
||||||
|
List<Field> list = new ArrayList<>();
|
||||||
|
for (Field f : clazz.getFields().getFields())
|
||||||
|
{
|
||||||
|
if (getExportedName(f.getAttributes()) != null)
|
||||||
|
list.add(f);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Method> getExportedMethods(ClassFile clazz)
|
||||||
|
{
|
||||||
|
List<Method> list = new ArrayList<>();
|
||||||
|
for (Method m : clazz.getMethods().getMethods())
|
||||||
|
{
|
||||||
|
if (getExportedName(m.getAttributes()) != null)
|
||||||
|
list.add(m);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getExportedName(Attributes attr)
|
||||||
|
{
|
||||||
|
Annotations an = attr.getAnnotations();
|
||||||
|
|
||||||
|
if (an == null || an.find(EXPORT) == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return an.find(EXPORT).getElement().getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Field findExportedField(ClassFile clazz, String name)
|
||||||
|
{
|
||||||
|
for (Field f : getExportedFields(clazz))
|
||||||
|
if (getExportedName(f.getAttributes()).equals(name))
|
||||||
|
return f;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Method findExportedMethod(ClassFile clazz, String name)
|
||||||
|
{
|
||||||
|
for (Method m : getExportedMethods(clazz))
|
||||||
|
if (getExportedName(m.getAttributes()).equals(name))
|
||||||
|
return m;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,18 +30,10 @@ public class AnnotationMapper
|
|||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
ClassGroupMapper m = new ClassGroupMapper(source, target);
|
|
||||||
m.map();
|
|
||||||
|
|
||||||
for (ClassFile c : source.getClasses())
|
for (ClassFile c : source.getClasses())
|
||||||
{
|
{
|
||||||
ClassFile other = m.get(c);
|
ClassFile other = (ClassFile) mapping.get(c);
|
||||||
|
System.out.println(c + " -> " + other);
|
||||||
if (other == null)
|
|
||||||
{
|
|
||||||
other = (ClassFile) mapping.get(c);
|
|
||||||
System.out.println("FALLBACK " + c + " -> " + other);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (other == null)
|
if (other == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.runelite.deob.deobfuscators.mapping;
|
package net.runelite.deob.deobfuscators.mapping;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class ExecutionMapper
|
|||||||
public ParallelExecutorMapping run()
|
public ParallelExecutorMapping run()
|
||||||
{
|
{
|
||||||
ParallelExecutorMapping highest = null;
|
ParallelExecutorMapping highest = null;
|
||||||
|
boolean multiple = false;
|
||||||
|
|
||||||
for (Method m : methods2)
|
for (Method m : methods2)
|
||||||
{
|
{
|
||||||
@@ -30,9 +31,19 @@ public class ExecutionMapper
|
|||||||
mappings.put(m, mapping);
|
mappings.put(m, mapping);
|
||||||
|
|
||||||
if (highest == null || mapping.same > highest.same)
|
if (highest == null || mapping.same > highest.same)
|
||||||
|
{
|
||||||
highest = mapping;
|
highest = mapping;
|
||||||
|
multiple = false;
|
||||||
|
}
|
||||||
|
else if (mapping.same == highest.same)
|
||||||
|
{
|
||||||
|
multiple = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (multiple)
|
||||||
|
return null;
|
||||||
|
|
||||||
return highest;
|
return highest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ public class Mapper
|
|||||||
ExecutionMapper em = new ExecutionMapper(m, methods);
|
ExecutionMapper em = new ExecutionMapper(m, methods);
|
||||||
|
|
||||||
ParallelExecutorMapping mapping = em.run();
|
ParallelExecutorMapping mapping = em.run();
|
||||||
|
if (mapping == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
mapping.map(mapping.m1, mapping.m2);
|
mapping.map(mapping.m1, mapping.m2);
|
||||||
|
|
||||||
pmes.add(mapping);
|
pmes.add(mapping);
|
||||||
@@ -85,6 +88,9 @@ public class Mapper
|
|||||||
ExecutionMapper em = new ExecutionMapper(m, methods);
|
ExecutionMapper em = new ExecutionMapper(m, methods);
|
||||||
|
|
||||||
ParallelExecutorMapping mapping = em.run();
|
ParallelExecutorMapping mapping = em.run();
|
||||||
|
if (mapping == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
mapping.map(mapping.m1, mapping.m2);
|
mapping.map(mapping.m1, mapping.m2);
|
||||||
|
|
||||||
pmes.add(mapping);
|
pmes.add(mapping);
|
||||||
@@ -129,7 +135,6 @@ public class Mapper
|
|||||||
|
|
||||||
PacketHandler highestHandler = null;
|
PacketHandler highestHandler = null;
|
||||||
ParallelExecutorMapping highest = null;
|
ParallelExecutorMapping highest = null;
|
||||||
int maxContradictions = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < mappings.packetHandler2.size(); ++j)
|
for (int j = 0; j < mappings.packetHandler2.size(); ++j)
|
||||||
{
|
{
|
||||||
@@ -148,22 +153,12 @@ public class Mapper
|
|||||||
|
|
||||||
int p = pem.contradicts(mapping);
|
int p = pem.contradicts(mapping);
|
||||||
|
|
||||||
if (if1.getPacketId() == 9 && (if2.getPacketId() == 25 || if2.getPacketId() == 187))
|
|
||||||
{
|
|
||||||
int i444 =6;
|
|
||||||
pem.contradicts(mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (highest == null || p < maxContradictions)
|
|
||||||
if (highest == null || mapping.getMap().size() > highest.getMap().size())
|
if (highest == null || mapping.getMap().size() > highest.getMap().size())
|
||||||
{
|
{
|
||||||
if (p == 0 && mapping.crashed == false)
|
if (p == 0 && mapping.crashed == false)
|
||||||
//if (p == 0)
|
|
||||||
//if (!pem.contradicts(mapping))
|
|
||||||
{
|
{
|
||||||
highest = mapping;
|
highest = mapping;
|
||||||
highestHandler = if2;
|
highestHandler = if2;
|
||||||
maxContradictions = p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +166,6 @@ public class Mapper
|
|||||||
if (highest == null)
|
if (highest == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
//int i44 = 5;
|
|
||||||
}
|
}
|
||||||
System.out.println(if1 + " <-> " + highestHandler + " <-> " + highest.getMap().size() + " " + highest.crashed);
|
System.out.println(if1 + " <-> " + highestHandler + " <-> " + highest.getMap().size() + " " + highest.crashed);
|
||||||
all.merge(highest);
|
all.merge(highest);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class ParallelExecutorMapping
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "ParallelExecutorMapping{size = " + map.size() + ", crashed = " + crashed + "}";
|
return "ParallelExecutorMapping{size = " + map.keySet().size() + ", crashed = " + crashed + ", same = " + same + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mapping getMapping(Object from, Object to)
|
private Mapping getMapping(Object from, Object to)
|
||||||
@@ -143,6 +143,29 @@ public class ParallelExecutorMapping
|
|||||||
|
|
||||||
mapClass(key, value);
|
mapClass(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get leftover classes, they usually contain exclusively static
|
||||||
|
* fields and methods so they're hard to pinpoint
|
||||||
|
*/
|
||||||
|
ClassGroupMapper m = new ClassGroupMapper(group, group2);
|
||||||
|
m.map();
|
||||||
|
|
||||||
|
for (ClassFile cf : group.getClasses())
|
||||||
|
if (!map.containsKey(cf))
|
||||||
|
{
|
||||||
|
ClassFile other = m.get(cf);
|
||||||
|
if (other == null)
|
||||||
|
{
|
||||||
|
System.out.println("Unable to map class " + cf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.out.println("Build classes fallback " + cf + " -> " + other);
|
||||||
|
|
||||||
|
Mapping ma = getMapping(cf, other);
|
||||||
|
ma.inc();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(Object o)
|
public Object get(Object o)
|
||||||
|
|||||||
@@ -3,14 +3,21 @@ package net.runelite.deob.deobfuscators.rename;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import net.runelite.asm.ClassGroup;
|
import net.runelite.asm.ClassGroup;
|
||||||
import net.runelite.deob.updater.UpdateMappings;
|
import net.runelite.asm.Method;
|
||||||
|
import net.runelite.deob.deobfuscators.mapping.AnnotationIntegrityChecker;
|
||||||
|
import net.runelite.deob.deobfuscators.mapping.AnnotationMapper;
|
||||||
|
import net.runelite.deob.deobfuscators.mapping.Mapper;
|
||||||
|
import net.runelite.deob.deobfuscators.mapping.MappingExecutorUtil;
|
||||||
|
import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping;
|
||||||
|
import static net.runelite.deob.deobfuscators.rename.MapStaticTest.print;
|
||||||
|
import static net.runelite.deob.deobfuscators.rename.MapStaticTest.summary;
|
||||||
import net.runelite.deob.util.JarUtil;
|
import net.runelite.deob.util.JarUtil;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class AnnotationMapperTest
|
public class AnnotationMapperTest
|
||||||
{
|
{
|
||||||
private static final String JAR1 = "C:\\Users\\Adam\\.m2\\repository\\net\\runelite\\rs\\rs-client\\1.0-SNAPSHOT\\rs-client-1.0-SNAPSHOT.jar",
|
private static final String JAR1 = "C:\\Users\\Adam\\.m2\\repository\\net\\runelite\\rs\\rs-client\\1.0-SNAPSHOT\\rs-client-1.0-SNAPSHOT.jar",
|
||||||
JAR2 = "d:/rs/07/gamepack_v21_deobfuscated.jar",
|
JAR2 = "d:/rs/07/gamepack_113_deobfuscated.jar",
|
||||||
OUT = "d:/rs/07/adamout.jar";
|
OUT = "d:/rs/07/adamout.jar";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -19,10 +26,30 @@ public class AnnotationMapperTest
|
|||||||
ClassGroup group1 = JarUtil.loadJar(new File(JAR1));
|
ClassGroup group1 = JarUtil.loadJar(new File(JAR1));
|
||||||
ClassGroup group2 = JarUtil.loadJar(new File(JAR2));
|
ClassGroup group2 = JarUtil.loadJar(new File(JAR2));
|
||||||
|
|
||||||
UpdateMappings um = new UpdateMappings(group1, group2);
|
Mapper mapper = new Mapper(group1, group2);
|
||||||
um.update();
|
mapper.run();
|
||||||
|
ParallelExecutorMapping mapping = mapper.getMapping();
|
||||||
|
|
||||||
um.save(new File(OUT));
|
summary(mapping, group1);
|
||||||
|
|
||||||
|
String sg1 = print(group1),
|
||||||
|
sg2 = print(group2);
|
||||||
|
|
||||||
|
System.out.println("GROUP 1 " + sg1);
|
||||||
|
System.out.println("GROUP 2 " + sg2);
|
||||||
|
|
||||||
|
Method m1 = group1.findClass("class199").findMethod("method3902");
|
||||||
|
Method m2 = (Method) mapping.get(m1);
|
||||||
|
|
||||||
|
MappingExecutorUtil.map(m1, m2);
|
||||||
|
|
||||||
|
AnnotationMapper amapper = new AnnotationMapper(group1, group2, mapping);
|
||||||
|
amapper.run();
|
||||||
|
|
||||||
|
AnnotationIntegrityChecker aic = new AnnotationIntegrityChecker(group1, group2, mapping);
|
||||||
|
aic.run();
|
||||||
|
|
||||||
|
JarUtil.saveJar(group2, new File(OUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user