diff options
| author | 2017-03-08 08:17:04 +0100 | |
|---|---|---|
| committer | 2017-03-08 08:17:04 +0100 | |
| commit | 6e464ea251cab63c776ece0b2a356f1498ffa294 (patch) | |
| tree | 5ed30c03f5ac4cd2d6877874f5ede576049954f7 /src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java | |
| parent | Drop unix case style and implement hashCode when equals is overrided (diff) | |
| download | enigma-fork-6e464ea251cab63c776ece0b2a356f1498ffa294.tar.gz enigma-fork-6e464ea251cab63c776ece0b2a356f1498ffa294.tar.xz enigma-fork-6e464ea251cab63c776ece0b2a356f1498ffa294.zip | |
Follow Fabric guidelines
Diffstat (limited to 'src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java')
| -rw-r--r-- | src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java | 239 |
1 files changed, 118 insertions, 121 deletions
diff --git a/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java index eb70c23..5f8be90 100644 --- a/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java +++ b/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java | |||
| @@ -8,13 +8,10 @@ | |||
| 8 | * Contributors: | 8 | * Contributors: |
| 9 | * Jeff Martin - initial API and implementation | 9 | * Jeff Martin - initial API and implementation |
| 10 | ******************************************************************************/ | 10 | ******************************************************************************/ |
| 11 | |||
| 11 | package cuchaz.enigma.bytecode; | 12 | package cuchaz.enigma.bytecode; |
| 12 | 13 | ||
| 13 | import com.google.common.collect.Lists; | 14 | import com.google.common.collect.Lists; |
| 14 | |||
| 15 | import java.util.Collection; | ||
| 16 | import java.util.List; | ||
| 17 | |||
| 18 | import cuchaz.enigma.analysis.JarIndex; | 15 | import cuchaz.enigma.analysis.JarIndex; |
| 19 | import cuchaz.enigma.mapping.*; | 16 | import cuchaz.enigma.mapping.*; |
| 20 | import javassist.ClassPool; | 17 | import javassist.ClassPool; |
| @@ -22,126 +19,126 @@ import javassist.CtClass; | |||
| 22 | import javassist.NotFoundException; | 19 | import javassist.NotFoundException; |
| 23 | import javassist.bytecode.*; | 20 | import javassist.bytecode.*; |
| 24 | 21 | ||
| 22 | import java.util.Collection; | ||
| 23 | import java.util.List; | ||
| 24 | |||
| 25 | public class InnerClassWriter { | 25 | public class InnerClassWriter { |
| 26 | 26 | ||
| 27 | private JarIndex index; | 27 | private JarIndex index; |
| 28 | private Translator deobfuscatorTranslator; | 28 | private Translator deobfuscatorTranslator; |
| 29 | 29 | ||
| 30 | public InnerClassWriter(JarIndex index, Translator deobfuscatorTranslator) { | 30 | public InnerClassWriter(JarIndex index, Translator deobfuscatorTranslator) { |
| 31 | this.index = index; | 31 | this.index = index; |
| 32 | this.deobfuscatorTranslator = deobfuscatorTranslator; | 32 | this.deobfuscatorTranslator = deobfuscatorTranslator; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | public void write(CtClass c) { | 35 | // FIXME: modiffier is not applied to inner class |
| 36 | 36 | public static void changeModifier(CtClass c, InnerClassesAttribute attr, Translator translator) { | |
| 37 | // don't change anything if there's already an attribute there | 37 | ClassPool pool = c.getClassPool(); |
| 38 | InnerClassesAttribute oldAttr = (InnerClassesAttribute) c.getClassFile().getAttribute(InnerClassesAttribute.tag); | 38 | for (int i = 0; i < attr.tableLength(); i++) { |
| 39 | if (oldAttr != null) { | 39 | |
| 40 | // bail! | 40 | String innerName = attr.innerClass(i); |
| 41 | return; | 41 | // get the inner class full name (which has already been translated) |
| 42 | } | 42 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(innerName)); |
| 43 | 43 | try { | |
| 44 | ClassEntry obfClassEntry = EntryFactory.getClassEntry(c); | 44 | CtClass innerClass = pool.get(innerName); |
| 45 | List<ClassEntry> obfClassChain = this.index.getObfClassChain(obfClassEntry); | 45 | Mappings.EntryModifier modifier = translator.getModifier(classEntry); |
| 46 | 46 | if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED) | |
| 47 | boolean isInnerClass = obfClassChain.size() > 1; | 47 | ClassRenamer.applyModifier(innerClass, modifier); |
| 48 | if (isInnerClass) { | 48 | } catch (NotFoundException e) { |
| 49 | 49 | // This shouldn't be possible in theory | |
| 50 | // it's an inner class, rename it to the fully qualified name | 50 | //e.printStackTrace(); |
| 51 | c.setName(obfClassEntry.buildClassEntry(obfClassChain).getName()); | 51 | } |
| 52 | 52 | } | |
| 53 | BehaviorEntry caller = this.index.getAnonymousClassCaller(obfClassEntry); | 53 | } |
| 54 | if (caller != null) { | 54 | |
| 55 | 55 | public void write(CtClass c) { | |
| 56 | // write the enclosing method attribute | 56 | |
| 57 | if (caller.getName().equals("<clinit>")) { | 57 | // don't change anything if there's already an attribute there |
| 58 | c.getClassFile().addAttribute(new EnclosingMethodAttribute(c.getClassFile().getConstPool(), caller.getClassName())); | 58 | InnerClassesAttribute oldAttr = (InnerClassesAttribute) c.getClassFile().getAttribute(InnerClassesAttribute.tag); |
| 59 | } else { | 59 | if (oldAttr != null) { |
| 60 | c.getClassFile().addAttribute(new EnclosingMethodAttribute(c.getClassFile().getConstPool(), caller.getClassName(), caller.getName(), caller.getSignature().toString())); | 60 | // bail! |
| 61 | } | 61 | return; |
| 62 | } | 62 | } |
| 63 | } | 63 | |
| 64 | 64 | ClassEntry obfClassEntry = EntryFactory.getClassEntry(c); | |
| 65 | // does this class have any inner classes? | 65 | List<ClassEntry> obfClassChain = this.index.getObfClassChain(obfClassEntry); |
| 66 | Collection<ClassEntry> obfInnerClassEntries = this.index.getInnerClasses(obfClassEntry); | 66 | |
| 67 | 67 | boolean isInnerClass = obfClassChain.size() > 1; | |
| 68 | if (isInnerClass || !obfInnerClassEntries.isEmpty()) { | 68 | if (isInnerClass) { |
| 69 | 69 | ||
| 70 | // create an inner class attribute | 70 | // it's an inner class, rename it to the fully qualified name |
| 71 | InnerClassesAttribute attr = new InnerClassesAttribute(c.getClassFile().getConstPool()); | 71 | c.setName(obfClassEntry.buildClassEntry(obfClassChain).getName()); |
| 72 | c.getClassFile().addAttribute(attr); | 72 | |
| 73 | 73 | BehaviorEntry caller = this.index.getAnonymousClassCaller(obfClassEntry); | |
| 74 | // write the ancestry, but not the outermost class | 74 | if (caller != null) { |
| 75 | for (int i = 1; i < obfClassChain.size(); i++) { | 75 | |
| 76 | ClassEntry obfInnerClassEntry = obfClassChain.get(i); | 76 | // write the enclosing method attribute |
| 77 | writeInnerClass(attr, obfClassChain, obfInnerClassEntry); | 77 | if (caller.getName().equals("<clinit>")) { |
| 78 | 78 | c.getClassFile().addAttribute(new EnclosingMethodAttribute(c.getClassFile().getConstPool(), caller.getClassName())); | |
| 79 | // update references to use the fully qualified inner class name | 79 | } else { |
| 80 | c.replaceClassName(obfInnerClassEntry.getName(), obfInnerClassEntry.buildClassEntry(obfClassChain).getName()); | 80 | c.getClassFile().addAttribute(new EnclosingMethodAttribute(c.getClassFile().getConstPool(), caller.getClassName(), caller.getName(), caller.getSignature().toString())); |
| 81 | } | 81 | } |
| 82 | 82 | } | |
| 83 | // write the inner classes | 83 | } |
| 84 | for (ClassEntry obfInnerClassEntry : obfInnerClassEntries) { | 84 | |
| 85 | 85 | // does this class have any inner classes? | |
| 86 | // extend the class chain | 86 | Collection<ClassEntry> obfInnerClassEntries = this.index.getInnerClasses(obfClassEntry); |
| 87 | List<ClassEntry> extendedObfClassChain = Lists.newArrayList(obfClassChain); | 87 | |
| 88 | extendedObfClassChain.add(obfInnerClassEntry); | 88 | if (isInnerClass || !obfInnerClassEntries.isEmpty()) { |
| 89 | 89 | ||
| 90 | writeInnerClass(attr, extendedObfClassChain, obfInnerClassEntry); | 90 | // create an inner class attribute |
| 91 | 91 | InnerClassesAttribute attr = new InnerClassesAttribute(c.getClassFile().getConstPool()); | |
| 92 | // update references to use the fully qualified inner class name | 92 | c.getClassFile().addAttribute(attr); |
| 93 | c.replaceClassName(obfInnerClassEntry.getName(), obfInnerClassEntry.buildClassEntry(extendedObfClassChain).getName()); | 93 | |
| 94 | } | 94 | // write the ancestry, but not the outermost class |
| 95 | } | 95 | for (int i = 1; i < obfClassChain.size(); i++) { |
| 96 | } | 96 | ClassEntry obfInnerClassEntry = obfClassChain.get(i); |
| 97 | 97 | writeInnerClass(attr, obfClassChain, obfInnerClassEntry); | |
| 98 | // FIXME: modiffier is not applied to inner class | 98 | |
| 99 | public static void changeModifier(CtClass c, InnerClassesAttribute attr, Translator translator) | 99 | // update references to use the fully qualified inner class name |
| 100 | { | 100 | c.replaceClassName(obfInnerClassEntry.getName(), obfInnerClassEntry.buildClassEntry(obfClassChain).getName()); |
| 101 | ClassPool pool = c.getClassPool(); | 101 | } |
| 102 | for (int i = 0; i < attr.tableLength(); i++) { | 102 | |
| 103 | 103 | // write the inner classes | |
| 104 | String innerName = attr.innerClass(i); | 104 | for (ClassEntry obfInnerClassEntry : obfInnerClassEntries) { |
| 105 | // get the inner class full name (which has already been translated) | 105 | |
| 106 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(innerName)); | 106 | // extend the class chain |
| 107 | try | 107 | List<ClassEntry> extendedObfClassChain = Lists.newArrayList(obfClassChain); |
| 108 | { | 108 | extendedObfClassChain.add(obfInnerClassEntry); |
| 109 | CtClass innerClass = pool.get(innerName); | 109 | |
| 110 | Mappings.EntryModifier modifier = translator.getModifier(classEntry); | 110 | writeInnerClass(attr, extendedObfClassChain, obfInnerClassEntry); |
| 111 | if (modifier != null && modifier != Mappings.EntryModifier.UNCHANGED) | 111 | |
| 112 | ClassRenamer.applyModifier(innerClass, modifier); | 112 | // update references to use the fully qualified inner class name |
| 113 | } catch (NotFoundException e) | 113 | c.replaceClassName(obfInnerClassEntry.getName(), obfInnerClassEntry.buildClassEntry(extendedObfClassChain).getName()); |
| 114 | { | 114 | } |
| 115 | // This shouldn't be possible in theory | 115 | } |
| 116 | //e.printStackTrace(); | 116 | } |
| 117 | } | 117 | |
| 118 | } | 118 | private void writeInnerClass(InnerClassesAttribute attr, List<ClassEntry> obfClassChain, ClassEntry obfClassEntry) { |
| 119 | } | 119 | |
| 120 | 120 | // get the new inner class name | |
| 121 | private void writeInnerClass(InnerClassesAttribute attr, List<ClassEntry> obfClassChain, ClassEntry obfClassEntry) { | 121 | ClassEntry obfInnerClassEntry = obfClassEntry.buildClassEntry(obfClassChain); |
| 122 | 122 | ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOuterClassEntry(); | |
| 123 | // get the new inner class name | 123 | |
| 124 | ClassEntry obfInnerClassEntry = obfClassEntry.buildClassEntry(obfClassChain); | 124 | // here's what the JVM spec says about the InnerClasses attribute |
| 125 | ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOuterClassEntry(); | 125 | // append(inner, parent, 0 if anonymous else simple name, flags); |
| 126 | 126 | ||
| 127 | // here's what the JVM spec says about the InnerClasses attribute | 127 | // update the attribute with this inner class |
| 128 | // append(inner, parent, 0 if anonymous else simple name, flags); | 128 | ConstPool constPool = attr.getConstPool(); |
| 129 | 129 | int innerClassIndex = constPool.addClassInfo(obfInnerClassEntry.getName()); | |
| 130 | // update the attribute with this inner class | 130 | int parentClassIndex = constPool.addClassInfo(obfOuterClassEntry.getName()); |
| 131 | ConstPool constPool = attr.getConstPool(); | 131 | int innerClassNameIndex = 0; |
| 132 | int innerClassIndex = constPool.addClassInfo(obfInnerClassEntry.getName()); | 132 | int accessFlags = AccessFlag.PUBLIC; |
| 133 | int parentClassIndex = constPool.addClassInfo(obfOuterClassEntry.getName()); | 133 | // TODO: need to figure out if we can put static or not |
| 134 | int innerClassNameIndex = 0; | 134 | if (!this.index.isAnonymousClass(obfClassEntry)) { |
| 135 | int accessFlags = AccessFlag.PUBLIC; | 135 | innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnermostClassName()); |
| 136 | // TODO: need to figure out if we can put static or not | 136 | } |
| 137 | if (!this.index.isAnonymousClass(obfClassEntry)) { | 137 | |
| 138 | innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnermostClassName()); | 138 | attr.append(innerClassIndex, parentClassIndex, innerClassNameIndex, accessFlags); |
| 139 | } | ||
| 140 | |||
| 141 | attr.append(innerClassIndex, parentClassIndex, innerClassNameIndex, accessFlags); | ||
| 142 | 139 | ||
| 143 | /* DEBUG | 140 | /* DEBUG |
| 144 | System.out.println(String.format("\tOBF: %s -> ATTR: %s,%s,%s (replace %s with %s)", | 141 | System.out.println(String.format("\tOBF: %s -> ATTR: %s,%s,%s (replace %s with %s)", |
| 145 | obfClassEntry, | 142 | obfClassEntry, |
| 146 | attr.innerClass(attr.tableLength() - 1), | 143 | attr.innerClass(attr.tableLength() - 1), |
| 147 | attr.outerClass(attr.tableLength() - 1), | 144 | attr.outerClass(attr.tableLength() - 1), |
| @@ -150,5 +147,5 @@ public class InnerClassWriter { | |||
| 150 | obfClassEntry.getName() | 147 | obfClassEntry.getName() |
| 151 | )); | 148 | )); |
| 152 | */ | 149 | */ |
| 153 | } | 150 | } |
| 154 | } | 151 | } |