diff options
| author | 2015-01-19 22:22:57 -0500 | |
|---|---|---|
| committer | 2015-01-19 22:22:57 -0500 | |
| commit | 2fbcf8e5c4eec0aa4a4fc59c7cc8abac33b1429c (patch) | |
| tree | 0e9c23d6838d3e0299831dbc24b6d736c268cd8b /src/cuchaz/enigma/mapping | |
| parent | added inverse operation for moving classes out of the default package (diff) | |
| download | enigma-fork-2fbcf8e5c4eec0aa4a4fc59c7cc8abac33b1429c.tar.gz enigma-fork-2fbcf8e5c4eec0aa4a4fc59c7cc8abac33b1429c.tar.xz enigma-fork-2fbcf8e5c4eec0aa4a4fc59c7cc8abac33b1429c.zip | |
solved tricky issue with incorrect translation of fields/methods referenced by a subclass instead of the declaring class
Diffstat (limited to 'src/cuchaz/enigma/mapping')
| -rw-r--r-- | src/cuchaz/enigma/mapping/JavassistUtil.java | 55 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Mappings.java | 11 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MappingsRenamer.java | 6 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Translator.java | 57 |
4 files changed, 102 insertions, 27 deletions
diff --git a/src/cuchaz/enigma/mapping/JavassistUtil.java b/src/cuchaz/enigma/mapping/JavassistUtil.java new file mode 100644 index 0000000..b011e0b --- /dev/null +++ b/src/cuchaz/enigma/mapping/JavassistUtil.java | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | package cuchaz.enigma.mapping; | ||
| 2 | |||
| 3 | import javassist.CtBehavior; | ||
| 4 | import javassist.CtClass; | ||
| 5 | import javassist.CtConstructor; | ||
| 6 | import javassist.CtField; | ||
| 7 | import javassist.CtMethod; | ||
| 8 | import javassist.bytecode.Descriptor; | ||
| 9 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 10 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 11 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 12 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 13 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 14 | |||
| 15 | public class JavassistUtil { | ||
| 16 | |||
| 17 | public static ClassEntry getClassEntry(CtClass c) { | ||
| 18 | return new ClassEntry(Descriptor.toJvmName(c.getName())); | ||
| 19 | } | ||
| 20 | |||
| 21 | public static ClassEntry getSuperclassEntry(CtClass c) { | ||
| 22 | return new ClassEntry(Descriptor.toJvmName(c.getClassFile().getSuperclass())); | ||
| 23 | } | ||
| 24 | |||
| 25 | public static MethodEntry getMethodEntry(CtMethod method) { | ||
| 26 | return new MethodEntry( | ||
| 27 | getClassEntry(method.getDeclaringClass()), | ||
| 28 | method.getName(), | ||
| 29 | method.getMethodInfo().getDescriptor() | ||
| 30 | ); | ||
| 31 | } | ||
| 32 | |||
| 33 | public static ConstructorEntry getConstructorEntry(CtConstructor constructor) { | ||
| 34 | return new ConstructorEntry( | ||
| 35 | getClassEntry(constructor.getDeclaringClass()), | ||
| 36 | constructor.getMethodInfo().getDescriptor() | ||
| 37 | ); | ||
| 38 | } | ||
| 39 | |||
| 40 | public static BehaviorEntry getBehaviorEntry(CtBehavior behavior) { | ||
| 41 | if (behavior instanceof CtMethod) { | ||
| 42 | return getMethodEntry((CtMethod)behavior); | ||
| 43 | } else if (behavior instanceof CtConstructor) { | ||
| 44 | return getConstructorEntry((CtConstructor)behavior); | ||
| 45 | } | ||
| 46 | throw new Error("behavior is neither Method nor Constructor!"); | ||
| 47 | } | ||
| 48 | |||
| 49 | public static FieldEntry getFieldEntry(CtField field) { | ||
| 50 | return new FieldEntry( | ||
| 51 | getClassEntry(field.getDeclaringClass()), | ||
| 52 | field.getName() | ||
| 53 | ); | ||
| 54 | } | ||
| 55 | } | ||
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index c5e38f4..cc560a8 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; | |||
| 24 | import com.google.common.collect.Sets; | 24 | import com.google.common.collect.Sets; |
| 25 | 25 | ||
| 26 | import cuchaz.enigma.Util; | 26 | import cuchaz.enigma.Util; |
| 27 | import cuchaz.enigma.analysis.TranslationIndex; | ||
| 27 | import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; | 28 | import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; |
| 28 | 29 | ||
| 29 | public class Mappings implements Serializable { | 30 | public class Mappings implements Serializable { |
| @@ -104,11 +105,11 @@ public class Mappings implements Serializable { | |||
| 104 | return m_classesByDeobf.get(deobfName); | 105 | return m_classesByDeobf.get(deobfName); |
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | public Translator getTranslator(TranslationDirection direction) { | 108 | public Translator getTranslator(TranslationDirection direction, TranslationIndex index) { |
| 108 | switch (direction) { | 109 | switch (direction) { |
| 109 | case Deobfuscating: | 110 | case Deobfuscating: |
| 110 | 111 | ||
| 111 | return new Translator(direction, m_classesByObf); | 112 | return new Translator(direction, m_classesByObf, index); |
| 112 | 113 | ||
| 113 | case Obfuscating: | 114 | case Obfuscating: |
| 114 | 115 | ||
| @@ -122,7 +123,11 @@ public class Mappings implements Serializable { | |||
| 122 | } | 123 | } |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | return new Translator(direction, classes); | 126 | // translate the translation index |
| 127 | // NOTE: this isn't actually recursive | ||
| 128 | TranslationIndex deobfIndex = new TranslationIndex(index, getTranslator(TranslationDirection.Deobfuscating, index)); | ||
| 129 | |||
| 130 | return new Translator(direction, classes, deobfIndex); | ||
| 126 | 131 | ||
| 127 | default: | 132 | default: |
| 128 | throw new Error("Invalid translation direction!"); | 133 | throw new Error("Invalid translation direction!"); |
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java index cb95f42..3aac65a 100644 --- a/src/cuchaz/enigma/mapping/MappingsRenamer.java +++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java | |||
| @@ -100,10 +100,10 @@ public class MappingsRenamer { | |||
| 100 | 100 | ||
| 101 | deobfName = NameValidator.validateMethodName(deobfName); | 101 | deobfName = NameValidator.validateMethodName(deobfName); |
| 102 | for (MethodEntry entry : implementations) { | 102 | for (MethodEntry entry : implementations) { |
| 103 | String deobfSignature = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateSignature(obf.getSignature()); | 103 | String deobfSignature = m_mappings.getTranslator(TranslationDirection.Deobfuscating, m_index.getTranslationIndex()).translateSignature(obf.getSignature()); |
| 104 | MethodEntry targetEntry = new MethodEntry(entry.getClassEntry(), deobfName, deobfSignature); | 104 | MethodEntry targetEntry = new MethodEntry(entry.getClassEntry(), deobfName, deobfSignature); |
| 105 | if (m_mappings.containsDeobfMethod(entry.getClassEntry(), deobfName, entry.getSignature()) || m_index.containsObfBehavior(targetEntry)) { | 105 | if (m_mappings.containsDeobfMethod(entry.getClassEntry(), deobfName, entry.getSignature()) || m_index.containsObfBehavior(targetEntry)) { |
| 106 | String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateClass(entry.getClassName()); | 106 | String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating, m_index.getTranslationIndex()).translateClass(entry.getClassName()); |
| 107 | throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); | 107 | throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); |
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| @@ -117,7 +117,7 @@ public class MappingsRenamer { | |||
| 117 | deobfName = NameValidator.validateMethodName(deobfName); | 117 | deobfName = NameValidator.validateMethodName(deobfName); |
| 118 | MethodEntry targetEntry = new MethodEntry(obf.getClassEntry(), deobfName, obf.getSignature()); | 118 | MethodEntry targetEntry = new MethodEntry(obf.getClassEntry(), deobfName, obf.getSignature()); |
| 119 | if (m_mappings.containsDeobfMethod(obf.getClassEntry(), deobfName, obf.getSignature()) || m_index.containsObfBehavior(targetEntry)) { | 119 | if (m_mappings.containsDeobfMethod(obf.getClassEntry(), deobfName, obf.getSignature()) || m_index.containsObfBehavior(targetEntry)) { |
| 120 | String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateClass(obf.getClassName()); | 120 | String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating, m_index.getTranslationIndex()).translateClass(obf.getClassName()); |
| 121 | throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); | 121 | throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); |
| 122 | } | 122 | } |
| 123 | 123 | ||
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java index d8d9f48..a5a3e2f 100644 --- a/src/cuchaz/enigma/mapping/Translator.java +++ b/src/cuchaz/enigma/mapping/Translator.java | |||
| @@ -14,21 +14,24 @@ import java.util.Map; | |||
| 14 | 14 | ||
| 15 | import com.google.common.collect.Maps; | 15 | import com.google.common.collect.Maps; |
| 16 | 16 | ||
| 17 | import cuchaz.enigma.analysis.TranslationIndex; | ||
| 17 | import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; | 18 | import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; |
| 18 | 19 | ||
| 19 | public class Translator { | 20 | public class Translator { |
| 20 | 21 | ||
| 21 | private TranslationDirection m_direction; | 22 | private TranslationDirection m_direction; |
| 22 | private Map<String,ClassMapping> m_classes; | 23 | private Map<String,ClassMapping> m_classes; |
| 24 | private TranslationIndex m_index; | ||
| 23 | 25 | ||
| 24 | public Translator() { | 26 | public Translator() { |
| 25 | m_direction = null; | 27 | m_direction = null; |
| 26 | m_classes = Maps.newHashMap(); | 28 | m_classes = Maps.newHashMap(); |
| 27 | } | 29 | } |
| 28 | 30 | ||
| 29 | public Translator(TranslationDirection direction, Map<String,ClassMapping> classes) { | 31 | public Translator(TranslationDirection direction, Map<String,ClassMapping> classes, TranslationIndex index) { |
| 30 | m_direction = direction; | 32 | m_direction = direction; |
| 31 | m_classes = classes; | 33 | m_classes = classes; |
| 34 | m_index = index; | ||
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | @SuppressWarnings("unchecked") | 37 | @SuppressWarnings("unchecked") |
| @@ -100,17 +103,22 @@ public class Translator { | |||
| 100 | 103 | ||
| 101 | public String translate(FieldEntry in) { | 104 | public String translate(FieldEntry in) { |
| 102 | 105 | ||
| 103 | // look for the class | 106 | // resolve the class entry |
| 104 | ClassMapping classMapping = findClassMapping(in.getClassEntry()); | 107 | ClassEntry resolvedClassEntry = m_index.resolveEntryClass(in); |
| 105 | if (classMapping != null) { | 108 | if (resolvedClassEntry != null) { |
| 106 | 109 | ||
| 107 | // look for the field | 110 | // look for the class |
| 108 | String translatedName = m_direction.choose( | 111 | ClassMapping classMapping = findClassMapping(resolvedClassEntry); |
| 109 | classMapping.getDeobfFieldName(in.getName()), | 112 | if (classMapping != null) { |
| 110 | classMapping.getObfFieldName(in.getName()) | 113 | |
| 111 | ); | 114 | // look for the field |
| 112 | if (translatedName != null) { | 115 | String translatedName = m_direction.choose( |
| 113 | return translatedName; | 116 | classMapping.getDeobfFieldName(in.getName()), |
| 117 | classMapping.getObfFieldName(in.getName()) | ||
| 118 | ); | ||
| 119 | if (translatedName != null) { | ||
| 120 | return translatedName; | ||
| 121 | } | ||
| 114 | } | 122 | } |
| 115 | } | 123 | } |
| 116 | return null; | 124 | return null; |
| @@ -126,15 +134,22 @@ public class Translator { | |||
| 126 | 134 | ||
| 127 | public String translate(MethodEntry in) { | 135 | public String translate(MethodEntry in) { |
| 128 | 136 | ||
| 129 | // look for class | 137 | // resolve the class entry |
| 130 | ClassMapping classMapping = findClassMapping(in.getClassEntry()); | 138 | ClassEntry resolvedClassEntry = m_index.resolveEntryClass(in); |
| 131 | if (classMapping != null) { | 139 | if (resolvedClassEntry != null) { |
| 132 | 140 | ||
| 133 | // look for the method | 141 | // look for class |
| 134 | MethodMapping methodMapping = m_direction.choose(classMapping.getMethodByObf(in.getName(), in.getSignature()), | 142 | ClassMapping classMapping = findClassMapping(resolvedClassEntry); |
| 135 | classMapping.getMethodByDeobf(in.getName(), translateSignature(in.getSignature()))); | 143 | if (classMapping != null) { |
| 136 | if (methodMapping != null) { | 144 | |
| 137 | return m_direction.choose(methodMapping.getDeobfName(), methodMapping.getObfName()); | 145 | // look for the method |
| 146 | MethodMapping methodMapping = m_direction.choose( | ||
| 147 | classMapping.getMethodByObf(in.getName(), in.getSignature()), | ||
| 148 | classMapping.getMethodByDeobf(in.getName(), translateSignature(in.getSignature())) | ||
| 149 | ); | ||
| 150 | if (methodMapping != null) { | ||
| 151 | return m_direction.choose(methodMapping.getDeobfName(), methodMapping.getObfName()); | ||
| 152 | } | ||
| 138 | } | 153 | } |
| 139 | } | 154 | } |
| 140 | return null; | 155 | return null; |