From 430df87ba5d855ca29bc53a5765a2862d2209098 Mon Sep 17 00:00:00 2001 From: jeff Date: Tue, 10 Mar 2015 00:55:03 -0400 Subject: tweaks and improvements to field matching gui --- src/cuchaz/enigma/convert/MappingsConverter.java | 130 +++++++++++++++++------ 1 file changed, 95 insertions(+), 35 deletions(-) (limited to 'src/cuchaz/enigma/convert/MappingsConverter.java') diff --git a/src/cuchaz/enigma/convert/MappingsConverter.java b/src/cuchaz/enigma/convert/MappingsConverter.java index 667ee9d..9ab1baa 100644 --- a/src/cuchaz/enigma/convert/MappingsConverter.java +++ b/src/cuchaz/enigma/convert/MappingsConverter.java @@ -17,6 +17,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.jar.JarFile; import com.beust.jcommander.internal.Lists; @@ -24,6 +25,7 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; import cuchaz.enigma.Deobfuscator; import cuchaz.enigma.analysis.JarIndex; @@ -31,13 +33,17 @@ import cuchaz.enigma.convert.ClassNamer.SidedClassNamer; import cuchaz.enigma.mapping.ClassEntry; import cuchaz.enigma.mapping.ClassMapping; import cuchaz.enigma.mapping.ClassNameReplacer; +import cuchaz.enigma.mapping.EntryFactory; +import cuchaz.enigma.mapping.FieldEntry; import cuchaz.enigma.mapping.FieldMapping; import cuchaz.enigma.mapping.Mappings; +import cuchaz.enigma.mapping.MappingsChecker; import cuchaz.enigma.mapping.MethodMapping; +import cuchaz.enigma.mapping.Type; public class MappingsConverter { - public static ClassMatches computeMatches(JarFile sourceJar, JarFile destJar, Mappings mappings) { + public static ClassMatches computeClassMatches(JarFile sourceJar, JarFile destJar, Mappings mappings) { // index jars System.out.println("Indexing source jar..."); @@ -245,47 +251,101 @@ public class MappingsConverter { mappings.renameObfClass(entry.getKey().getName(), entry.getValue().getName()); } } - - /* TODO: after we get a mapping, check to see that the other entries match - public static void checkMethods() { + + public static FieldMatches computeFieldMatches(Deobfuscator destDeobfuscator, Mappings destMappings, ClassMatches classMatches) { + + FieldMatches fieldMatches = new FieldMatches(); + + // unmatched source fields are easy + MappingsChecker checker = new MappingsChecker(destDeobfuscator.getJarIndex()); + checker.dropBrokenMappings(destMappings); + for (FieldEntry destObfField : checker.getDroppedFieldMappings().keySet()) { + FieldEntry srcObfField = translate(destObfField, classMatches.getUniqueMatches().inverse()); + fieldMatches.addUnmatchedSourceField(srcObfField); + } - // check the method matches - System.out.println("Checking methods..."); - for (ClassMapping classMapping : mappings.classes()) { - ClassEntry classEntry = new ClassEntry(classMapping.getObfFullName()); - for (MethodMapping methodMapping : classMapping.methods()) { + // get matched fields (anything that's left after the checks/drops is matched( + for (ClassMapping classMapping : destMappings.classes()) { + collectMatchedFields(fieldMatches, classMapping, classMatches); + } + + // get unmatched dest fields + for (FieldEntry destFieldEntry : destDeobfuscator.getJarIndex().getObfFieldEntries()) { + if (!fieldMatches.isMatchedDestField(destFieldEntry)) { + fieldMatches.addUnmatchedDestField(destFieldEntry); + } + } + + System.out.println("Automatching " + fieldMatches.getUnmatchedSourceFields().size() + " unmatched source fields..."); + + // go through the unmatched source fields and try to pick out the easy matches + for (ClassEntry obfSourceClass : Lists.newArrayList(fieldMatches.getSourceClassesWithUnmatchedFields())) { + for (FieldEntry obfSourceField : Lists.newArrayList(fieldMatches.getUnmatchedSourceFields(obfSourceClass))) { - // skip constructors - if (methodMapping.getObfName().equals("")) { - continue; - } + // get the possible dest matches + ClassEntry obfDestClass = classMatches.getUniqueMatches().get(obfSourceClass); - MethodEntry methodEntry = new MethodEntry( - classEntry, - methodMapping.getObfName(), - methodMapping.getObfSignature() - ); - if (!destIndex.containsObfBehavior(methodEntry)) { - System.err.println("WARNING: method doesn't match: " + methodEntry); - - // TODO: show methods if needed - // show the available methods - System.err.println("\tAvailable dest methods:"); - CtClass c = destLoader.loadClass(classMapping.getObfFullName()); - for (CtBehavior behavior : c.getDeclaredBehaviors()) { - System.err.println("\t\t" + EntryFactory.getBehaviorEntry(behavior)); - } - - System.err.println("\tAvailable source methods:"); - c = sourceLoader.loadClass(matchedClassNames.inverse().get(classMapping.getObfFullName())); - for (CtBehavior behavior : c.getDeclaredBehaviors()) { - System.err.println("\t\t" + EntryFactory.getBehaviorEntry(behavior)); + // filter by type + Set obfDestFields = Sets.newHashSet(); + for (FieldEntry obfDestField : fieldMatches.getUnmatchedDestFields(obfDestClass)) { + Type translatedDestType = translate(obfDestField.getType(), classMatches.getUniqueMatches().inverse()); + if (translatedDestType.equals(obfSourceField.getType())) { + obfDestFields.add(obfDestField); } } + + if (obfDestFields.size() == 1) { + // make the easy match + FieldEntry obfDestField = obfDestFields.iterator().next(); + fieldMatches.makeMatch(obfSourceField, obfDestField); + } else if (obfDestFields.isEmpty()) { + // no match is possible =( + fieldMatches.makeSourceUnmatchable(obfSourceField); + } } } - System.out.println("Done!"); + System.out.println(String.format("Ended up with %d ambiguous and %d unmatchable source fields", + fieldMatches.getUnmatchedSourceFields().size(), + fieldMatches.getUnmatchableSourceFields().size() + )); + + return fieldMatches; + } + + private static void collectMatchedFields(FieldMatches fieldMatches, ClassMapping destClassMapping, ClassMatches classMatches) { + + // get the fields for this class + for (FieldMapping destFieldMapping : destClassMapping.fields()) { + FieldEntry destObfField = EntryFactory.getObfFieldEntry(destClassMapping, destFieldMapping); + FieldEntry srcObfField = translate(destObfField, classMatches.getUniqueMatches().inverse()); + fieldMatches.addMatch(srcObfField, destObfField); + } + + // recurse + for (ClassMapping destInnerClassMapping : destClassMapping.innerClasses()) { + collectMatchedFields(fieldMatches, destInnerClassMapping, classMatches); + } + } + + private static FieldEntry translate(FieldEntry in, BiMap map) { + return new FieldEntry( + map.get(in.getClassEntry()), + in.getName(), + translate(in.getType(), map) + ); + } + + private static Type translate(Type type, final BiMap map) { + return new Type(type, new ClassNameReplacer() { + @Override + public String replace(String inClassName) { + ClassEntry outClassEntry = map.get(new ClassEntry(inClassName)); + if (outClassEntry == null) { + return null; + } + return outClassEntry.getName(); + } + }); } - */ } -- cgit v1.2.3