summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java
diff options
context:
space:
mode:
authorGravatar Thog2017-03-08 08:17:04 +0100
committerGravatar Thog2017-03-08 08:17:04 +0100
commit6e464ea251cab63c776ece0b2a356f1498ffa294 (patch)
tree5ed30c03f5ac4cd2d6877874f5ede576049954f7 /src/main/java/cuchaz/enigma/bytecode/InnerClassWriter.java
parentDrop unix case style and implement hashCode when equals is overrided (diff)
downloadenigma-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.java239
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
11package cuchaz.enigma.bytecode; 12package cuchaz.enigma.bytecode;
12 13
13import com.google.common.collect.Lists; 14import com.google.common.collect.Lists;
14
15import java.util.Collection;
16import java.util.List;
17
18import cuchaz.enigma.analysis.JarIndex; 15import cuchaz.enigma.analysis.JarIndex;
19import cuchaz.enigma.mapping.*; 16import cuchaz.enigma.mapping.*;
20import javassist.ClassPool; 17import javassist.ClassPool;
@@ -22,126 +19,126 @@ import javassist.CtClass;
22import javassist.NotFoundException; 19import javassist.NotFoundException;
23import javassist.bytecode.*; 20import javassist.bytecode.*;
24 21
22import java.util.Collection;
23import java.util.List;
24
25public class InnerClassWriter { 25public 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}