summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle2
-rw-r--r--src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java96
-rw-r--r--src/main/java/cuchaz/enigma/analysis/JarIndex.java13
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/AccessFlags.java27
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java2
-rw-r--r--src/main/java/cuchaz/enigma/gui/Gui.java4
-rw-r--r--src/main/java/cuchaz/enigma/gui/GuiController.java7
7 files changed, 144 insertions, 7 deletions
diff --git a/build.gradle b/build.gradle
index c9054256..896534d5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -64,7 +64,7 @@ configurations {
64} 64}
65 65
66dependencies { 66dependencies {
67 compile 'com.google.guava:guava:23.+' 67 compile 'com.google.guava:guava:27.0-jre'
68 compile 'org.bitbucket.mstrobel:procyon-compilertools:0.5.33.8-enigma' 68 compile 'org.bitbucket.mstrobel:procyon-compilertools:0.5.33.8-enigma'
69 compile 'com.google.code.gson:gson:2.8.5' 69 compile 'com.google.code.gson:gson:2.8.5'
70 compile 'org.ow2.asm:asm:7.0' 70 compile 'org.ow2.asm:asm:7.0'
diff --git a/src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java b/src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java
new file mode 100644
index 00000000..ff5f2e9a
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java
@@ -0,0 +1,96 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.analysis;
13
14import com.google.common.collect.Sets;
15import cuchaz.enigma.bytecode.AccessFlags;
16import cuchaz.enigma.mapping.Translator;
17import cuchaz.enigma.mapping.entry.ClassEntry;
18import cuchaz.enigma.mapping.entry.Entry;
19import cuchaz.enigma.mapping.entry.MethodDefEntry;
20import cuchaz.enigma.mapping.entry.MethodEntry;
21
22import javax.swing.tree.DefaultMutableTreeNode;
23import javax.swing.tree.TreeNode;
24import java.util.Set;
25
26public class ClassReferenceTreeNode extends DefaultMutableTreeNode
27 implements ReferenceTreeNode<ClassEntry, MethodDefEntry> {
28
29 private Translator deobfuscatingTranslator;
30 private ClassEntry entry;
31 private EntryReference<ClassEntry, MethodDefEntry> reference;
32 private AccessFlags access;
33
34 public ClassReferenceTreeNode(Translator deobfuscatingTranslator, ClassEntry entry) {
35 this.deobfuscatingTranslator = deobfuscatingTranslator;
36 this.entry = entry;
37 this.reference = null;
38 }
39
40 public ClassReferenceTreeNode(Translator deobfuscatingTranslator,
41 EntryReference<ClassEntry, MethodDefEntry> reference, AccessFlags access) {
42 this.deobfuscatingTranslator = deobfuscatingTranslator;
43 this.entry = reference.entry;
44 this.reference = reference;
45 this.access = access;
46 }
47
48 @Override
49 public ClassEntry getEntry() {
50 return this.entry;
51 }
52
53 @Override
54 public EntryReference<ClassEntry, MethodDefEntry> getReference() {
55 return this.reference;
56 }
57
58 @Override
59 public String toString() {
60 if (this.reference != null) {
61 return String.format("%s (%s)", this.deobfuscatingTranslator.getTranslatedMethodDef(this.reference.context),
62 this.access);
63 }
64 return this.deobfuscatingTranslator.getTranslatedClass(this.entry).getName();
65 }
66
67 public void load(JarIndex index, boolean recurse) {
68 // get all the child nodes
69 for (EntryReference<ClassEntry, MethodDefEntry> reference : index.getMethodsReferencing(this.entry)) {
70 add(new ClassReferenceTreeNode(this.deobfuscatingTranslator, reference, index.getAccessFlags(this.entry)));
71 }
72
73 if (recurse && this.children != null) {
74 for (Object child : this.children) {
75 if (child instanceof ClassReferenceTreeNode) {
76 ClassReferenceTreeNode node = (ClassReferenceTreeNode) child;
77
78 // don't recurse into ancestor
79 Set<Entry> ancestors = Sets.newHashSet();
80 TreeNode n = node;
81 while (n.getParent() != null) {
82 n = n.getParent();
83 if (n instanceof ClassReferenceTreeNode) {
84 ancestors.add(((ClassReferenceTreeNode) n).getEntry());
85 }
86 }
87 if (ancestors.contains(node.getEntry())) {
88 continue;
89 }
90
91 node.load(index, true);
92 }
93 }
94 }
95 }
96}
diff --git a/src/main/java/cuchaz/enigma/analysis/JarIndex.java b/src/main/java/cuchaz/enigma/analysis/JarIndex.java
index f6338a27..158df4b5 100644
--- a/src/main/java/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/JarIndex.java
@@ -30,6 +30,7 @@ public class JarIndex {
30 private Multimap<ClassEntry, MethodDefEntry> methods; 30 private Multimap<ClassEntry, MethodDefEntry> methods;
31 private Multimap<String, MethodDefEntry> methodImplementations; 31 private Multimap<String, MethodDefEntry> methodImplementations;
32 private Multimap<MethodEntry, EntryReference<MethodEntry, MethodDefEntry>> methodsReferencing; 32 private Multimap<MethodEntry, EntryReference<MethodEntry, MethodDefEntry>> methodsReferencing;
33 private Multimap<ClassEntry, EntryReference<ClassEntry, MethodDefEntry>> methodsReferencingClasses;
33 private Multimap<MethodEntry, MethodEntry> methodReferences; 34 private Multimap<MethodEntry, MethodEntry> methodReferences;
34 private Multimap<FieldEntry, EntryReference<FieldEntry, MethodDefEntry>> fieldReferences; 35 private Multimap<FieldEntry, EntryReference<FieldEntry, MethodDefEntry>> fieldReferences;
35 private Multimap<ClassEntry, ClassEntry> innerClassesByOuter; 36 private Multimap<ClassEntry, ClassEntry> innerClassesByOuter;
@@ -45,6 +46,7 @@ public class JarIndex {
45 this.fields = HashMultimap.create(); 46 this.fields = HashMultimap.create();
46 this.methods = HashMultimap.create(); 47 this.methods = HashMultimap.create();
47 this.methodImplementations = HashMultimap.create(); 48 this.methodImplementations = HashMultimap.create();
49 this.methodsReferencingClasses = HashMultimap.create();
48 this.methodsReferencing = HashMultimap.create(); 50 this.methodsReferencing = HashMultimap.create();
49 this.methodReferences = HashMultimap.create(); 51 this.methodReferences = HashMultimap.create();
50 this.fieldReferences = HashMultimap.create(); 52 this.fieldReferences = HashMultimap.create();
@@ -93,6 +95,7 @@ public class JarIndex {
93 EntryRenamer.renameClassesInSet(renames, this.obfClassEntries); 95 EntryRenamer.renameClassesInSet(renames, this.obfClassEntries);
94 this.translationIndex.renameClasses(renames); 96 this.translationIndex.renameClasses(renames);
95 EntryRenamer.renameClassesInMultimap(renames, this.methodImplementations); 97 EntryRenamer.renameClassesInMultimap(renames, this.methodImplementations);
98 EntryRenamer.renameClassesInMultimap(renames, this.methodsReferencingClasses);
96 EntryRenamer.renameClassesInMultimap(renames, this.methodsReferencing); 99 EntryRenamer.renameClassesInMultimap(renames, this.methodsReferencing);
97 EntryRenamer.renameClassesInMultimap(renames, this.methodReferences); 100 EntryRenamer.renameClassesInMultimap(renames, this.methodReferences);
98 EntryRenamer.renameClassesInMultimap(renames, this.fieldReferences); 101 EntryRenamer.renameClassesInMultimap(renames, this.fieldReferences);
@@ -136,12 +139,16 @@ public class JarIndex {
136 } 139 }
137 140
138 protected void indexMethodCall(MethodDefEntry callerEntry, String owner, String name, String desc) { 141 protected void indexMethodCall(MethodDefEntry callerEntry, String owner, String name, String desc) {
139 MethodEntry referencedMethod = new MethodEntry(entryPool.getClass(owner), name, new MethodDescriptor(desc)); 142 ClassEntry referencedClass = entryPool.getClass(owner);
143 MethodEntry referencedMethod = new MethodEntry(referencedClass, name, new MethodDescriptor(desc));
140 ClassEntry resolvedClassEntry = translationIndex.resolveEntryOwner(referencedMethod); 144 ClassEntry resolvedClassEntry = translationIndex.resolveEntryOwner(referencedMethod);
141 if (resolvedClassEntry != null && !resolvedClassEntry.equals(referencedMethod.getOwnerClassEntry())) { 145 if (resolvedClassEntry != null && !resolvedClassEntry.equals(referencedMethod.getOwnerClassEntry())) {
142 referencedMethod = referencedMethod.updateOwnership(resolvedClassEntry); 146 referencedMethod = referencedMethod.updateOwnership(resolvedClassEntry);
143 } 147 }
144 methodsReferencing.put(referencedMethod, new EntryReference<>(referencedMethod, referencedMethod.getName(), callerEntry)); 148 methodsReferencing.put(referencedMethod, new EntryReference<>(referencedMethod, referencedMethod.getName(), callerEntry));
149 if (referencedMethod.isConstructor()) {
150 methodsReferencingClasses.put(referencedClass, new EntryReference<>(referencedClass, referencedMethod.getName(), callerEntry));
151 }
145 methodReferences.put(callerEntry, referencedMethod); 152 methodReferences.put(callerEntry, referencedMethod);
146 } 153 }
147 154
@@ -421,6 +428,10 @@ public class JarIndex {
421 return fieldEntries; 428 return fieldEntries;
422 } 429 }
423 430
431 public Collection<EntryReference<ClassEntry, MethodDefEntry>> getMethodsReferencing(ClassEntry classEntry) {
432 return this.methodsReferencingClasses.get(classEntry);
433 }
434
424 public Collection<EntryReference<MethodEntry, MethodDefEntry>> getMethodsReferencing(MethodEntry methodEntry) { 435 public Collection<EntryReference<MethodEntry, MethodDefEntry>> getMethodsReferencing(MethodEntry methodEntry) {
425 return this.methodsReferencing.get(methodEntry); 436 return this.methodsReferencing.get(methodEntry);
426 } 437 }
diff --git a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
index 0bfc59bd..31c86918 100644
--- a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
+++ b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
@@ -1,5 +1,6 @@
1package cuchaz.enigma.bytecode; 1package cuchaz.enigma.bytecode;
2 2
3import cuchaz.enigma.analysis.Access;
3import org.objectweb.asm.Opcodes; 4import org.objectweb.asm.Opcodes;
4 5
5import java.lang.reflect.Modifier; 6import java.lang.reflect.Modifier;
@@ -35,6 +36,10 @@ public class AccessFlags {
35 return (flags & Opcodes.ACC_ENUM) != 0; 36 return (flags & Opcodes.ACC_ENUM) != 0;
36 } 37 }
37 38
39 public boolean isBridge() {
40 return (flags & Opcodes.ACC_BRIDGE) != 0;
41 }
42
38 public AccessFlags setPrivate() { 43 public AccessFlags setPrivate() {
39 this.setVisibility(Opcodes.ACC_PRIVATE); 44 this.setVisibility(Opcodes.ACC_PRIVATE);
40 return this; 45 return this;
@@ -50,11 +55,16 @@ public class AccessFlags {
50 return this; 55 return this;
51 } 56 }
52 57
53 public AccessFlags setBridged() { 58 public AccessFlags setBridge() {
54 flags |= Opcodes.ACC_BRIDGE; 59 flags |= Opcodes.ACC_BRIDGE;
55 return this; 60 return this;
56 } 61 }
57 62
63 @Deprecated
64 public AccessFlags setBridged() {
65 return setBridge();
66 }
67
58 public void setVisibility(int visibility) { 68 public void setVisibility(int visibility) {
59 this.resetVisibility(); 69 this.resetVisibility();
60 this.flags |= visibility; 70 this.flags |= visibility;
@@ -77,4 +87,19 @@ public class AccessFlags {
77 public int hashCode() { 87 public int hashCode() {
78 return flags; 88 return flags;
79 } 89 }
90
91 @Override
92 public String toString() {
93 StringBuilder builder = new StringBuilder(Access.get(this).toString().toLowerCase());
94 if (isStatic()) {
95 builder.append(" static");
96 }
97 if (isSynthetic()) {
98 builder.append(" synthetic");
99 }
100 if (isBridge()) {
101 builder.append(" bridge");
102 }
103 return builder.toString();
104 }
80} 105}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
index 234d11f3..5b16138e 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java
@@ -61,7 +61,7 @@ public class TranslationClassVisitor extends ClassVisitor {
61 MethodDefEntry entry = new MethodDefEntry(obfClassEntry, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access)); 61 MethodDefEntry entry = new MethodDefEntry(obfClassEntry, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access));
62 MethodDefEntry translatedEntry = translator.getTranslatedMethodDef(entry); 62 MethodDefEntry translatedEntry = translator.getTranslatedMethodDef(entry);
63 if (jarIndex.getBridgedMethod(entry) != null) { 63 if (jarIndex.getBridgedMethod(entry) != null) {
64 translatedEntry.getAccess().setBridged(); 64 translatedEntry.getAccess().setBridge();
65 } 65 }
66 String[] translatedExceptions = new String[exceptions.length]; 66 String[] translatedExceptions = new String[exceptions.length];
67 for (int i = 0; i < exceptions.length; i++) { 67 for (int i = 0; i < exceptions.length; i++) {
diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java
index cfac8ad8..1fc8bf34 100644
--- a/src/main/java/cuchaz/enigma/gui/Gui.java
+++ b/src/main/java/cuchaz/enigma/gui/Gui.java
@@ -693,9 +693,7 @@ public class Gui {
693 } 693 }
694 694
695 if (reference.entry instanceof ClassEntry) { 695 if (reference.entry instanceof ClassEntry) {
696 // look for calls to the default constructor 696 ClassReferenceTreeNode node = this.controller.getClassReferences((ClassEntry) reference.entry);
697 // TODO: get a list of all the constructors and find calls to all of them
698 MethodReferenceTreeNode node = this.controller.getMethodReferences(new MethodEntry((ClassEntry) reference.entry, "<init>", new MethodDescriptor("()V")));
699 callsTree.setModel(new DefaultTreeModel(node)); 697 callsTree.setModel(new DefaultTreeModel(node));
700 } else if (reference.entry instanceof FieldEntry) { 698 } else if (reference.entry instanceof FieldEntry) {
701 FieldReferenceTreeNode node = this.controller.getFieldReferences((FieldEntry) reference.entry); 699 FieldReferenceTreeNode node = this.controller.getFieldReferences((FieldEntry) reference.entry);
diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java
index ae1b6528..653f0244 100644
--- a/src/main/java/cuchaz/enigma/gui/GuiController.java
+++ b/src/main/java/cuchaz/enigma/gui/GuiController.java
@@ -192,6 +192,13 @@ public class GuiController {
192 return MethodImplementationsTreeNode.findNode(rootNodes.get(0), obfMethodEntry); 192 return MethodImplementationsTreeNode.findNode(rootNodes.get(0), obfMethodEntry);
193 } 193 }
194 194
195 public ClassReferenceTreeNode getClassReferences(ClassEntry deobfClassEntry) {
196 ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry);
197 ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry);
198 rootNode.load(this.deobfuscator.getJarIndex(), true);
199 return rootNode;
200 }
201
195 public FieldReferenceTreeNode getFieldReferences(FieldEntry deobfFieldEntry) { 202 public FieldReferenceTreeNode getFieldReferences(FieldEntry deobfFieldEntry) {
196 FieldEntry obfFieldEntry = this.deobfuscator.obfuscateEntry(deobfFieldEntry); 203 FieldEntry obfFieldEntry = this.deobfuscator.obfuscateEntry(deobfFieldEntry);
197 FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfFieldEntry); 204 FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfFieldEntry);