From be22b07ae28cd8de11e3a32c3766aed6966ec6b5 Mon Sep 17 00:00:00 2001
From: asie
Date: Wed, 7 Nov 2018 20:18:50 +0100
Subject: update Guava, show proper constructor tree node, fix
AccessFlags.toString
---
build.gradle | 2 +-
.../enigma/analysis/ClassReferenceTreeNode.java | 96 ++++++++++++++++++++++
src/main/java/cuchaz/enigma/analysis/JarIndex.java | 13 ++-
.../java/cuchaz/enigma/bytecode/AccessFlags.java | 27 +++++-
.../translators/TranslationClassVisitor.java | 2 +-
src/main/java/cuchaz/enigma/gui/Gui.java | 4 +-
src/main/java/cuchaz/enigma/gui/GuiController.java | 7 ++
7 files changed, 144 insertions(+), 7 deletions(-)
create mode 100644 src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java
diff --git a/build.gradle b/build.gradle
index c9054256..896534d5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -64,7 +64,7 @@ configurations {
}
dependencies {
- compile 'com.google.guava:guava:23.+'
+ compile 'com.google.guava:guava:27.0-jre'
compile 'org.bitbucket.mstrobel:procyon-compilertools:0.5.33.8-enigma'
compile 'com.google.code.gson:gson:2.8.5'
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 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Jeff Martin.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Lesser General Public
+ * License v3.0 which accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Contributors:
+ * Jeff Martin - initial API and implementation
+ ******************************************************************************/
+
+package cuchaz.enigma.analysis;
+
+import com.google.common.collect.Sets;
+import cuchaz.enigma.bytecode.AccessFlags;
+import cuchaz.enigma.mapping.Translator;
+import cuchaz.enigma.mapping.entry.ClassEntry;
+import cuchaz.enigma.mapping.entry.Entry;
+import cuchaz.enigma.mapping.entry.MethodDefEntry;
+import cuchaz.enigma.mapping.entry.MethodEntry;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.util.Set;
+
+public class ClassReferenceTreeNode extends DefaultMutableTreeNode
+ implements ReferenceTreeNode {
+
+ private Translator deobfuscatingTranslator;
+ private ClassEntry entry;
+ private EntryReference reference;
+ private AccessFlags access;
+
+ public ClassReferenceTreeNode(Translator deobfuscatingTranslator, ClassEntry entry) {
+ this.deobfuscatingTranslator = deobfuscatingTranslator;
+ this.entry = entry;
+ this.reference = null;
+ }
+
+ public ClassReferenceTreeNode(Translator deobfuscatingTranslator,
+ EntryReference reference, AccessFlags access) {
+ this.deobfuscatingTranslator = deobfuscatingTranslator;
+ this.entry = reference.entry;
+ this.reference = reference;
+ this.access = access;
+ }
+
+ @Override
+ public ClassEntry getEntry() {
+ return this.entry;
+ }
+
+ @Override
+ public EntryReference getReference() {
+ return this.reference;
+ }
+
+ @Override
+ public String toString() {
+ if (this.reference != null) {
+ return String.format("%s (%s)", this.deobfuscatingTranslator.getTranslatedMethodDef(this.reference.context),
+ this.access);
+ }
+ return this.deobfuscatingTranslator.getTranslatedClass(this.entry).getName();
+ }
+
+ public void load(JarIndex index, boolean recurse) {
+ // get all the child nodes
+ for (EntryReference reference : index.getMethodsReferencing(this.entry)) {
+ add(new ClassReferenceTreeNode(this.deobfuscatingTranslator, reference, index.getAccessFlags(this.entry)));
+ }
+
+ if (recurse && this.children != null) {
+ for (Object child : this.children) {
+ if (child instanceof ClassReferenceTreeNode) {
+ ClassReferenceTreeNode node = (ClassReferenceTreeNode) child;
+
+ // don't recurse into ancestor
+ Set ancestors = Sets.newHashSet();
+ TreeNode n = node;
+ while (n.getParent() != null) {
+ n = n.getParent();
+ if (n instanceof ClassReferenceTreeNode) {
+ ancestors.add(((ClassReferenceTreeNode) n).getEntry());
+ }
+ }
+ if (ancestors.contains(node.getEntry())) {
+ continue;
+ }
+
+ node.load(index, true);
+ }
+ }
+ }
+ }
+}
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 {
private Multimap methods;
private Multimap methodImplementations;
private Multimap> methodsReferencing;
+ private Multimap> methodsReferencingClasses;
private Multimap methodReferences;
private Multimap> fieldReferences;
private Multimap innerClassesByOuter;
@@ -45,6 +46,7 @@ public class JarIndex {
this.fields = HashMultimap.create();
this.methods = HashMultimap.create();
this.methodImplementations = HashMultimap.create();
+ this.methodsReferencingClasses = HashMultimap.create();
this.methodsReferencing = HashMultimap.create();
this.methodReferences = HashMultimap.create();
this.fieldReferences = HashMultimap.create();
@@ -93,6 +95,7 @@ public class JarIndex {
EntryRenamer.renameClassesInSet(renames, this.obfClassEntries);
this.translationIndex.renameClasses(renames);
EntryRenamer.renameClassesInMultimap(renames, this.methodImplementations);
+ EntryRenamer.renameClassesInMultimap(renames, this.methodsReferencingClasses);
EntryRenamer.renameClassesInMultimap(renames, this.methodsReferencing);
EntryRenamer.renameClassesInMultimap(renames, this.methodReferences);
EntryRenamer.renameClassesInMultimap(renames, this.fieldReferences);
@@ -136,12 +139,16 @@ public class JarIndex {
}
protected void indexMethodCall(MethodDefEntry callerEntry, String owner, String name, String desc) {
- MethodEntry referencedMethod = new MethodEntry(entryPool.getClass(owner), name, new MethodDescriptor(desc));
+ ClassEntry referencedClass = entryPool.getClass(owner);
+ MethodEntry referencedMethod = new MethodEntry(referencedClass, name, new MethodDescriptor(desc));
ClassEntry resolvedClassEntry = translationIndex.resolveEntryOwner(referencedMethod);
if (resolvedClassEntry != null && !resolvedClassEntry.equals(referencedMethod.getOwnerClassEntry())) {
referencedMethod = referencedMethod.updateOwnership(resolvedClassEntry);
}
methodsReferencing.put(referencedMethod, new EntryReference<>(referencedMethod, referencedMethod.getName(), callerEntry));
+ if (referencedMethod.isConstructor()) {
+ methodsReferencingClasses.put(referencedClass, new EntryReference<>(referencedClass, referencedMethod.getName(), callerEntry));
+ }
methodReferences.put(callerEntry, referencedMethod);
}
@@ -421,6 +428,10 @@ public class JarIndex {
return fieldEntries;
}
+ public Collection> getMethodsReferencing(ClassEntry classEntry) {
+ return this.methodsReferencingClasses.get(classEntry);
+ }
+
public Collection> getMethodsReferencing(MethodEntry methodEntry) {
return this.methodsReferencing.get(methodEntry);
}
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 @@
package cuchaz.enigma.bytecode;
+import cuchaz.enigma.analysis.Access;
import org.objectweb.asm.Opcodes;
import java.lang.reflect.Modifier;
@@ -35,6 +36,10 @@ public class AccessFlags {
return (flags & Opcodes.ACC_ENUM) != 0;
}
+ public boolean isBridge() {
+ return (flags & Opcodes.ACC_BRIDGE) != 0;
+ }
+
public AccessFlags setPrivate() {
this.setVisibility(Opcodes.ACC_PRIVATE);
return this;
@@ -50,11 +55,16 @@ public class AccessFlags {
return this;
}
- public AccessFlags setBridged() {
+ public AccessFlags setBridge() {
flags |= Opcodes.ACC_BRIDGE;
return this;
}
+ @Deprecated
+ public AccessFlags setBridged() {
+ return setBridge();
+ }
+
public void setVisibility(int visibility) {
this.resetVisibility();
this.flags |= visibility;
@@ -77,4 +87,19 @@ public class AccessFlags {
public int hashCode() {
return flags;
}
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder(Access.get(this).toString().toLowerCase());
+ if (isStatic()) {
+ builder.append(" static");
+ }
+ if (isSynthetic()) {
+ builder.append(" synthetic");
+ }
+ if (isBridge()) {
+ builder.append(" bridge");
+ }
+ return builder.toString();
+ }
}
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 {
MethodDefEntry entry = new MethodDefEntry(obfClassEntry, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access));
MethodDefEntry translatedEntry = translator.getTranslatedMethodDef(entry);
if (jarIndex.getBridgedMethod(entry) != null) {
- translatedEntry.getAccess().setBridged();
+ translatedEntry.getAccess().setBridge();
}
String[] translatedExceptions = new String[exceptions.length];
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 {
}
if (reference.entry instanceof ClassEntry) {
- // look for calls to the default constructor
- // TODO: get a list of all the constructors and find calls to all of them
- MethodReferenceTreeNode node = this.controller.getMethodReferences(new MethodEntry((ClassEntry) reference.entry, "", new MethodDescriptor("()V")));
+ ClassReferenceTreeNode node = this.controller.getClassReferences((ClassEntry) reference.entry);
callsTree.setModel(new DefaultTreeModel(node));
} else if (reference.entry instanceof FieldEntry) {
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 {
return MethodImplementationsTreeNode.findNode(rootNodes.get(0), obfMethodEntry);
}
+ public ClassReferenceTreeNode getClassReferences(ClassEntry deobfClassEntry) {
+ ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry);
+ ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry);
+ rootNode.load(this.deobfuscator.getJarIndex(), true);
+ return rootNode;
+ }
+
public FieldReferenceTreeNode getFieldReferences(FieldEntry deobfFieldEntry) {
FieldEntry obfFieldEntry = this.deobfuscator.obfuscateEntry(deobfFieldEntry);
FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfFieldEntry);
--
cgit v1.2.3