summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/InnerClassWriter.java
diff options
context:
space:
mode:
authorGravatar jeff2015-02-08 21:29:25 -0500
committerGravatar jeff2015-02-08 21:29:25 -0500
commited9b5cdfc648e86fd463bfa8d86b94c41671e14c (patch)
tree2619bbc7e04dfa3b82f8dfd3b1d31f529766cd4b /src/cuchaz/enigma/bytecode/InnerClassWriter.java
downloadenigma-fork-ed9b5cdfc648e86fd463bfa8d86b94c41671e14c.tar.gz
enigma-fork-ed9b5cdfc648e86fd463bfa8d86b94c41671e14c.tar.xz
enigma-fork-ed9b5cdfc648e86fd463bfa8d86b94c41671e14c.zip
switch all classes to new signature/type system
Diffstat (limited to 'src/cuchaz/enigma/bytecode/InnerClassWriter.java')
-rw-r--r--src/cuchaz/enigma/bytecode/InnerClassWriter.java102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
new file mode 100644
index 0000000..817500b
--- /dev/null
+++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
@@ -0,0 +1,102 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode;
12
13import java.util.Collection;
14
15import javassist.CtClass;
16import javassist.bytecode.AccessFlag;
17import javassist.bytecode.ConstPool;
18import javassist.bytecode.Descriptor;
19import javassist.bytecode.EnclosingMethodAttribute;
20import javassist.bytecode.InnerClassesAttribute;
21import cuchaz.enigma.Constants;
22import cuchaz.enigma.analysis.JarIndex;
23import cuchaz.enigma.mapping.BehaviorEntry;
24import cuchaz.enigma.mapping.ClassEntry;
25
26public class InnerClassWriter {
27
28 private JarIndex m_jarIndex;
29
30 public InnerClassWriter(JarIndex jarIndex) {
31 m_jarIndex = jarIndex;
32 }
33
34 public void write(CtClass c) {
35
36 // is this an inner or outer class?
37 String obfInnerClassName = new ClassEntry(Descriptor.toJvmName(c.getName())).getSimpleName();
38 String obfOuterClassName = m_jarIndex.getOuterClass(obfInnerClassName);
39 if (obfOuterClassName == null) {
40 // this is an outer class
41 obfOuterClassName = Descriptor.toJvmName(c.getName());
42 } else {
43 // this is an inner class, rename it to outer$inner
44 ClassEntry obfClassEntry = new ClassEntry(obfOuterClassName + "$" + obfInnerClassName);
45 c.setName(obfClassEntry.getName());
46
47 BehaviorEntry caller = m_jarIndex.getAnonymousClassCaller(obfInnerClassName);
48 if (caller != null) {
49 // write the enclosing method attribute
50 if (caller.getName().equals("<clinit>")) {
51 c.getClassFile().addAttribute(new EnclosingMethodAttribute(c.getClassFile().getConstPool(), caller.getClassName()));
52 } else {
53 c.getClassFile().addAttribute(new EnclosingMethodAttribute(c.getClassFile().getConstPool(), caller.getClassName(), caller.getName(), caller.getSignature().toString()));
54 }
55 }
56 }
57
58 // write the inner classes if needed
59 Collection<String> obfInnerClassNames = m_jarIndex.getInnerClasses(obfOuterClassName);
60 if (obfInnerClassNames != null && !obfInnerClassNames.isEmpty()) {
61 writeInnerClasses(c, obfOuterClassName, obfInnerClassNames);
62 }
63 }
64
65 private void writeInnerClasses(CtClass c, String obfOuterClassName, Collection<String> obfInnerClassNames) {
66 InnerClassesAttribute attr = new InnerClassesAttribute(c.getClassFile().getConstPool());
67 c.getClassFile().addAttribute(attr);
68 for (String obfInnerClassName : obfInnerClassNames) {
69 // get the new inner class name
70 ClassEntry obfClassEntry = new ClassEntry(obfOuterClassName + "$" + obfInnerClassName);
71
72 // here's what the JVM spec says about the InnerClasses attribute
73 // append( inner, outer of inner if inner is member of outer 0 ow, name after $ if inner not anonymous 0 ow, flags );
74
75 // update the attribute with this inner class
76 ConstPool constPool = c.getClassFile().getConstPool();
77 int innerClassIndex = constPool.addClassInfo(obfClassEntry.getName());
78 int outerClassIndex = 0;
79 int innerClassSimpleNameIndex = 0;
80 if (!m_jarIndex.isAnonymousClass(obfInnerClassName)) {
81 outerClassIndex = constPool.addClassInfo(obfClassEntry.getOuterClassName());
82 innerClassSimpleNameIndex = constPool.addUtf8Info(obfClassEntry.getInnerClassName());
83 }
84
85 attr.append(innerClassIndex, outerClassIndex, innerClassSimpleNameIndex, c.getClassFile().getAccessFlags() & ~AccessFlag.SUPER);
86
87 /* DEBUG
88 System.out.println(String.format("\tOBF: %s -> ATTR: %s,%s,%s (replace %s with %s)",
89 obfClassEntry,
90 attr.outerClass(attr.tableLength() - 1),
91 attr.innerClass(attr.tableLength() - 1),
92 attr.innerName(attr.tableLength() - 1),
93 Constants.NonePackage + "/" + obfInnerClassName,
94 obfClassEntry.getName()
95 ));
96 */
97
98 // make sure the outer class references only the new inner class names
99 c.replaceClassName(Constants.NonePackage + "/" + obfInnerClassName, obfClassEntry.getName());
100 }
101 }
102}