From 2fbcf8e5c4eec0aa4a4fc59c7cc8abac33b1429c Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 19 Jan 2015 22:22:57 -0500 Subject: solved tricky issue with incorrect translation of fields/methods referenced by a subclass instead of the declaring class --- build.py | 79 +++++--- libs/proguard.jar | Bin 0 -> 853203 bytes proguard.conf | 7 + src/cuchaz/enigma/Deobfuscator.java | 8 +- src/cuchaz/enigma/Main.java | 2 +- .../enigma/analysis/ClassInheritanceTreeNode.java | 4 +- src/cuchaz/enigma/analysis/JarIndex.java | 65 ++---- .../enigma/analysis/MethodInheritanceTreeNode.java | 4 +- src/cuchaz/enigma/analysis/TranslationIndex.java | 172 ++++++++++++---- src/cuchaz/enigma/bytecode/ClassTranslator.java | 9 + src/cuchaz/enigma/mapping/JavassistUtil.java | 55 +++++ src/cuchaz/enigma/mapping/Mappings.java | 11 +- src/cuchaz/enigma/mapping/MappingsRenamer.java | 6 +- src/cuchaz/enigma/mapping/Translator.java | 57 ++++-- ssjb.py | 223 +++++++++++---------- test/cuchaz/enigma/TestDeobfuscator.java | 2 +- test/cuchaz/enigma/TestInnerClasses.java | 2 +- .../enigma/TestJarIndexConstructorReferences.java | 2 +- .../cuchaz/enigma/TestJarIndexInheritanceTree.java | 30 +-- test/cuchaz/enigma/TestJarIndexLoneClass.java | 15 +- test/cuchaz/enigma/TestSourceIndex.java | 1 + test/cuchaz/enigma/TestTokensConstructors.java | 2 +- 22 files changed, 472 insertions(+), 284 deletions(-) create mode 100644 libs/proguard.jar create mode 100644 proguard.conf create mode 100644 src/cuchaz/enigma/mapping/JavassistUtil.java diff --git a/build.py b/build.py index 62b96d11..b9d1121f 100644 --- a/build.py +++ b/build.py @@ -19,42 +19,65 @@ def getJarFullName(name=None) : return "%s-%s.jar" % (projectName, version) def buildGuiJar(): - jarName = "gui" - os.makedirs(dirTemp) - ssjb.copyFiles(dirTemp, dirBin, ssjb.findFiles(dirBin)) - ssjb.unpackJars(dirTemp, "ivy/bundles", recursive=True) - ssjb.unpackJars(dirTemp, "ivy/jars", recursive=True) - ssjb.unpackJars(dirTemp, "libs", recursive=True) - ssjb.delete(os.path.join(dirTemp, "LICENSE.txt")) - ssjb.copyFile(dirTemp, "license.APL2.txt") - ssjb.copyFile(dirTemp, "license.GPL3.txt") - ssjb.copyFile(dirTemp, "readme.txt") - manifest = ssjb.buildManifest(projectName, version, author, "cuchaz.enigma.Main") - ssjb.jar(os.path.join(dirBuild, getJarFullName()), dirTemp, manifest=manifest) - ssjb.delete(dirTemp) + jarName = "gui" + os.makedirs(dirTemp) + ssjb.copyFiles(dirTemp, dirBin, ssjb.findFiles(dirBin)) + ssjb.unpackJars(dirTemp, "ivy/bundles", recursive=True) + ssjb.unpackJars(dirTemp, "ivy/jars", recursive=True) + ssjb.unpackJars(dirTemp, "libs", recursive=True) + ssjb.delete(os.path.join(dirTemp, "LICENSE.txt")) + ssjb.copyFile(dirTemp, "license.APL2.txt") + ssjb.copyFile(dirTemp, "license.GPL3.txt") + ssjb.copyFile(dirTemp, "readme.txt") + manifest = ssjb.buildManifest(projectName, version, author, "cuchaz.enigma.Main") + ssjb.jar(os.path.join(dirBuild, getJarFullName()), dirTemp, manifest=manifest) + ssjb.delete(dirTemp) def buildTranslateJar(): - jarName = "translate" - os.makedirs(dirTemp) - files = ssjb.findFiles(dirBin, "cuchaz/enigma/mapping/*") - files += ssjb.findFiles(dirBin, "cuchaz/enigma/bytecode/*") - ssjb.copyFiles(dirTemp, dirBin, files) - ssjb.copyFile(dirTemp, "license.GPL3.txt", renameTo="license.txt") - ssjb.copyFile(dirTemp, "readme.translate.txt", renameTo="readme.txt") - manifest = ssjb.buildManifest("%s-%s" % (projectName, jarName), version, author) - ssjb.jar(os.path.join(dirBuild, getJarFullName(jarName)), dirTemp, manifest=manifest) - ssjb.delete(dirTemp) + jarName = "translate" + os.makedirs(dirTemp) + files = ssjb.findFiles(dirBin, "cuchaz/enigma/mapping/*") + files += ssjb.findFiles(dirBin, "cuchaz/enigma/bytecode/*") + ssjb.copyFiles(dirTemp, dirBin, files) + ssjb.copyFile(dirTemp, "license.GPL3.txt", renameTo="license.txt") + ssjb.copyFile(dirTemp, "readme.translate.txt", renameTo="readme.txt") + manifest = ssjb.buildManifest("%s-%s" % (projectName, jarName), version, author) + ssjb.jar(os.path.join(dirBuild, getJarFullName(jarName)), dirTemp, manifest=manifest) + ssjb.delete(dirTemp) def taskMain(): - ssjb.delete(dirBuild) - os.makedirs(dirBuild) - buildGuiJar() - buildTranslateJar() + ssjb.delete(dirBuild) + os.makedirs(dirBuild) + buildGuiJar() + buildTranslateJar() +def makeTestJar(name, glob): + + pathJar = os.path.join(dirBuild, "%s.jar" % name) + pathObfJar = os.path.join(dirBuild, "%s.obf.jar" % name) + + # build the deobf jar + ssjb.delete(dirTemp) + os.makedirs(dirTemp) + ssjb.copyFiles(dirTemp, dirBin, ssjb.findFiles(dirBin, "cuchaz/enigma/inputs/Keep.class")) + ssjb.copyFiles(dirTemp, dirBin, ssjb.findFiles(dirBin, glob)) + ssjb.jar(pathJar, dirTemp) + ssjb.delete(dirTemp) + + # build the obf jar + ssjb.callJavaJar("libs/proguard.jar", ["@proguard.conf", "-injars", pathJar, "-outjars", pathObfJar]) + +def taskBuildTestJars(): + makeTestJar("testLoneClass", "cuchaz/enigma/inputs/loneClass/*.class") + makeTestJar("testConstructors", "cuchaz/enigma/inputs/constructors/*.class") + makeTestJar("testInheritanceTree", "cuchaz/enigma/inputs/inheritanceTree/*.class") + makeTestJar("testInnerClasses", "cuchaz/enigma/inputs/innerClasses/*.class") + ssjb.registerTask("main", taskMain) +ssjb.registerTask("buildTestJars", taskBuildTestJars) if __name__ == "__main__": - ssjb.run() + ssjb.run() diff --git a/libs/proguard.jar b/libs/proguard.jar new file mode 100644 index 00000000..a948c89b Binary files /dev/null and b/libs/proguard.jar differ diff --git a/proguard.conf b/proguard.conf new file mode 100644 index 00000000..e1f04aee --- /dev/null +++ b/proguard.conf @@ -0,0 +1,7 @@ +-libraryjars /lib/rt.jar +-overloadaggressively +-repackageclasses +-allowaccessmodification +-dontoptimize +-dontshrink +-keep class cuchaz.enigma.inputs.Keep \ No newline at end of file diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 679518a4..23057223 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java @@ -144,7 +144,7 @@ public class Deobfuscator { // fields for (FieldMapping fieldMapping : Lists.newArrayList(classMapping.fields())) { FieldEntry fieldEntry = new FieldEntry(obfClassEntry, fieldMapping.getObfName()); - ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass(fieldEntry); + ClassEntry resolvedObfClassEntry = m_jarIndex.getTranslationIndex().resolveEntryClass(fieldEntry); if (resolvedObfClassEntry != null && !resolvedObfClassEntry.equals(fieldEntry.getClassEntry())) { boolean wasMoved = renamer.moveFieldToObfClass(classMapping, fieldMapping, resolvedObfClassEntry); if (wasMoved) { @@ -167,7 +167,7 @@ public class Deobfuscator { methodMapping.getObfName(), methodMapping.getObfSignature() ); - ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass(methodEntry); + ClassEntry resolvedObfClassEntry = m_jarIndex.getTranslationIndex().resolveEntryClass(methodEntry); if (resolvedObfClassEntry != null && !resolvedObfClassEntry.equals(methodEntry.getClassEntry())) { boolean wasMoved = renamer.moveMethodToObfClass(classMapping, methodMapping, resolvedObfClassEntry); if (wasMoved) { @@ -233,7 +233,7 @@ public class Deobfuscator { public Translator getTranslator(TranslationDirection direction) { Translator translator = m_translatorCache.get(direction); if (translator == null) { - translator = m_mappings.getTranslator(direction); + translator = m_mappings.getTranslator(direction, m_jarIndex.getTranslationIndex()); m_translatorCache.put(direction, translator); } return translator; @@ -311,7 +311,7 @@ public class Deobfuscator { Entry obfEntry = obfuscateEntry(deobfReference.entry); // try to resolve the class - ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass(obfEntry); + ClassEntry resolvedObfClassEntry = m_jarIndex.getTranslationIndex().resolveEntryClass(obfEntry); if (resolvedObfClassEntry != null && !resolvedObfClassEntry.equals(obfEntry.getClassEntry())) { // change the class of the entry obfEntry = obfEntry.cloneToNewClass(resolvedObfClassEntry); diff --git a/src/cuchaz/enigma/Main.java b/src/cuchaz/enigma/Main.java index f8d3afe2..1891ded8 100644 --- a/src/cuchaz/enigma/Main.java +++ b/src/cuchaz/enigma/Main.java @@ -28,7 +28,7 @@ public class Main { } // DEBUG - // gui.getController().openDeclaration( new ClassEntry( "none/ces" ) ); + //gui.getController().openDeclaration(new ClassEntry("none/bxq")); } private static File getFile(String path) { diff --git a/src/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java b/src/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java index b132305c..3eaa3912 100644 --- a/src/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java +++ b/src/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java @@ -51,8 +51,8 @@ public class ClassInheritanceTreeNode extends DefaultMutableTreeNode { public void load(TranslationIndex ancestries, boolean recurse) { // get all the child nodes List nodes = Lists.newArrayList(); - for (String subclassName : ancestries.getSubclassNames(m_obfClassName)) { - nodes.add(new ClassInheritanceTreeNode(m_deobfuscatingTranslator, subclassName)); + for (ClassEntry subclassEntry : ancestries.getSubclass(new ClassEntry(m_obfClassName))) { + nodes.add(new ClassInheritanceTreeNode(m_deobfuscatingTranslator, subclassEntry.getName())); } // add them to this node diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 4b03a332..c96d3bc4 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java @@ -114,8 +114,8 @@ public class JarIndex { // step 3: index extends, implements, fields, and methods for (CtClass c : JarClassIterator.classes(jar)) { ClassRenamer.moveAllClassesOutOfDefaultPackage(c, Constants.NonePackage); + m_translationIndex.indexClass(c); String className = Descriptor.toJvmName(c.getName()); - m_translationIndex.addSuperclass(className, Descriptor.toJvmName(c.getClassFile().getSuperclass())); for (String interfaceName : c.getClassFile().getInterfaces()) { className = Descriptor.toJvmName(className); interfaceName = Descriptor.toJvmName(interfaceName); @@ -191,8 +191,6 @@ public class JarIndex { String className = Descriptor.toJvmName(field.getDeclaringClass().getName()); FieldEntry fieldEntry = new FieldEntry(new ClassEntry(className), field.getName()); - m_translationIndex.addField(className, field.getName()); - // is the field a class type? if (field.getSignature().startsWith("L")) { ClassEntry fieldTypeEntry = new ClassEntry(field.getSignature().substring(1, field.getSignature().length() - 1)); @@ -230,13 +228,12 @@ public class JarIndex { behavior.instrument(new ExprEditor() { @Override public void edit(MethodCall call) { - String className = Descriptor.toJvmName(call.getClassName()); MethodEntry calledMethodEntry = new MethodEntry( - new ClassEntry(className), + new ClassEntry(Descriptor.toJvmName(call.getClassName())), call.getMethodName(), call.getSignature() ); - ClassEntry resolvedClassEntry = resolveEntryClass(calledMethodEntry); + ClassEntry resolvedClassEntry = m_translationIndex.resolveEntryClass(calledMethodEntry); if (resolvedClassEntry != null && !resolvedClassEntry.equals(calledMethodEntry.getClassEntry())) { calledMethodEntry = new MethodEntry( resolvedClassEntry, @@ -254,12 +251,11 @@ public class JarIndex { @Override public void edit(FieldAccess call) { - String className = Descriptor.toJvmName(call.getClassName()); FieldEntry calledFieldEntry = new FieldEntry( - new ClassEntry(className), + new ClassEntry(Descriptor.toJvmName(call.getClassName())), call.getFieldName() ); - ClassEntry resolvedClassEntry = resolveEntryClass(calledFieldEntry); + ClassEntry resolvedClassEntry = m_translationIndex.resolveEntryClass(calledFieldEntry); if (resolvedClassEntry != null && !resolvedClassEntry.equals(calledFieldEntry.getClassEntry())) { calledFieldEntry = new FieldEntry(resolvedClassEntry, call.getFieldName()); } @@ -273,9 +269,8 @@ public class JarIndex { @Override public void edit(ConstructorCall call) { - String className = Descriptor.toJvmName(call.getClassName()); ConstructorEntry calledConstructorEntry = new ConstructorEntry( - new ClassEntry(className), + new ClassEntry(Descriptor.toJvmName(call.getClassName())), call.getSignature() ); EntryReference reference = new EntryReference( @@ -288,9 +283,8 @@ public class JarIndex { @Override public void edit(NewExpr call) { - String className = Descriptor.toJvmName(call.getClassName()); ConstructorEntry calledConstructorEntry = new ConstructorEntry( - new ClassEntry(className), + new ClassEntry(Descriptor.toJvmName(call.getClassName())), call.getSignature() ); EntryReference reference = new EntryReference( @@ -306,25 +300,6 @@ public class JarIndex { } } - public ClassEntry resolveEntryClass(Entry obfEntry) { - - // this entry could refer to a method on a class where the method is not actually implemented - // travel up the inheritance tree to find the closest implementation - while (!containsObfEntry(obfEntry)) { - // is there a parent class? - String superclassName = m_translationIndex.getSuperclassName(obfEntry.getClassName()); - if (superclassName == null) { - // this is probably a method from a class in a library - // we can't trace the implementation up any higher unless we index the library - return null; - } - - // move up to the parent class - obfEntry = obfEntry.cloneToNewClass(new ClassEntry(superclassName)); - } - return obfEntry.getClassEntry(); - } - private CtMethod getBridgedMethod(CtMethod method) { // bridge methods just call another method, cast it to the return type, and return the result @@ -402,9 +377,9 @@ public class JarIndex { if (reference.entry instanceof ConstructorEntry && reference.context instanceof ConstructorEntry) { // is the entry a superclass of the context? - String calledClassName = reference.entry.getClassName(); - String callerSuperclassName = m_translationIndex.getSuperclassName(reference.context.getClassName()); - if (callerSuperclassName != null && callerSuperclassName.equals(calledClassName)) { + ClassEntry calledClassEntry = reference.entry.getClassEntry(); + ClassEntry superclassEntry = m_translationIndex.getSuperclass(reference.context.getClassEntry()); + if (superclassEntry != null && superclassEntry.equals(calledClassEntry)) { // it's a super call, skip continue; } @@ -599,7 +574,9 @@ public class JarIndex { // get the root node List ancestry = Lists.newArrayList(); ancestry.add(obfClassEntry.getName()); - ancestry.addAll(m_translationIndex.getAncestry(obfClassEntry.getName())); + for (ClassEntry classEntry : m_translationIndex.getAncestry(obfClassEntry)) { + ancestry.add(classEntry.getName()); + } ClassInheritanceTreeNode rootNode = new ClassInheritanceTreeNode( deobfuscatingTranslator, ancestry.get(ancestry.size() - 1) @@ -625,21 +602,21 @@ public class JarIndex { public MethodInheritanceTreeNode getMethodInheritance(Translator deobfuscatingTranslator, MethodEntry obfMethodEntry) { // travel to the ancestor implementation - String baseImplementationClassName = obfMethodEntry.getClassName(); - for (String ancestorClassName : m_translationIndex.getAncestry(obfMethodEntry.getClassName())) { + ClassEntry baseImplementationClassEntry = obfMethodEntry.getClassEntry(); + for (ClassEntry ancestorClassEntry : m_translationIndex.getAncestry(obfMethodEntry.getClassEntry())) { MethodEntry ancestorMethodEntry = new MethodEntry( - new ClassEntry(ancestorClassName), + new ClassEntry(ancestorClassEntry), obfMethodEntry.getName(), obfMethodEntry.getSignature() ); if (containsObfBehavior(ancestorMethodEntry)) { - baseImplementationClassName = ancestorClassName; + baseImplementationClassEntry = ancestorClassEntry; } } // make a root node at the base MethodEntry methodEntry = new MethodEntry( - new ClassEntry(baseImplementationClassName), + baseImplementationClassEntry, obfMethodEntry.getName(), obfMethodEntry.getSignature() ); @@ -781,8 +758,8 @@ public class JarIndex { public Set getInterfaces(String className) { Set interfaceNames = new HashSet(); interfaceNames.addAll(m_interfaces.get(className)); - for (String ancestor : m_translationIndex.getAncestry(className)) { - interfaceNames.addAll(m_interfaces.get(ancestor)); + for (ClassEntry ancestor : m_translationIndex.getAncestry(new ClassEntry(className))) { + interfaceNames.addAll(m_interfaces.get(ancestor.getName())); } return interfaceNames; } @@ -795,7 +772,7 @@ public class JarIndex { String interfaceName = entry.getValue(); if (interfaceName.equals(targetInterfaceName)) { classNames.add(className); - m_translationIndex.getSubclassNamesRecursively(classNames, className); + m_translationIndex.getSubclassNamesRecursively(classNames, new ClassEntry(className)); } } return classNames; diff --git a/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java b/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java index eba8d874..87182204 100644 --- a/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java +++ b/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java @@ -71,9 +71,9 @@ public class MethodInheritanceTreeNode extends DefaultMutableTreeNode { public void load(JarIndex index, boolean recurse) { // get all the child nodes List nodes = Lists.newArrayList(); - for (String subclassName : index.getTranslationIndex().getSubclassNames(m_entry.getClassName())) { + for (ClassEntry subclassEntry : index.getTranslationIndex().getSubclass(m_entry.getClassEntry())) { MethodEntry methodEntry = new MethodEntry( - new ClassEntry(subclassName), + subclassEntry, m_entry.getName(), m_entry.getSignature() ); diff --git a/src/cuchaz/enigma/analysis/TranslationIndex.java b/src/cuchaz/enigma/analysis/TranslationIndex.java index c14fd593..4a356eb6 100644 --- a/src/cuchaz/enigma/analysis/TranslationIndex.java +++ b/src/cuchaz/enigma/analysis/TranslationIndex.java @@ -11,97 +11,185 @@ package cuchaz.enigma.analysis; import java.io.Serializable; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; -import javassist.bytecode.Descriptor; +import javassist.CtBehavior; +import javassist.CtClass; +import javassist.CtField; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import cuchaz.enigma.mapping.ArgumentEntry; +import cuchaz.enigma.mapping.BehaviorEntry; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.Entry; +import cuchaz.enigma.mapping.FieldEntry; +import cuchaz.enigma.mapping.JavassistUtil; +import cuchaz.enigma.mapping.Translator; + public class TranslationIndex implements Serializable { private static final long serialVersionUID = 738687982126844179L; - private Map m_superclasses; - private Multimap m_fields; + private Map m_superclasses; + private Multimap m_fieldEntries; + private Multimap m_behaviorEntries; public TranslationIndex() { m_superclasses = Maps.newHashMap(); - m_fields = HashMultimap.create(); - } - - public TranslationIndex(TranslationIndex other) { - m_superclasses = Maps.newHashMap(other.m_superclasses); - m_fields = HashMultimap.create(other.m_fields); + m_fieldEntries = HashMultimap.create(); + m_behaviorEntries = HashMultimap.create(); } - public void addSuperclass(String className, String superclassName) { - className = Descriptor.toJvmName(className); - superclassName = Descriptor.toJvmName(superclassName); + public TranslationIndex(TranslationIndex other, Translator translator) { - if (className.equals(superclassName)) { - throw new IllegalArgumentException("Class cannot be its own superclass! " + className); + // translate the superclasses + m_superclasses = Maps.newHashMap(); + for (Map.Entry mapEntry : other.m_superclasses.entrySet()) { + m_superclasses.put( + translator.translateEntry(mapEntry.getKey()), + translator.translateEntry(mapEntry.getValue()) + ); } - if (!isJre(className) && !isJre(superclassName)) { - m_superclasses.put(className, superclassName); + // translate the fields + m_fieldEntries = HashMultimap.create(); + for (Map.Entry mapEntry : other.m_fieldEntries.entries()) { + m_fieldEntries.put( + translator.translateEntry(mapEntry.getKey()), + translator.translateEntry(mapEntry.getValue()) + ); + } + + m_behaviorEntries = HashMultimap.create(); + for (Map.Entry mapEntry : other.m_behaviorEntries.entries()) { + m_behaviorEntries.put( + translator.translateEntry(mapEntry.getKey()), + translator.translateEntry(mapEntry.getValue()) + ); } } - public void addField(String className, String fieldName) { - m_fields.put(className, fieldName); + public void indexClass(CtClass c) { + + ClassEntry classEntry = JavassistUtil.getClassEntry(c); + + // add the superclass + ClassEntry superclassEntry = JavassistUtil.getSuperclassEntry(c); + if (!isJre(classEntry) && !isJre(superclassEntry)) { + m_superclasses.put(classEntry, superclassEntry); + } + + // add fields + for (CtField field : c.getDeclaredFields()) { + FieldEntry fieldEntry = JavassistUtil.getFieldEntry(field); + m_fieldEntries.put(fieldEntry.getClassEntry(), fieldEntry); + } + + // add behaviors + for (CtBehavior behavior : c.getDeclaredBehaviors()) { + BehaviorEntry behaviorEntry = JavassistUtil.getBehaviorEntry(behavior); + m_behaviorEntries.put(behaviorEntry.getClassEntry(), behaviorEntry); + } } public void renameClasses(Map renames) { EntryRenamer.renameClassesInMap(renames, m_superclasses); - EntryRenamer.renameClassesInMultimap(renames, m_fields); + EntryRenamer.renameClassesInMultimap(renames, m_fieldEntries); + EntryRenamer.renameClassesInMultimap(renames, m_behaviorEntries); } - public String getSuperclassName(String className) { - return m_superclasses.get(className); + public ClassEntry getSuperclass(ClassEntry classEntry) { + return m_superclasses.get(classEntry); } - public List getAncestry(String className) { - List ancestors = new ArrayList(); - while (className != null) { - className = getSuperclassName(className); - if (className != null) { - ancestors.add(className); + public List getAncestry(ClassEntry classEntry) { + List ancestors = Lists.newArrayList(); + while (classEntry != null) { + classEntry = getSuperclass(classEntry); + if (classEntry != null) { + ancestors.add(classEntry); } } return ancestors; } - public List getSubclassNames(String className) { + public List getSubclass(ClassEntry classEntry) { // linear search is fast enough for now - List subclasses = Lists.newArrayList(); - for (Map.Entry entry : m_superclasses.entrySet()) { - String subclass = entry.getKey(); - String superclass = entry.getValue(); - if (className.equals(superclass)) { + List subclasses = Lists.newArrayList(); + for (Map.Entry entry : m_superclasses.entrySet()) { + ClassEntry subclass = entry.getKey(); + ClassEntry superclass = entry.getValue(); + if (classEntry.equals(superclass)) { subclasses.add(subclass); } } return subclasses; } - public void getSubclassNamesRecursively(Set out, String className) { - for (String subclassName : getSubclassNames(className)) { - out.add(subclassName); - getSubclassNamesRecursively(out, subclassName); + public void getSubclassesRecursively(Set out, ClassEntry classEntry) { + for (ClassEntry subclassEntry : getSubclass(classEntry)) { + out.add(subclassEntry); + getSubclassesRecursively(out, subclassEntry); + } + } + + public void getSubclassNamesRecursively(Set out, ClassEntry classEntry) { + for (ClassEntry subclassEntry : getSubclass(classEntry)) { + out.add(subclassEntry.getName()); + getSubclassNamesRecursively(out, subclassEntry); } } - public boolean containsField(String className, String fieldName) { - return m_fields.containsEntry(className, fieldName); + public boolean entryExists(Entry entry) { + if (entry instanceof FieldEntry) { + return fieldExists((FieldEntry)entry); + } else if (entry instanceof BehaviorEntry) { + return behaviorExists((BehaviorEntry)entry); + } else if (entry instanceof ArgumentEntry) { + return behaviorExists(((ArgumentEntry)entry).getBehaviorEntry()); + } + throw new IllegalArgumentException("Cannot check existence for " + entry.getClass()); + } + + public boolean fieldExists(FieldEntry fieldEntry) { + return m_fieldEntries.containsEntry(fieldEntry.getClassEntry(), fieldEntry); + } + + public boolean behaviorExists(BehaviorEntry behaviorEntry) { + return m_behaviorEntries.containsEntry(behaviorEntry.getClassEntry(), behaviorEntry); + } + + public ClassEntry resolveEntryClass(Entry entry) { + + if (entry instanceof ClassEntry) { + return (ClassEntry)entry; + } + + // this entry could refer to a method on a class where the method is not actually implemented + // travel up the inheritance tree to find the closest implementation + while (!entryExists(entry)) { + + // is there a parent class? + ClassEntry superclassEntry = getSuperclass(entry.getClassEntry()); + if (superclassEntry == null) { + // this is probably a method from a class in a library + // we can't trace the implementation up any higher unless we index the library + return null; + } + + // move up to the parent class + entry = entry.cloneToNewClass(superclassEntry); + } + return entry.getClassEntry(); } - private boolean isJre(String className) { - return className.startsWith("java/") || className.startsWith("javax/"); + private boolean isJre(ClassEntry classEntry) { + return classEntry.getPackageName().startsWith("java") || classEntry.getPackageName().startsWith("javax"); } } diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java index 735a8fa3..64418307 100644 --- a/src/cuchaz/enigma/bytecode/ClassTranslator.java +++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java @@ -38,6 +38,7 @@ public class ClassTranslator { } public void translate(CtClass c) { + // NOTE: the order of these translations is very important // translate all the field and method references in the code by editing the constant pool @@ -45,7 +46,9 @@ public class ClassTranslator { ConstPoolEditor editor = new ConstPoolEditor(constants); for (int i = 1; i < constants.getSize(); i++) { switch (constants.getTag(i)) { + case ConstPool.CONST_Fieldref: { + // translate the name FieldEntry entry = new FieldEntry( new ClassEntry(Descriptor.toJvmName(constants.getFieldrefClassName(i))), @@ -53,6 +56,11 @@ public class ClassTranslator { ); FieldEntry translatedEntry = m_translator.translateEntry(entry); + // TEMP + if (entry.toString().equals("none/bxq.m")) { + System.out.println("FIELD: " + entry + " -> " + translatedEntry); + } + // translate the type String type = constants.getFieldrefType(i); String translatedType = m_translator.translateSignature(type); @@ -65,6 +73,7 @@ public class ClassTranslator { case ConstPool.CONST_Methodref: case ConstPool.CONST_InterfaceMethodref: { + // translate the name and type BehaviorEntry entry = BehaviorEntryFactory.create( Descriptor.toJvmName(editor.getMemberrefClassname(i)), diff --git a/src/cuchaz/enigma/mapping/JavassistUtil.java b/src/cuchaz/enigma/mapping/JavassistUtil.java new file mode 100644 index 00000000..b011e0be --- /dev/null +++ b/src/cuchaz/enigma/mapping/JavassistUtil.java @@ -0,0 +1,55 @@ +package cuchaz.enigma.mapping; + +import javassist.CtBehavior; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtField; +import javassist.CtMethod; +import javassist.bytecode.Descriptor; +import cuchaz.enigma.mapping.BehaviorEntry; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.ConstructorEntry; +import cuchaz.enigma.mapping.FieldEntry; +import cuchaz.enigma.mapping.MethodEntry; + +public class JavassistUtil { + + public static ClassEntry getClassEntry(CtClass c) { + return new ClassEntry(Descriptor.toJvmName(c.getName())); + } + + public static ClassEntry getSuperclassEntry(CtClass c) { + return new ClassEntry(Descriptor.toJvmName(c.getClassFile().getSuperclass())); + } + + public static MethodEntry getMethodEntry(CtMethod method) { + return new MethodEntry( + getClassEntry(method.getDeclaringClass()), + method.getName(), + method.getMethodInfo().getDescriptor() + ); + } + + public static ConstructorEntry getConstructorEntry(CtConstructor constructor) { + return new ConstructorEntry( + getClassEntry(constructor.getDeclaringClass()), + constructor.getMethodInfo().getDescriptor() + ); + } + + public static BehaviorEntry getBehaviorEntry(CtBehavior behavior) { + if (behavior instanceof CtMethod) { + return getMethodEntry((CtMethod)behavior); + } else if (behavior instanceof CtConstructor) { + return getConstructorEntry((CtConstructor)behavior); + } + throw new Error("behavior is neither Method nor Constructor!"); + } + + public static FieldEntry getFieldEntry(CtField field) { + return new FieldEntry( + getClassEntry(field.getDeclaringClass()), + field.getName() + ); + } +} diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index c5e38f4b..cc560a87 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java @@ -24,6 +24,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import cuchaz.enigma.Util; +import cuchaz.enigma.analysis.TranslationIndex; import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; public class Mappings implements Serializable { @@ -104,11 +105,11 @@ public class Mappings implements Serializable { return m_classesByDeobf.get(deobfName); } - public Translator getTranslator(TranslationDirection direction) { + public Translator getTranslator(TranslationDirection direction, TranslationIndex index) { switch (direction) { case Deobfuscating: - return new Translator(direction, m_classesByObf); + return new Translator(direction, m_classesByObf, index); case Obfuscating: @@ -122,7 +123,11 @@ public class Mappings implements Serializable { } } - return new Translator(direction, classes); + // translate the translation index + // NOTE: this isn't actually recursive + TranslationIndex deobfIndex = new TranslationIndex(index, getTranslator(TranslationDirection.Deobfuscating, index)); + + return new Translator(direction, classes, deobfIndex); default: throw new Error("Invalid translation direction!"); diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java index cb95f42b..3aac65a1 100644 --- a/src/cuchaz/enigma/mapping/MappingsRenamer.java +++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java @@ -100,10 +100,10 @@ public class MappingsRenamer { deobfName = NameValidator.validateMethodName(deobfName); for (MethodEntry entry : implementations) { - String deobfSignature = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateSignature(obf.getSignature()); + String deobfSignature = m_mappings.getTranslator(TranslationDirection.Deobfuscating, m_index.getTranslationIndex()).translateSignature(obf.getSignature()); MethodEntry targetEntry = new MethodEntry(entry.getClassEntry(), deobfName, deobfSignature); if (m_mappings.containsDeobfMethod(entry.getClassEntry(), deobfName, entry.getSignature()) || m_index.containsObfBehavior(targetEntry)) { - String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateClass(entry.getClassName()); + String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating, m_index.getTranslationIndex()).translateClass(entry.getClassName()); throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); } } @@ -117,7 +117,7 @@ public class MappingsRenamer { deobfName = NameValidator.validateMethodName(deobfName); MethodEntry targetEntry = new MethodEntry(obf.getClassEntry(), deobfName, obf.getSignature()); if (m_mappings.containsDeobfMethod(obf.getClassEntry(), deobfName, obf.getSignature()) || m_index.containsObfBehavior(targetEntry)) { - String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateClass(obf.getClassName()); + String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating, m_index.getTranslationIndex()).translateClass(obf.getClassName()); throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); } diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java index d8d9f480..a5a3e2f0 100644 --- a/src/cuchaz/enigma/mapping/Translator.java +++ b/src/cuchaz/enigma/mapping/Translator.java @@ -14,21 +14,24 @@ import java.util.Map; import com.google.common.collect.Maps; +import cuchaz.enigma.analysis.TranslationIndex; import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; public class Translator { private TranslationDirection m_direction; private Map m_classes; + private TranslationIndex m_index; public Translator() { m_direction = null; m_classes = Maps.newHashMap(); } - public Translator(TranslationDirection direction, Map classes) { + public Translator(TranslationDirection direction, Map classes, TranslationIndex index) { m_direction = direction; m_classes = classes; + m_index = index; } @SuppressWarnings("unchecked") @@ -100,17 +103,22 @@ public class Translator { public String translate(FieldEntry in) { - // look for the class - ClassMapping classMapping = findClassMapping(in.getClassEntry()); - if (classMapping != null) { - - // look for the field - String translatedName = m_direction.choose( - classMapping.getDeobfFieldName(in.getName()), - classMapping.getObfFieldName(in.getName()) - ); - if (translatedName != null) { - return translatedName; + // resolve the class entry + ClassEntry resolvedClassEntry = m_index.resolveEntryClass(in); + if (resolvedClassEntry != null) { + + // look for the class + ClassMapping classMapping = findClassMapping(resolvedClassEntry); + if (classMapping != null) { + + // look for the field + String translatedName = m_direction.choose( + classMapping.getDeobfFieldName(in.getName()), + classMapping.getObfFieldName(in.getName()) + ); + if (translatedName != null) { + return translatedName; + } } } return null; @@ -126,15 +134,22 @@ public class Translator { public String translate(MethodEntry in) { - // look for class - ClassMapping classMapping = findClassMapping(in.getClassEntry()); - if (classMapping != null) { - - // look for the method - MethodMapping methodMapping = m_direction.choose(classMapping.getMethodByObf(in.getName(), in.getSignature()), - classMapping.getMethodByDeobf(in.getName(), translateSignature(in.getSignature()))); - if (methodMapping != null) { - return m_direction.choose(methodMapping.getDeobfName(), methodMapping.getObfName()); + // resolve the class entry + ClassEntry resolvedClassEntry = m_index.resolveEntryClass(in); + if (resolvedClassEntry != null) { + + // look for class + ClassMapping classMapping = findClassMapping(resolvedClassEntry); + if (classMapping != null) { + + // look for the method + MethodMapping methodMapping = m_direction.choose( + classMapping.getMethodByObf(in.getName(), in.getSignature()), + classMapping.getMethodByDeobf(in.getName(), translateSignature(in.getSignature())) + ); + if (methodMapping != null) { + return m_direction.choose(methodMapping.getDeobfName(), methodMapping.getObfName()); + } } } return null; diff --git a/ssjb.py b/ssjb.py index d3e2bb52..7f051cc5 100644 --- a/ssjb.py +++ b/ssjb.py @@ -17,29 +17,30 @@ import fnmatch tasks = {} def registerTask(name, func): - tasks[name] = func + tasks[name] = func def run(): - # get the task name - taskName = "main" - if len(sys.argv) > 1: - taskName = sys.argv[1] - - # find that task - try: - task = tasks[taskName] - except: - print "Couldn't find task: %s" % taskName - return + # get the task name + taskName = "main" + if len(sys.argv) > 1: + taskName = sys.argv[1] + + # find that task + try: + task = tasks[taskName] + except: + print "Couldn't find task: %s" % taskName + return - # run it! - task() + # run it! + print "Running task: %s" % taskName + task() # set up the default main task def mainTask(): - print "The main task doesn't do anything by default" + print "The main task doesn't do anything by default" registerTask("main", mainTask) @@ -47,117 +48,123 @@ registerTask("main", mainTask) # library of useful functions def findFiles(dirSrc, pattern=None): - out = [] - for root, dirs, files in os.walk(dirSrc): - for file in files: - path = os.path.join(root, file)[len(dirSrc) + 1:] - if pattern is None or fnmatch.fnmatch(path, pattern): - out.append(path) - return out + out = [] + for root, dirs, files in os.walk(dirSrc): + for file in files: + path = os.path.join(root, file)[len(dirSrc) + 1:] + if pattern is None or fnmatch.fnmatch(path, pattern): + out.append(path) + return out def copyFile(dirDest, pathSrc, renameTo=None): - (dirParent, filename) = os.path.split(pathSrc) - if renameTo is None: - renameTo = filename - pathDest = os.path.join(dirDest, renameTo) - shutil.copy2(pathSrc, pathDest) + (dirParent, filename) = os.path.split(pathSrc) + if renameTo is None: + renameTo = filename + pathDest = os.path.join(dirDest, renameTo) + shutil.copy2(pathSrc, pathDest) def copyFiles(dirDest, dirSrc, paths): - for path in paths: - pathSrc = os.path.join(dirSrc, path) - pathDest = os.path.join(dirDest, path) - dirParent = os.path.dirname(pathDest) - if not os.path.isdir(dirParent): - os.makedirs(dirParent) - shutil.copy2(pathSrc, pathDest) + for path in paths: + pathSrc = os.path.join(dirSrc, path) + pathDest = os.path.join(dirDest, path) + dirParent = os.path.dirname(pathDest) + if not os.path.isdir(dirParent): + os.makedirs(dirParent) + shutil.copy2(pathSrc, pathDest) def patternStringToRegex(patternString): - # escape special chars - patternString = re.escape(patternString) - - # process ** and * wildcards - replacements = { - re.escape("**"): ".*", - re.escape("*"): "[^" + os.sep + "]+" - } - def getReplacement(match): - print "matched", match - return "a" - patternString = re.compile("(\\\\\*)+").sub(lambda m: replacements[m.group(0)], patternString) - - return re.compile("^" + patternString + "$") + # escape special chars + patternString = re.escape(patternString) + + # process ** and * wildcards + replacements = { + re.escape("**"): ".*", + re.escape("*"): "[^" + os.sep + "]+" + } + def getReplacement(match): + print "matched", match + return "a" + patternString = re.compile("(\\\\\*)+").sub(lambda m: replacements[m.group(0)], patternString) + + return re.compile("^" + patternString + "$") def matchesAnyPath(path, patternStrings): - for patternString in patternStrings: - pattern = patternStringToRegex(patternString) - # TEMP - print path, pattern.match(path) is not None - if pattern.match(path) is not None: - return True - return False + for patternString in patternStrings: + pattern = patternStringToRegex(patternString) + # TEMP + print path, pattern.match(path) is not None + if pattern.match(path) is not None: + return True + return False def delete(path): - try: - if os.path.isdir(path): - shutil.rmtree(path) - elif os.path.isfile(path): - os.remove(path) - except: - # don't care if it failed - pass + try: + if os.path.isdir(path): + shutil.rmtree(path) + elif os.path.isfile(path): + os.remove(path) + except: + # don't care if it failed + pass def buildManifest(title, version, author, mainClass=None): - manifest = { - "Title": title, - "Version": version, - "Created-by": author - } - if mainClass is not None: - manifest["Main-Class"] = mainClass - return manifest + manifest = { + "Title": title, + "Version": version, + "Created-by": author + } + if mainClass is not None: + manifest["Main-Class"] = mainClass + return manifest def jar(pathOut, dirIn, dirRoot=None, manifest=None): - # build the base args - if dirRoot is None: - dirRoot = dirIn - dirIn = "." - invokeArgs = ["jar"] - filesArgs = ["-C", dirRoot, dirIn] - - if manifest is not None: - # make a temp file for the manifest - tempFile, tempFilename = tempfile.mkstemp(text=True) - try: - # write the manifest - for (key, value) in manifest.iteritems(): - os.write(tempFile, "%s: %s\n" % (key, value)) - os.close(tempFile) - - # build the jar with a manifest - subprocess.call(invokeArgs + ["cmf", tempFilename, pathOut] + filesArgs) - - finally: - os.remove(tempFilename) - else: - # just build the jar without a manifest - subprocess.call(invokeArgs + ["cf", pathOut] + filesArgs) - - print "Wrote jar: %s" % pathOut + # build the base args + if dirRoot is None: + dirRoot = dirIn + dirIn = "." + invokeArgs = ["jar"] + filesArgs = ["-C", dirRoot, dirIn] + + if manifest is not None: + # make a temp file for the manifest + tempFile, tempFilename = tempfile.mkstemp(text=True) + try: + # write the manifest + for (key, value) in manifest.iteritems(): + os.write(tempFile, "%s: %s\n" % (key, value)) + os.close(tempFile) + + # build the jar with a manifest + subprocess.call(invokeArgs + ["cmf", tempFilename, pathOut] + filesArgs) + + finally: + os.remove(tempFilename) + else: + # just build the jar without a manifest + subprocess.call(invokeArgs + ["cf", pathOut] + filesArgs) + + print "Wrote jar: %s" % pathOut def unpackJar(dirOut, pathJar): - with zipfile.ZipFile(pathJar) as zf: - for member in zf.infolist(): - zf.extract(member, dirOut) - print "Unpacked jar: %s" % pathJar + with zipfile.ZipFile(pathJar) as zf: + for member in zf.infolist(): + zf.extract(member, dirOut) + print "Unpacked jar: %s" % pathJar def unpackJars(dirOut, dirJars, recursive=False): - for name in os.listdir(dirJars): - path = os.path.join(dirJars, name) - if os.path.isfile(path): - if name[-4:] == ".jar": - unpackJar(dirOut, path) - elif os.path.isdir(path) and recursive: - unpackJars(dirOut, path, recursive) + for name in os.listdir(dirJars): + path = os.path.join(dirJars, name) + if os.path.isfile(path): + if name[-4:] == ".jar": + unpackJar(dirOut, path) + elif os.path.isdir(path) and recursive: + unpackJars(dirOut, path, recursive) + +def callJava(classpath, className, javaArgs): + subprocess.call(["java", "-cp", classpath, className] + javaArgs) + +def callJavaJar(jar, javaArgs): + subprocess.call(["java", "-jar", jar] + javaArgs) diff --git a/test/cuchaz/enigma/TestDeobfuscator.java b/test/cuchaz/enigma/TestDeobfuscator.java index 45d27c40..6ac4c786 100644 --- a/test/cuchaz/enigma/TestDeobfuscator.java +++ b/test/cuchaz/enigma/TestDeobfuscator.java @@ -26,7 +26,7 @@ import cuchaz.enigma.mapping.ClassEntry; public class TestDeobfuscator { private Deobfuscator getDeobfuscator() throws IOException { - return new Deobfuscator(new File("build/libs/testLoneClass.obf.jar")); + return new Deobfuscator(new File("build/testLoneClass.obf.jar")); } @Test diff --git a/test/cuchaz/enigma/TestInnerClasses.java b/test/cuchaz/enigma/TestInnerClasses.java index c84d755e..51fb5e35 100644 --- a/test/cuchaz/enigma/TestInnerClasses.java +++ b/test/cuchaz/enigma/TestInnerClasses.java @@ -35,7 +35,7 @@ public class TestInnerClasses { public TestInnerClasses() throws Exception { m_index = new JarIndex(); - m_index.indexJar(new JarFile("build/libs/testInnerClasses.obf.jar"), true); + m_index.indexJar(new JarFile("build/testInnerClasses.obf.jar"), true); } @Test diff --git a/test/cuchaz/enigma/TestJarIndexConstructorReferences.java b/test/cuchaz/enigma/TestJarIndexConstructorReferences.java index b5f4c7f3..8e3ad6d2 100644 --- a/test/cuchaz/enigma/TestJarIndexConstructorReferences.java +++ b/test/cuchaz/enigma/TestJarIndexConstructorReferences.java @@ -37,7 +37,7 @@ public class TestJarIndexConstructorReferences { private ClassEntry m_callerClass = new ClassEntry("none/b"); public TestJarIndexConstructorReferences() throws Exception { - File jarFile = new File("build/libs/testConstructors.obf.jar"); + File jarFile = new File("build/testConstructors.obf.jar"); m_index = new JarIndex(); m_index.indexJar(new JarFile(jarFile), false); } diff --git a/test/cuchaz/enigma/TestJarIndexInheritanceTree.java b/test/cuchaz/enigma/TestJarIndexInheritanceTree.java index caf6578d..4d663972 100644 --- a/test/cuchaz/enigma/TestJarIndexInheritanceTree.java +++ b/test/cuchaz/enigma/TestJarIndexInheritanceTree.java @@ -43,7 +43,7 @@ public class TestJarIndexInheritanceTree { public TestJarIndexInheritanceTree() throws Exception { m_index = new JarIndex(); - m_index.indexJar(new JarFile("build/libs/testInheritanceTree.obf.jar"), false); + m_index.indexJar(new JarFile("build/testInheritanceTree.obf.jar"), false); } @Test @@ -63,27 +63,27 @@ public class TestJarIndexInheritanceTree { TranslationIndex index = m_index.getTranslationIndex(); // base class - assertThat(index.getSuperclassName(m_baseClass.getName()), is(nullValue())); - assertThat(index.getAncestry(m_baseClass.getName()), is(empty())); - assertThat(index.getSubclassNames(m_baseClass.getName()), containsInAnyOrder( - m_subClassA.getName(), - m_subClassB.getName() + assertThat(index.getSuperclass(m_baseClass), is(nullValue())); + assertThat(index.getAncestry(m_baseClass), is(empty())); + assertThat(index.getSubclass(m_baseClass), containsInAnyOrder( + m_subClassA, + m_subClassB )); // subclass a - assertThat(index.getSuperclassName(m_subClassA.getName()), is(m_baseClass.getName())); - assertThat(index.getAncestry(m_subClassA.getName()), contains(m_baseClass.getName())); - assertThat(index.getSubclassNames(m_subClassA.getName()), contains(m_subClassAA.getName())); + assertThat(index.getSuperclass(m_subClassA), is(m_baseClass)); + assertThat(index.getAncestry(m_subClassA), contains(m_baseClass)); + assertThat(index.getSubclass(m_subClassA), contains(m_subClassAA)); // subclass aa - assertThat(index.getSuperclassName(m_subClassAA.getName()), is(m_subClassA.getName())); - assertThat(index.getAncestry(m_subClassAA.getName()), contains(m_subClassA.getName(), m_baseClass.getName())); - assertThat(index.getSubclassNames(m_subClassAA.getName()), is(empty())); + assertThat(index.getSuperclass(m_subClassAA), is(m_subClassA)); + assertThat(index.getAncestry(m_subClassAA), contains(m_subClassA, m_baseClass)); + assertThat(index.getSubclass(m_subClassAA), is(empty())); // subclass b - assertThat(index.getSuperclassName(m_subClassB.getName()), is(m_baseClass.getName())); - assertThat(index.getAncestry(m_subClassB.getName()), contains(m_baseClass.getName())); - assertThat(index.getSubclassNames(m_subClassB.getName()), is(empty())); + assertThat(index.getSuperclass(m_subClassB), is(m_baseClass)); + assertThat(index.getAncestry(m_subClassB), contains(m_baseClass)); + assertThat(index.getSubclass(m_subClassB), is(empty())); } @Test diff --git a/test/cuchaz/enigma/TestJarIndexLoneClass.java b/test/cuchaz/enigma/TestJarIndexLoneClass.java index 0575eec3..a061b72d 100644 --- a/test/cuchaz/enigma/TestJarIndexLoneClass.java +++ b/test/cuchaz/enigma/TestJarIndexLoneClass.java @@ -29,6 +29,7 @@ import cuchaz.enigma.analysis.JarIndex; import cuchaz.enigma.analysis.MethodImplementationsTreeNode; import cuchaz.enigma.analysis.MethodInheritanceTreeNode; import cuchaz.enigma.mapping.BehaviorEntry; +import cuchaz.enigma.mapping.ClassEntry; import cuchaz.enigma.mapping.FieldEntry; import cuchaz.enigma.mapping.MethodEntry; import cuchaz.enigma.mapping.Translator; @@ -39,7 +40,7 @@ public class TestJarIndexLoneClass { public TestJarIndexLoneClass() throws Exception { m_index = new JarIndex(); - m_index.indexJar(new JarFile("build/libs/testLoneClass.obf.jar"), false); + m_index.indexJar(new JarFile("build/testLoneClass.obf.jar"), false); } @Test @@ -52,12 +53,12 @@ public class TestJarIndexLoneClass { @Test public void translationIndex() { - assertThat(m_index.getTranslationIndex().getSuperclassName("none/a"), is(nullValue())); - assertThat(m_index.getTranslationIndex().getSuperclassName("cuchaz/enigma/inputs/Keep"), is(nullValue())); - assertThat(m_index.getTranslationIndex().getAncestry("none/a"), is(empty())); - assertThat(m_index.getTranslationIndex().getAncestry("cuchaz/enigma/inputs/Keep"), is(empty())); - assertThat(m_index.getTranslationIndex().getSubclassNames("none/a"), is(empty())); - assertThat(m_index.getTranslationIndex().getSubclassNames("cuchaz/enigma/inputs/Keep"), is(empty())); + assertThat(m_index.getTranslationIndex().getSuperclass(new ClassEntry("none/a")), is(nullValue())); + assertThat(m_index.getTranslationIndex().getSuperclass(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(nullValue())); + assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("none/a")), is(empty())); + assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); + assertThat(m_index.getTranslationIndex().getSubclass(new ClassEntry("none/a")), is(empty())); + assertThat(m_index.getTranslationIndex().getSubclass(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); } @Test diff --git a/test/cuchaz/enigma/TestSourceIndex.java b/test/cuchaz/enigma/TestSourceIndex.java index fb385e06..ba7fc797 100644 --- a/test/cuchaz/enigma/TestSourceIndex.java +++ b/test/cuchaz/enigma/TestSourceIndex.java @@ -23,6 +23,7 @@ import cuchaz.enigma.mapping.ClassEntry; public class TestSourceIndex { + // TEMP @Test public void indexEverything() throws Exception { Deobfuscator deobfuscator = new Deobfuscator(new File("input/1.8.jar")); diff --git a/test/cuchaz/enigma/TestTokensConstructors.java b/test/cuchaz/enigma/TestTokensConstructors.java index f805a655..9f85e81d 100644 --- a/test/cuchaz/enigma/TestTokensConstructors.java +++ b/test/cuchaz/enigma/TestTokensConstructors.java @@ -27,7 +27,7 @@ import cuchaz.enigma.mapping.BehaviorEntry; public class TestTokensConstructors extends TokenChecker { public TestTokensConstructors() throws Exception { - super(new File("build/libs/testConstructors.obf.jar")); + super(new File("build/testConstructors.obf.jar")); } @Test -- cgit v1.2.3