summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/convert/MappingsConverter.java
diff options
context:
space:
mode:
authorGravatar jeff2015-03-10 00:55:03 -0400
committerGravatar jeff2015-03-10 00:55:03 -0400
commit430df87ba5d855ca29bc53a5765a2862d2209098 (patch)
treeee427f009da8b29e7a66a4b4ce882120f9bb2cbf /src/cuchaz/enigma/convert/MappingsConverter.java
parentfield matcher is starting to be useful (diff)
downloadenigma-fork-430df87ba5d855ca29bc53a5765a2862d2209098.tar.gz
enigma-fork-430df87ba5d855ca29bc53a5765a2862d2209098.tar.xz
enigma-fork-430df87ba5d855ca29bc53a5765a2862d2209098.zip
tweaks and improvements to field matching gui
Diffstat (limited to 'src/cuchaz/enigma/convert/MappingsConverter.java')
-rw-r--r--src/cuchaz/enigma/convert/MappingsConverter.java130
1 files changed, 95 insertions, 35 deletions
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;
17import java.util.List; 17import java.util.List;
18import java.util.Map; 18import java.util.Map;
19import java.util.Map.Entry; 19import java.util.Map.Entry;
20import java.util.Set;
20import java.util.jar.JarFile; 21import java.util.jar.JarFile;
21 22
22import com.beust.jcommander.internal.Lists; 23import com.beust.jcommander.internal.Lists;
@@ -24,6 +25,7 @@ import com.google.common.collect.BiMap;
24import com.google.common.collect.HashMultimap; 25import com.google.common.collect.HashMultimap;
25import com.google.common.collect.Maps; 26import com.google.common.collect.Maps;
26import com.google.common.collect.Multimap; 27import com.google.common.collect.Multimap;
28import com.google.common.collect.Sets;
27 29
28import cuchaz.enigma.Deobfuscator; 30import cuchaz.enigma.Deobfuscator;
29import cuchaz.enigma.analysis.JarIndex; 31import cuchaz.enigma.analysis.JarIndex;
@@ -31,13 +33,17 @@ import cuchaz.enigma.convert.ClassNamer.SidedClassNamer;
31import cuchaz.enigma.mapping.ClassEntry; 33import cuchaz.enigma.mapping.ClassEntry;
32import cuchaz.enigma.mapping.ClassMapping; 34import cuchaz.enigma.mapping.ClassMapping;
33import cuchaz.enigma.mapping.ClassNameReplacer; 35import cuchaz.enigma.mapping.ClassNameReplacer;
36import cuchaz.enigma.mapping.EntryFactory;
37import cuchaz.enigma.mapping.FieldEntry;
34import cuchaz.enigma.mapping.FieldMapping; 38import cuchaz.enigma.mapping.FieldMapping;
35import cuchaz.enigma.mapping.Mappings; 39import cuchaz.enigma.mapping.Mappings;
40import cuchaz.enigma.mapping.MappingsChecker;
36import cuchaz.enigma.mapping.MethodMapping; 41import cuchaz.enigma.mapping.MethodMapping;
42import cuchaz.enigma.mapping.Type;
37 43
38public class MappingsConverter { 44public class MappingsConverter {
39 45
40 public static ClassMatches computeMatches(JarFile sourceJar, JarFile destJar, Mappings mappings) { 46 public static ClassMatches computeClassMatches(JarFile sourceJar, JarFile destJar, Mappings mappings) {
41 47
42 // index jars 48 // index jars
43 System.out.println("Indexing source jar..."); 49 System.out.println("Indexing source jar...");
@@ -245,47 +251,101 @@ public class MappingsConverter {
245 mappings.renameObfClass(entry.getKey().getName(), entry.getValue().getName()); 251 mappings.renameObfClass(entry.getKey().getName(), entry.getValue().getName());
246 } 252 }
247 } 253 }
248 254
249 /* TODO: after we get a mapping, check to see that the other entries match 255 public static FieldMatches computeFieldMatches(Deobfuscator destDeobfuscator, Mappings destMappings, ClassMatches classMatches) {
250 public static void checkMethods() { 256
257 FieldMatches fieldMatches = new FieldMatches();
258
259 // unmatched source fields are easy
260 MappingsChecker checker = new MappingsChecker(destDeobfuscator.getJarIndex());
261 checker.dropBrokenMappings(destMappings);
262 for (FieldEntry destObfField : checker.getDroppedFieldMappings().keySet()) {
263 FieldEntry srcObfField = translate(destObfField, classMatches.getUniqueMatches().inverse());
264 fieldMatches.addUnmatchedSourceField(srcObfField);
265 }
251 266
252 // check the method matches 267 // get matched fields (anything that's left after the checks/drops is matched(
253 System.out.println("Checking methods..."); 268 for (ClassMapping classMapping : destMappings.classes()) {
254 for (ClassMapping classMapping : mappings.classes()) { 269 collectMatchedFields(fieldMatches, classMapping, classMatches);
255 ClassEntry classEntry = new ClassEntry(classMapping.getObfFullName()); 270 }
256 for (MethodMapping methodMapping : classMapping.methods()) { 271
272 // get unmatched dest fields
273 for (FieldEntry destFieldEntry : destDeobfuscator.getJarIndex().getObfFieldEntries()) {
274 if (!fieldMatches.isMatchedDestField(destFieldEntry)) {
275 fieldMatches.addUnmatchedDestField(destFieldEntry);
276 }
277 }
278
279 System.out.println("Automatching " + fieldMatches.getUnmatchedSourceFields().size() + " unmatched source fields...");
280
281 // go through the unmatched source fields and try to pick out the easy matches
282 for (ClassEntry obfSourceClass : Lists.newArrayList(fieldMatches.getSourceClassesWithUnmatchedFields())) {
283 for (FieldEntry obfSourceField : Lists.newArrayList(fieldMatches.getUnmatchedSourceFields(obfSourceClass))) {
257 284
258 // skip constructors 285 // get the possible dest matches
259 if (methodMapping.getObfName().equals("<init>")) { 286 ClassEntry obfDestClass = classMatches.getUniqueMatches().get(obfSourceClass);
260 continue;
261 }
262 287
263 MethodEntry methodEntry = new MethodEntry( 288 // filter by type
264 classEntry, 289 Set<FieldEntry> obfDestFields = Sets.newHashSet();
265 methodMapping.getObfName(), 290 for (FieldEntry obfDestField : fieldMatches.getUnmatchedDestFields(obfDestClass)) {
266 methodMapping.getObfSignature() 291 Type translatedDestType = translate(obfDestField.getType(), classMatches.getUniqueMatches().inverse());
267 ); 292 if (translatedDestType.equals(obfSourceField.getType())) {
268 if (!destIndex.containsObfBehavior(methodEntry)) { 293 obfDestFields.add(obfDestField);
269 System.err.println("WARNING: method doesn't match: " + methodEntry);
270
271 // TODO: show methods if needed
272 // show the available methods
273 System.err.println("\tAvailable dest methods:");
274 CtClass c = destLoader.loadClass(classMapping.getObfFullName());
275 for (CtBehavior behavior : c.getDeclaredBehaviors()) {
276 System.err.println("\t\t" + EntryFactory.getBehaviorEntry(behavior));
277 }
278
279 System.err.println("\tAvailable source methods:");
280 c = sourceLoader.loadClass(matchedClassNames.inverse().get(classMapping.getObfFullName()));
281 for (CtBehavior behavior : c.getDeclaredBehaviors()) {
282 System.err.println("\t\t" + EntryFactory.getBehaviorEntry(behavior));
283 } 294 }
284 } 295 }
296
297 if (obfDestFields.size() == 1) {
298 // make the easy match
299 FieldEntry obfDestField = obfDestFields.iterator().next();
300 fieldMatches.makeMatch(obfSourceField, obfDestField);
301 } else if (obfDestFields.isEmpty()) {
302 // no match is possible =(
303 fieldMatches.makeSourceUnmatchable(obfSourceField);
304 }
285 } 305 }
286 } 306 }
287 307
288 System.out.println("Done!"); 308 System.out.println(String.format("Ended up with %d ambiguous and %d unmatchable source fields",
309 fieldMatches.getUnmatchedSourceFields().size(),
310 fieldMatches.getUnmatchableSourceFields().size()
311 ));
312
313 return fieldMatches;
314 }
315
316 private static void collectMatchedFields(FieldMatches fieldMatches, ClassMapping destClassMapping, ClassMatches classMatches) {
317
318 // get the fields for this class
319 for (FieldMapping destFieldMapping : destClassMapping.fields()) {
320 FieldEntry destObfField = EntryFactory.getObfFieldEntry(destClassMapping, destFieldMapping);
321 FieldEntry srcObfField = translate(destObfField, classMatches.getUniqueMatches().inverse());
322 fieldMatches.addMatch(srcObfField, destObfField);
323 }
324
325 // recurse
326 for (ClassMapping destInnerClassMapping : destClassMapping.innerClasses()) {
327 collectMatchedFields(fieldMatches, destInnerClassMapping, classMatches);
328 }
329 }
330
331 private static FieldEntry translate(FieldEntry in, BiMap<ClassEntry,ClassEntry> map) {
332 return new FieldEntry(
333 map.get(in.getClassEntry()),
334 in.getName(),
335 translate(in.getType(), map)
336 );
337 }
338
339 private static Type translate(Type type, final BiMap<ClassEntry,ClassEntry> map) {
340 return new Type(type, new ClassNameReplacer() {
341 @Override
342 public String replace(String inClassName) {
343 ClassEntry outClassEntry = map.get(new ClassEntry(inClassName));
344 if (outClassEntry == null) {
345 return null;
346 }
347 return outClassEntry.getName();
348 }
349 });
289 } 350 }
290 */
291} 351}