diff options
| author | 2018-11-07 20:18:50 +0100 | |
|---|---|---|
| committer | 2018-11-07 20:18:50 +0100 | |
| commit | be22b07ae28cd8de11e3a32c3766aed6966ec6b5 (patch) | |
| tree | 97f8db1c2bcb129fe4af262bf3df959dd8f97711 /src | |
| parent | unify local variable/argument numbering (diff) | |
| download | enigma-be22b07ae28cd8de11e3a32c3766aed6966ec6b5.tar.gz enigma-be22b07ae28cd8de11e3a32c3766aed6966ec6b5.tar.xz enigma-be22b07ae28cd8de11e3a32c3766aed6966ec6b5.zip | |
update Guava, show proper constructor tree node, fix AccessFlags.toString
Diffstat (limited to 'src')
6 files changed, 143 insertions, 6 deletions
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 | |||
| 12 | package cuchaz.enigma.analysis; | ||
| 13 | |||
| 14 | import com.google.common.collect.Sets; | ||
| 15 | import cuchaz.enigma.bytecode.AccessFlags; | ||
| 16 | import cuchaz.enigma.mapping.Translator; | ||
| 17 | import cuchaz.enigma.mapping.entry.ClassEntry; | ||
| 18 | import cuchaz.enigma.mapping.entry.Entry; | ||
| 19 | import cuchaz.enigma.mapping.entry.MethodDefEntry; | ||
| 20 | import cuchaz.enigma.mapping.entry.MethodEntry; | ||
| 21 | |||
| 22 | import javax.swing.tree.DefaultMutableTreeNode; | ||
| 23 | import javax.swing.tree.TreeNode; | ||
| 24 | import java.util.Set; | ||
| 25 | |||
| 26 | public 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 @@ | |||
| 1 | package cuchaz.enigma.bytecode; | 1 | package cuchaz.enigma.bytecode; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.analysis.Access; | ||
| 3 | import org.objectweb.asm.Opcodes; | 4 | import org.objectweb.asm.Opcodes; |
| 4 | 5 | ||
| 5 | import java.lang.reflect.Modifier; | 6 | import 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); |