summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/JarIndex.java
diff options
context:
space:
mode:
authorGravatar jeff2015-02-23 23:29:22 -0500
committerGravatar jeff2015-02-23 23:29:22 -0500
commit2dc7428e37bdd7a119f53d02ce157675509b0d63 (patch)
tree68f409ac726166e427eea3a199eb462130c53ccd /src/cuchaz/enigma/analysis/JarIndex.java
parentmake types serializable (diff)
downloadenigma-fork-2dc7428e37bdd7a119f53d02ce157675509b0d63.tar.gz
enigma-fork-2dc7428e37bdd7a119f53d02ce157675509b0d63.tar.xz
enigma-fork-2dc7428e37bdd7a119f53d02ce157675509b0d63.zip
lots of work in better handling of inner classes
also working on recognizing unobfuscated and deobfuscated jars (needed for M3L)
Diffstat (limited to 'src/cuchaz/enigma/analysis/JarIndex.java')
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java67
1 files changed, 35 insertions, 32 deletions
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 {
61 private Multimap<String,MethodEntry> m_methodImplementations; 61 private Multimap<String,MethodEntry> m_methodImplementations;
62 private Multimap<BehaviorEntry,EntryReference<BehaviorEntry,BehaviorEntry>> m_behaviorReferences; 62 private Multimap<BehaviorEntry,EntryReference<BehaviorEntry,BehaviorEntry>> m_behaviorReferences;
63 private Multimap<FieldEntry,EntryReference<FieldEntry,BehaviorEntry>> m_fieldReferences; 63 private Multimap<FieldEntry,EntryReference<FieldEntry,BehaviorEntry>> m_fieldReferences;
64 private Multimap<String,String> m_innerClasses; 64 private Multimap<ClassEntry,ClassEntry> m_innerClassesByOuter;
65 private Map<String,String> m_outerClasses; 65 private Map<ClassEntry,ClassEntry> m_outerClassesByInner;
66 private Map<String,BehaviorEntry> m_anonymousClasses; 66 private Map<ClassEntry,BehaviorEntry> m_anonymousClasses;
67 private Map<MethodEntry,MethodEntry> m_bridgedMethods; 67 private Map<MethodEntry,MethodEntry> m_bridgedMethods;
68 68
69 public JarIndex() { 69 public JarIndex() {
@@ -74,8 +74,8 @@ public class JarIndex {
74 m_methodImplementations = HashMultimap.create(); 74 m_methodImplementations = HashMultimap.create();
75 m_behaviorReferences = HashMultimap.create(); 75 m_behaviorReferences = HashMultimap.create();
76 m_fieldReferences = HashMultimap.create(); 76 m_fieldReferences = HashMultimap.create();
77 m_innerClasses = HashMultimap.create(); 77 m_innerClassesByOuter = HashMultimap.create();
78 m_outerClasses = Maps.newHashMap(); 78 m_outerClassesByInner = Maps.newHashMap();
79 m_anonymousClasses = Maps.newHashMap(); 79 m_anonymousClasses = Maps.newHashMap();
80 m_bridgedMethods = Maps.newHashMap(); 80 m_bridgedMethods = Maps.newHashMap();
81 } 81 }
@@ -129,33 +129,40 @@ public class JarIndex {
129 } 129 }
130 130
131 if (buildInnerClasses) { 131 if (buildInnerClasses) {
132
132 // step 5: index inner classes and anonymous classes 133 // step 5: index inner classes and anonymous classes
133 for (CtClass c : JarClassIterator.classes(jar)) { 134 for (CtClass c : JarClassIterator.classes(jar)) {
134 ClassRenamer.moveAllClassesOutOfDefaultPackage(c, Constants.NonePackage); 135 ClassRenamer.moveAllClassesOutOfDefaultPackage(c, Constants.NonePackage);
135 String outerClassName = findOuterClass(c); 136 ClassEntry innerClassEntry = EntryFactory.getClassEntry(c);
136 if (outerClassName != null) { 137 ClassEntry outerClassEntry = findOuterClass(c);
137 String innerClassName = c.getSimpleName(); 138 if (outerClassEntry != null) {
138 m_innerClasses.put(outerClassName, innerClassName); 139 m_innerClassesByOuter.put(outerClassEntry, innerClassEntry);
139 boolean innerWasAdded = m_outerClasses.put(innerClassName, outerClassName) == null; 140 boolean innerWasAdded = m_outerClassesByInner.put(innerClassEntry, outerClassEntry) == null;
140 assert (innerWasAdded); 141 assert (innerWasAdded);
141 142
142 BehaviorEntry enclosingBehavior = isAnonymousClass(c, outerClassName); 143 BehaviorEntry enclosingBehavior = isAnonymousClass(c, outerClassEntry);
143 if (enclosingBehavior != null) { 144 if (enclosingBehavior != null) {
144 m_anonymousClasses.put(innerClassName, enclosingBehavior); 145 m_anonymousClasses.put(innerClassEntry, enclosingBehavior);
145 146
146 // DEBUG 147 // DEBUG
147 // System.out.println( "ANONYMOUS: " + outerClassName + "$" + innerClassName ); 148 //System.out.println("ANONYMOUS: " + outerClassEntry.getName() + "$" + innerClassEntry.getSimpleName());
148 } else { 149 } else {
149 // DEBUG 150 // DEBUG
150 // System.out.println( "INNER: " + outerClassName + "$" + innerClassName ); 151 //System.out.println("INNER: " + outerClassEntry.getName() + "$" + innerClassEntry.getSimpleName());
151 } 152 }
152 } 153 }
153 } 154 }
154 155
155 // step 6: update other indices with inner class info 156 // step 6: update other indices with inner class info
156 Map<String,String> renames = Maps.newHashMap(); 157 Map<String,String> renames = Maps.newHashMap();
157 for (Map.Entry<String,String> entry : m_outerClasses.entrySet()) { 158 for (Map.Entry<ClassEntry,ClassEntry> mapEntry : m_innerClassesByOuter.entries()) {
158 renames.put(Constants.NonePackage + "/" + entry.getKey(), entry.getValue() + "$" + entry.getKey()); 159 ClassEntry outerClassEntry = mapEntry.getKey();
160 ClassEntry innerClassEntry = mapEntry.getValue();
161 outerClassEntry = EntryFactory.getChainedOuterClassName(this, outerClassEntry);
162 String newName = outerClassEntry.getName() + "$" + innerClassEntry.getSimpleName();
163 // DEBUG
164 //System.out.println("REPLACE: " + innerClassEntry.getName() + " WITH " + newName);
165 renames.put(innerClassEntry.getName(), newName);
159 } 166 }
160 EntryRenamer.renameClassesInSet(renames, m_obfClassEntries); 167 EntryRenamer.renameClassesInSet(renames, m_obfClassEntries);
161 m_translationIndex.renameClasses(renames); 168 m_translationIndex.renameClasses(renames);
@@ -290,7 +297,7 @@ public class JarIndex {
290 } 297 }
291 } 298 }
292 299
293 private String findOuterClass(CtClass c) { 300 private ClassEntry findOuterClass(CtClass c) {
294 301
295 // inner classes: 302 // inner classes:
296 // have constructors that can (illegally) set synthetic fields 303 // have constructors that can (illegally) set synthetic fields
@@ -341,19 +348,19 @@ public class JarIndex {
341 // do we have an answer yet? 348 // do we have an answer yet?
342 if (callerClasses.isEmpty()) { 349 if (callerClasses.isEmpty()) {
343 if (illegallySetClasses.size() == 1) { 350 if (illegallySetClasses.size() == 1) {
344 return illegallySetClasses.iterator().next().getName(); 351 return illegallySetClasses.iterator().next();
345 } else { 352 } else {
346 System.out.println(String.format("WARNING: Unable to find outer class for %s. No caller and no illegally set field classes.", classEntry)); 353 System.out.println(String.format("WARNING: Unable to find outer class for %s. No caller and no illegally set field classes.", classEntry));
347 } 354 }
348 } else { 355 } else {
349 if (callerClasses.size() == 1) { 356 if (callerClasses.size() == 1) {
350 return callerClasses.iterator().next().getName(); 357 return callerClasses.iterator().next();
351 } else { 358 } else {
352 // multiple callers, do the illegally set classes narrow it down? 359 // multiple callers, do the illegally set classes narrow it down?
353 Set<ClassEntry> intersection = Sets.newHashSet(callerClasses); 360 Set<ClassEntry> intersection = Sets.newHashSet(callerClasses);
354 intersection.retainAll(illegallySetClasses); 361 intersection.retainAll(illegallySetClasses);
355 if (intersection.size() == 1) { 362 if (intersection.size() == 1) {
356 return intersection.iterator().next().getName(); 363 return intersection.iterator().next();
357 } else { 364 } else {
358 System.out.println(String.format("WARNING: Unable to choose outer class for %s among options: %s", classEntry, callerClasses)); 365 System.out.println(String.format("WARNING: Unable to choose outer class for %s among options: %s", classEntry, callerClasses));
359 } 366 }
@@ -448,7 +455,7 @@ public class JarIndex {
448 return true; 455 return true;
449 } 456 }
450 457
451 private BehaviorEntry isAnonymousClass(CtClass c, String outerClassName) { 458 private BehaviorEntry isAnonymousClass(CtClass c, ClassEntry outerClassEntry) {
452 459
453 ClassEntry innerClassEntry = new ClassEntry(Descriptor.toJvmName(c.getName())); 460 ClassEntry innerClassEntry = new ClassEntry(Descriptor.toJvmName(c.getName()));
454 461
@@ -669,23 +676,19 @@ public class JarIndex {
669 return behaviorEntries; 676 return behaviorEntries;
670 } 677 }
671 678
672 public Collection<String> getInnerClasses(String obfOuterClassName) { 679 public Collection<ClassEntry> getInnerClasses(ClassEntry obfOuterClassEntry) {
673 return m_innerClasses.get(obfOuterClassName); 680 return m_innerClassesByOuter.get(obfOuterClassEntry);
674 } 681 }
675 682
676 public String getOuterClass(String obfInnerClassName) { 683 public ClassEntry getOuterClass(ClassEntry obfInnerClassEntry) {
677 // make sure we use the right name 684 return m_outerClassesByInner.get(obfInnerClassEntry);
678 if (new ClassEntry(obfInnerClassName).getPackageName() != null) {
679 throw new IllegalArgumentException("Don't reference obfuscated inner classes using packages: " + obfInnerClassName);
680 }
681 return m_outerClasses.get(obfInnerClassName);
682 } 685 }
683 686
684 public boolean isAnonymousClass(String obfInnerClassName) { 687 public boolean isAnonymousClass(ClassEntry obfInnerClassEntry) {
685 return m_anonymousClasses.containsKey(obfInnerClassName); 688 return m_anonymousClasses.containsKey(obfInnerClassEntry);
686 } 689 }
687 690
688 public BehaviorEntry getAnonymousClassCaller(String obfInnerClassName) { 691 public BehaviorEntry getAnonymousClassCaller(ClassEntry obfInnerClassName) {
689 return m_anonymousClasses.get(obfInnerClassName); 692 return m_anonymousClasses.get(obfInnerClassName);
690 } 693 }
691 694