diff options
| author | 2016-10-30 23:37:29 +0100 | |
|---|---|---|
| committer | 2016-10-30 23:37:29 +0100 | |
| commit | 6235bfc5ab85cdd471e315c52c413991fb9dbddf (patch) | |
| tree | f8d726850a60786176f999952c2e9f7c83e5ccbd /src/main/java/cuchaz/enigma/bytecode | |
| parent | Fix order of packages, hanging of Enigma and classes nodes not renamed when p... (diff) | |
| download | enigma-fork-6235bfc5ab85cdd471e315c52c413991fb9dbddf.tar.gz enigma-fork-6235bfc5ab85cdd471e315c52c413991fb9dbddf.tar.xz enigma-fork-6235bfc5ab85cdd471e315c52c413991fb9dbddf.zip | |
BREAKING CHANGE: Implement modifier transformer
Known Bugs:
- Inner class modifier isn't saved to mapping
- Inner class modifier isn't applied to bytecode
Diffstat (limited to 'src/main/java/cuchaz/enigma/bytecode')
3 files changed, 88 insertions, 18 deletions
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java b/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java index eb7e9a1..d49f13a 100644 --- a/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java +++ b/src/main/java/cuchaz/enigma/bytecode/ClassRenamer.java | |||
| @@ -19,8 +19,9 @@ import java.util.Map; | |||
| 19 | 19 | ||
| 20 | import cuchaz.enigma.mapping.ClassEntry; | 20 | import cuchaz.enigma.mapping.ClassEntry; |
| 21 | import cuchaz.enigma.mapping.ClassNameReplacer; | 21 | import cuchaz.enigma.mapping.ClassNameReplacer; |
| 22 | import cuchaz.enigma.mapping.Mappings; | ||
| 22 | import cuchaz.enigma.mapping.Translator; | 23 | import cuchaz.enigma.mapping.Translator; |
| 23 | import javassist.CtClass; | 24 | import javassist.*; |
| 24 | import javassist.bytecode.*; | 25 | import javassist.bytecode.*; |
| 25 | import javassist.bytecode.SignatureAttribute.*; | 26 | import javassist.bytecode.SignatureAttribute.*; |
| 26 | 27 | ||
| @@ -70,6 +71,41 @@ public class ClassRenamer { | |||
| 70 | } | 71 | } |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 74 | public static void applyModifier(Object obj, Mappings.EntryModifier modifier) | ||
| 75 | { | ||
| 76 | int mod = -1; | ||
| 77 | if (obj instanceof CtField) | ||
| 78 | mod = ((CtField) obj).getModifiers(); | ||
| 79 | else if (obj instanceof CtBehavior) | ||
| 80 | mod = ((CtBehavior) obj).getModifiers(); | ||
| 81 | else if (obj instanceof CtClass) | ||
| 82 | mod = ((CtClass) obj).getModifiers(); | ||
| 83 | |||
| 84 | if (mod != -1) | ||
| 85 | { | ||
| 86 | switch (modifier) | ||
| 87 | { | ||
| 88 | case PRIVATE: | ||
| 89 | mod = Modifier.setPrivate(mod); | ||
| 90 | break; | ||
| 91 | case PROTECTED: | ||
| 92 | mod = Modifier.setProtected(mod); | ||
| 93 | break; | ||
| 94 | case PUBLIC: | ||
| 95 | mod = Modifier.setPublic(mod); | ||
| 96 | break; | ||
| 97 | default: | ||
| 98 | break; | ||
| 99 | } | ||
| 100 | if (obj instanceof CtField) | ||
| 101 | ((CtField) obj).setModifiers(mod); | ||
| 102 | else if (obj instanceof CtBehavior) | ||
| 103 | ((CtBehavior) obj).setModifiers(mod); | ||
| 104 | else | ||
| 105 | ((CtClass) obj).setModifiers(mod); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 73 | public static void renameClasses(CtClass c, final Translator translator) { | 109 | public static void renameClasses(CtClass c, final Translator translator) { |
| 74 | renameClasses(c, className -> { | 110 | renameClasses(c, className -> { |
| 75 | ClassEntry entry = translator.translateEntry(new ClassEntry(className)); | 111 | ClassEntry entry = translator.translateEntry(new ClassEntry(className)); |
| @@ -110,6 +146,7 @@ public class ClassRenamer { | |||
| 110 | 146 | ||
| 111 | // rename the constant pool (covers ClassInfo, MethodTypeInfo, and NameAndTypeInfo) | 147 | // rename the constant pool (covers ClassInfo, MethodTypeInfo, and NameAndTypeInfo) |
| 112 | ConstPool constPool = c.getClassFile().getConstPool(); | 148 | ConstPool constPool = c.getClassFile().getConstPool(); |
| 149 | String className = constPool.getClassName(); | ||
| 113 | constPool.renameClass(map); | 150 | constPool.renameClass(map); |
| 114 | 151 | ||
| 115 | // rename class attributes | 152 | // rename class attributes |
| @@ -140,8 +177,9 @@ public class ClassRenamer { | |||
| 140 | if (attr != null) { | 177 | if (attr != null) { |
| 141 | for (int i = 0; i < attr.tableLength(); i++) { | 178 | for (int i = 0; i < attr.tableLength(); i++) { |
| 142 | 179 | ||
| 180 | String innerName = attr.innerClass(i); | ||
| 143 | // get the inner class full name (which has already been translated) | 181 | // get the inner class full name (which has already been translated) |
| 144 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i))); | 182 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(innerName)); |
| 145 | 183 | ||
| 146 | if (attr.innerNameIndex(i) != 0) { | 184 | if (attr.innerNameIndex(i) != 0) { |
| 147 | // update the inner name | 185 | // update the inner name |
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java b/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java index 6c05b83..62ebfaf 100644 --- a/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java +++ b/src/main/java/cuchaz/enigma/bytecode/ClassTranslator.java | |||
| @@ -11,14 +11,9 @@ | |||
| 11 | package cuchaz.enigma.bytecode; | 11 | package cuchaz.enigma.bytecode; |
| 12 | 12 | ||
| 13 | import cuchaz.enigma.mapping.*; | 13 | import cuchaz.enigma.mapping.*; |
| 14 | import javassist.CtBehavior; | 14 | import cuchaz.enigma.mapping.Translator; |
| 15 | import javassist.CtClass; | 15 | import javassist.*; |
| 16 | import javassist.CtField; | 16 | import javassist.bytecode.*; |
| 17 | import javassist.CtMethod; | ||
| 18 | import javassist.bytecode.ConstPool; | ||
| 19 | import javassist.bytecode.Descriptor; | ||
| 20 | import javassist.bytecode.EnclosingMethodAttribute; | ||
| 21 | import javassist.bytecode.SourceFileAttribute; | ||
| 22 | 17 | ||
| 23 | public class ClassTranslator { | 18 | public class ClassTranslator { |
| 24 | 19 | ||
| @@ -74,6 +69,9 @@ public class ClassTranslator { | |||
| 74 | } | 69 | } |
| 75 | 70 | ||
| 76 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(c.getName())); | 71 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(c.getName())); |
| 72 | Mappings.EntryModifier modifier = this.translator.getModifier(classEntry); | ||
| 73 | if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED) | ||
| 74 | ClassRenamer.applyModifier(c, modifier); | ||
| 77 | 75 | ||
| 78 | // translate all the fields | 76 | // translate all the fields |
| 79 | for (CtField field : c.getDeclaredFields()) { | 77 | for (CtField field : c.getDeclaredFields()) { |
| @@ -81,6 +79,10 @@ public class ClassTranslator { | |||
| 81 | // translate the name | 79 | // translate the name |
| 82 | FieldEntry entry = EntryFactory.getFieldEntry(field); | 80 | FieldEntry entry = EntryFactory.getFieldEntry(field); |
| 83 | String translatedName = this.translator.translate(entry); | 81 | String translatedName = this.translator.translate(entry); |
| 82 | modifier = this.translator.getModifier(entry); | ||
| 83 | if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED) | ||
| 84 | ClassRenamer.applyModifier(field, modifier); | ||
| 85 | |||
| 84 | if (translatedName != null) { | 86 | if (translatedName != null) { |
| 85 | field.setName(translatedName); | 87 | field.setName(translatedName); |
| 86 | } | 88 | } |
| @@ -95,6 +97,10 @@ public class ClassTranslator { | |||
| 95 | 97 | ||
| 96 | BehaviorEntry entry = EntryFactory.getBehaviorEntry(behavior); | 98 | BehaviorEntry entry = EntryFactory.getBehaviorEntry(behavior); |
| 97 | 99 | ||
| 100 | modifier = this.translator.getModifier(entry); | ||
| 101 | if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED) | ||
| 102 | ClassRenamer.applyModifier(behavior, modifier); | ||
| 103 | |||
| 98 | if (behavior instanceof CtMethod) { | 104 | if (behavior instanceof CtMethod) { |
| 99 | CtMethod method = (CtMethod) behavior; | 105 | CtMethod method = (CtMethod) behavior; |
| 100 | 106 | ||
| @@ -149,5 +155,8 @@ public class ClassTranslator { | |||
| 149 | String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOutermostClassEntry().getSimpleName()) + ".java"; | 155 | String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOutermostClassEntry().getSimpleName()) + ".java"; |
| 150 | c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile)); | 156 | c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile)); |
| 151 | } | 157 | } |
| 158 | InnerClassesAttribute attr = (InnerClassesAttribute) c.getClassFile().getAttribute(InnerClassesAttribute.tag); | ||
| 159 | if (attr != null) | ||
| 160 | InnerClassWriter.changeModifier(c, attr, translator); | ||
| 152 | } | 161 | } |
| 153 | } | 162 | } |
diff --git a/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java index 6d92610..6e2a29d 100644 --- a/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java +++ b/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java | |||
| @@ -15,22 +15,22 @@ import com.google.common.collect.Lists; | |||
| 15 | import java.util.Collection; | 15 | import java.util.Collection; |
| 16 | import java.util.List; | 16 | import java.util.List; |
| 17 | 17 | ||
| 18 | import cuchaz.enigma.Deobfuscator; | ||
| 18 | import cuchaz.enigma.analysis.JarIndex; | 19 | import cuchaz.enigma.analysis.JarIndex; |
| 19 | import cuchaz.enigma.mapping.BehaviorEntry; | 20 | import cuchaz.enigma.mapping.*; |
| 20 | import cuchaz.enigma.mapping.ClassEntry; | 21 | import javassist.ClassPool; |
| 21 | import cuchaz.enigma.mapping.EntryFactory; | ||
| 22 | import javassist.CtClass; | 22 | import javassist.CtClass; |
| 23 | import javassist.bytecode.AccessFlag; | 23 | import javassist.NotFoundException; |
| 24 | import javassist.bytecode.ConstPool; | 24 | import javassist.bytecode.*; |
| 25 | import javassist.bytecode.EnclosingMethodAttribute; | ||
| 26 | import javassist.bytecode.InnerClassesAttribute; | ||
| 27 | 25 | ||
| 28 | public class InnerClassWriter { | 26 | public class InnerClassWriter { |
| 29 | 27 | ||
| 30 | private JarIndex index; | 28 | private JarIndex index; |
| 29 | private Translator deobfuscatorTranslator; | ||
| 31 | 30 | ||
| 32 | public InnerClassWriter(JarIndex index) { | 31 | public InnerClassWriter(JarIndex index, Translator deobfuscatorTranslator) { |
| 33 | this.index = index; | 32 | this.index = index; |
| 33 | this.deobfuscatorTranslator = deobfuscatorTranslator; | ||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | public void write(CtClass c) { | 36 | public void write(CtClass c) { |
| @@ -96,6 +96,29 @@ public class InnerClassWriter { | |||
| 96 | } | 96 | } |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | // FIXME: modiffier is not applied to inner class | ||
| 100 | public static void changeModifier(CtClass c, InnerClassesAttribute attr, Translator translator) | ||
| 101 | { | ||
| 102 | ClassPool pool = c.getClassPool(); | ||
| 103 | for (int i = 0; i < attr.tableLength(); i++) { | ||
| 104 | |||
| 105 | String innerName = attr.innerClass(i); | ||
| 106 | // get the inner class full name (which has already been translated) | ||
| 107 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(innerName)); | ||
| 108 | try | ||
| 109 | { | ||
| 110 | CtClass innerClass = pool.get(innerName); | ||
| 111 | Mappings.EntryModifier modifier = translator.getModifier(classEntry); | ||
| 112 | if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED) | ||
| 113 | ClassRenamer.applyModifier(innerClass, modifier); | ||
| 114 | } catch (NotFoundException e) | ||
| 115 | { | ||
| 116 | // This shouldn't be possible in theory | ||
| 117 | //e.printStackTrace(); | ||
| 118 | } | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 99 | private void writeInnerClass(InnerClassesAttribute attr, List<ClassEntry> obfClassChain, ClassEntry obfClassEntry) { | 122 | private void writeInnerClass(InnerClassesAttribute attr, List<ClassEntry> obfClassChain, ClassEntry obfClassEntry) { |
| 100 | 123 | ||
| 101 | // get the new inner class name | 124 | // get the new inner class name |