From 2dc7428e37bdd7a119f53d02ce157675509b0d63 Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 23 Feb 2015 23:29:22 -0500 Subject: lots of work in better handling of inner classes also working on recognizing unobfuscated and deobfuscated jars (needed for M3L) --- src/cuchaz/enigma/analysis/JarIndex.java | 67 +++++++++++++++++--------------- 1 file changed, 35 insertions(+), 32 deletions(-) (limited to 'src/cuchaz/enigma/analysis/JarIndex.java') diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 1c74f15..6e7c69d 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java @@ -61,9 +61,9 @@ public class JarIndex { private Multimap m_methodImplementations; private Multimap> m_behaviorReferences; private Multimap> m_fieldReferences; - private Multimap m_innerClasses; - private Map m_outerClasses; - private Map m_anonymousClasses; + private Multimap m_innerClassesByOuter; + private Map m_outerClassesByInner; + private Map m_anonymousClasses; private Map m_bridgedMethods; public JarIndex() { @@ -74,8 +74,8 @@ public class JarIndex { m_methodImplementations = HashMultimap.create(); m_behaviorReferences = HashMultimap.create(); m_fieldReferences = HashMultimap.create(); - m_innerClasses = HashMultimap.create(); - m_outerClasses = Maps.newHashMap(); + m_innerClassesByOuter = HashMultimap.create(); + m_outerClassesByInner = Maps.newHashMap(); m_anonymousClasses = Maps.newHashMap(); m_bridgedMethods = Maps.newHashMap(); } @@ -129,33 +129,40 @@ public class JarIndex { } if (buildInnerClasses) { + // step 5: index inner classes and anonymous classes for (CtClass c : JarClassIterator.classes(jar)) { ClassRenamer.moveAllClassesOutOfDefaultPackage(c, Constants.NonePackage); - String outerClassName = findOuterClass(c); - if (outerClassName != null) { - String innerClassName = c.getSimpleName(); - m_innerClasses.put(outerClassName, innerClassName); - boolean innerWasAdded = m_outerClasses.put(innerClassName, outerClassName) == null; + ClassEntry innerClassEntry = EntryFactory.getClassEntry(c); + ClassEntry outerClassEntry = findOuterClass(c); + if (outerClassEntry != null) { + m_innerClassesByOuter.put(outerClassEntry, innerClassEntry); + boolean innerWasAdded = m_outerClassesByInner.put(innerClassEntry, outerClassEntry) == null; assert (innerWasAdded); - BehaviorEntry enclosingBehavior = isAnonymousClass(c, outerClassName); + BehaviorEntry enclosingBehavior = isAnonymousClass(c, outerClassEntry); if (enclosingBehavior != null) { - m_anonymousClasses.put(innerClassName, enclosingBehavior); + m_anonymousClasses.put(innerClassEntry, enclosingBehavior); // DEBUG - // System.out.println( "ANONYMOUS: " + outerClassName + "$" + innerClassName ); + //System.out.println("ANONYMOUS: " + outerClassEntry.getName() + "$" + innerClassEntry.getSimpleName()); } else { // DEBUG - // System.out.println( "INNER: " + outerClassName + "$" + innerClassName ); + //System.out.println("INNER: " + outerClassEntry.getName() + "$" + innerClassEntry.getSimpleName()); } } } // step 6: update other indices with inner class info Map renames = Maps.newHashMap(); - for (Map.Entry entry : m_outerClasses.entrySet()) { - renames.put(Constants.NonePackage + "/" + entry.getKey(), entry.getValue() + "$" + entry.getKey()); + for (Map.Entry mapEntry : m_innerClassesByOuter.entries()) { + ClassEntry outerClassEntry = mapEntry.getKey(); + ClassEntry innerClassEntry = mapEntry.getValue(); + outerClassEntry = EntryFactory.getChainedOuterClassName(this, outerClassEntry); + String newName = outerClassEntry.getName() + "$" + innerClassEntry.getSimpleName(); + // DEBUG + //System.out.println("REPLACE: " + innerClassEntry.getName() + " WITH " + newName); + renames.put(innerClassEntry.getName(), newName); } EntryRenamer.renameClassesInSet(renames, m_obfClassEntries); m_translationIndex.renameClasses(renames); @@ -290,7 +297,7 @@ public class JarIndex { } } - private String findOuterClass(CtClass c) { + private ClassEntry findOuterClass(CtClass c) { // inner classes: // have constructors that can (illegally) set synthetic fields @@ -341,19 +348,19 @@ public class JarIndex { // do we have an answer yet? if (callerClasses.isEmpty()) { if (illegallySetClasses.size() == 1) { - return illegallySetClasses.iterator().next().getName(); + return illegallySetClasses.iterator().next(); } else { System.out.println(String.format("WARNING: Unable to find outer class for %s. No caller and no illegally set field classes.", classEntry)); } } else { if (callerClasses.size() == 1) { - return callerClasses.iterator().next().getName(); + return callerClasses.iterator().next(); } else { // multiple callers, do the illegally set classes narrow it down? Set intersection = Sets.newHashSet(callerClasses); intersection.retainAll(illegallySetClasses); if (intersection.size() == 1) { - return intersection.iterator().next().getName(); + return intersection.iterator().next(); } else { System.out.println(String.format("WARNING: Unable to choose outer class for %s among options: %s", classEntry, callerClasses)); } @@ -448,7 +455,7 @@ public class JarIndex { return true; } - private BehaviorEntry isAnonymousClass(CtClass c, String outerClassName) { + private BehaviorEntry isAnonymousClass(CtClass c, ClassEntry outerClassEntry) { ClassEntry innerClassEntry = new ClassEntry(Descriptor.toJvmName(c.getName())); @@ -669,23 +676,19 @@ public class JarIndex { return behaviorEntries; } - public Collection getInnerClasses(String obfOuterClassName) { - return m_innerClasses.get(obfOuterClassName); + public Collection getInnerClasses(ClassEntry obfOuterClassEntry) { + return m_innerClassesByOuter.get(obfOuterClassEntry); } - public String getOuterClass(String obfInnerClassName) { - // make sure we use the right name - if (new ClassEntry(obfInnerClassName).getPackageName() != null) { - throw new IllegalArgumentException("Don't reference obfuscated inner classes using packages: " + obfInnerClassName); - } - return m_outerClasses.get(obfInnerClassName); + public ClassEntry getOuterClass(ClassEntry obfInnerClassEntry) { + return m_outerClassesByInner.get(obfInnerClassEntry); } - public boolean isAnonymousClass(String obfInnerClassName) { - return m_anonymousClasses.containsKey(obfInnerClassName); + public boolean isAnonymousClass(ClassEntry obfInnerClassEntry) { + return m_anonymousClasses.containsKey(obfInnerClassEntry); } - public BehaviorEntry getAnonymousClassCaller(String obfInnerClassName) { + public BehaviorEntry getAnonymousClassCaller(ClassEntry obfInnerClassName) { return m_anonymousClasses.get(obfInnerClassName); } -- cgit v1.2.3