summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/ClassTranslator.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/ClassTranslator.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/ClassTranslator.java')
-rw-r--r--src/cuchaz/enigma/bytecode/ClassTranslator.java144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java
new file mode 100644
index 0000000..afd3a77
--- /dev/null
+++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java
@@ -0,0 +1,144 @@
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.Map;
14
15import javassist.CtBehavior;
16import javassist.CtClass;
17import javassist.CtField;
18import javassist.CtMethod;
19import javassist.bytecode.ConstPool;
20import javassist.bytecode.Descriptor;
21import javassist.bytecode.SourceFileAttribute;
22
23import com.google.common.collect.Maps;
24
25import cuchaz.enigma.mapping.BehaviorEntry;
26import cuchaz.enigma.mapping.BehaviorEntryFactory;
27import cuchaz.enigma.mapping.ClassEntry;
28import cuchaz.enigma.mapping.FieldEntry;
29import cuchaz.enigma.mapping.JavassistUtil;
30import cuchaz.enigma.mapping.MethodEntry;
31import cuchaz.enigma.mapping.Signature;
32import cuchaz.enigma.mapping.Translator;
33import cuchaz.enigma.mapping.Type;
34
35public class ClassTranslator {
36
37 private Translator m_translator;
38
39 public ClassTranslator(Translator translator) {
40 m_translator = translator;
41 }
42
43 public void translate(CtClass c) {
44
45 // NOTE: the order of these translations is very important
46
47 // translate all the field and method references in the code by editing the constant pool
48 ConstPool constants = c.getClassFile().getConstPool();
49 ConstPoolEditor editor = new ConstPoolEditor(constants);
50 for (int i = 1; i < constants.getSize(); i++) {
51 switch (constants.getTag(i)) {
52
53 case ConstPool.CONST_Fieldref: {
54
55 // translate the name
56 FieldEntry entry = new FieldEntry(
57 new ClassEntry(Descriptor.toJvmName(constants.getFieldrefClassName(i))),
58 constants.getFieldrefName(i)
59 );
60 FieldEntry translatedEntry = m_translator.translateEntry(entry);
61
62 // translate the type
63 Type type = new Type(constants.getFieldrefType(i));
64 Type translatedType = m_translator.translateType(type);
65
66 if (!entry.equals(translatedEntry) || !type.equals(translatedType)) {
67 editor.changeMemberrefNameAndType(i, translatedEntry.getName(), translatedType.toString());
68 }
69 }
70 break;
71
72 case ConstPool.CONST_Methodref:
73 case ConstPool.CONST_InterfaceMethodref: {
74
75 // translate the name and type
76 BehaviorEntry entry = BehaviorEntryFactory.create(
77 Descriptor.toJvmName(editor.getMemberrefClassname(i)),
78 editor.getMemberrefName(i),
79 editor.getMemberrefType(i)
80 );
81 BehaviorEntry translatedEntry = m_translator.translateEntry(entry);
82
83 if (!entry.getName().equals(translatedEntry.getName()) || !entry.getSignature().equals(translatedEntry.getSignature())) {
84 editor.changeMemberrefNameAndType(i, translatedEntry.getName(), translatedEntry.getSignature().toString());
85 }
86 }
87 break;
88 }
89 }
90
91 ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(c.getName()));
92
93 // translate all the fields
94 for (CtField field : c.getDeclaredFields()) {
95
96 // translate the name
97 FieldEntry entry = new FieldEntry(classEntry, field.getName());
98 String translatedName = m_translator.translate(entry);
99 if (translatedName != null) {
100 field.setName(translatedName);
101 }
102
103 // translate the type
104 Type translatedType = m_translator.translateType(new Type(field.getFieldInfo().getDescriptor()));
105 field.getFieldInfo().setDescriptor(translatedType.toString());
106 }
107
108 // translate all the methods and constructors
109 for (CtBehavior behavior : c.getDeclaredBehaviors()) {
110 if (behavior instanceof CtMethod) {
111 CtMethod method = (CtMethod)behavior;
112
113 // translate the name
114 MethodEntry entry = JavassistUtil.getMethodEntry(method);
115 String translatedName = m_translator.translate(entry);
116 if (translatedName != null) {
117 method.setName(translatedName);
118 }
119 }
120
121 // translate the type
122 Signature translatedSignature = m_translator.translateSignature(new Signature(behavior.getMethodInfo().getDescriptor()));
123 behavior.getMethodInfo().setDescriptor(translatedSignature.toString());
124 }
125
126 // translate all the class names referenced in the code
127 // the above code only changed method/field/reference names and types, but not the class names themselves
128 Map<ClassEntry,ClassEntry> map = Maps.newHashMap();
129 for (ClassEntry obfClassEntry : ClassRenamer.getAllClassEntries(c)) {
130 ClassEntry deobfClassEntry = m_translator.translateEntry(obfClassEntry);
131 if (!obfClassEntry.equals(deobfClassEntry)) {
132 map.put(obfClassEntry, deobfClassEntry);
133 }
134 }
135 ClassRenamer.renameClasses(c, map);
136
137 // translate the source file attribute too
138 ClassEntry deobfClassEntry = map.get(classEntry);
139 if (deobfClassEntry != null) {
140 String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOuterClassName()) + ".java";
141 c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile));
142 }
143 }
144}