summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java')
-rw-r--r--src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java365
1 files changed, 0 insertions, 365 deletions
diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java b/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java
deleted file mode 100644
index 8ef4f12..0000000
--- a/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java
+++ /dev/null
@@ -1,365 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.mapping;
13
14import com.google.common.collect.Lists;
15import cuchaz.enigma.analysis.JarIndex;
16import cuchaz.enigma.mapping.entry.*;
17import cuchaz.enigma.throwables.IllegalNameException;
18import cuchaz.enigma.throwables.MappingConflict;
19
20import java.io.IOException;
21import java.io.ObjectOutputStream;
22import java.io.OutputStream;
23import java.util.List;
24import java.util.Set;
25import java.util.zip.GZIPOutputStream;
26
27public class MappingsRenamer {
28
29 private final JarIndex index;
30 private final ReferencedEntryPool entryPool;
31 private Mappings mappings;
32
33 public MappingsRenamer(JarIndex index, Mappings mappings, ReferencedEntryPool entryPool) {
34 this.index = index;
35 this.mappings = mappings;
36 this.entryPool = entryPool;
37 }
38
39 public void setMappings(Mappings mappings) {
40 this.mappings = mappings;
41 }
42
43 public void setClassName(ClassEntry obf, String deobfName) {
44
45 deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass());
46
47 List<ClassMapping> mappingChain = getOrCreateClassMappingChain(obf);
48 if (mappingChain.size() == 1) {
49
50 if (deobfName != null) {
51 // make sure we don't rename to an existing obf or deobf class
52 if (mappings.containsDeobfClass(deobfName) || index.containsObfClass(entryPool.getClass(deobfName))) {
53 throw new IllegalNameException(deobfName, "There is already a class with that name");
54 }
55 }
56
57 ClassMapping classMapping = mappingChain.get(0);
58 mappings.setClassDeobfName(classMapping, deobfName);
59
60 } else {
61
62 ClassMapping outerClassMapping = mappingChain.get(mappingChain.size() - 2);
63
64 if (deobfName != null) {
65 // make sure we don't rename to an existing obf or deobf inner class
66 if (outerClassMapping.hasInnerClassByDeobf(deobfName) || outerClassMapping.hasInnerClassByObfSimple(deobfName)) {
67 throw new IllegalNameException(deobfName, "There is already a class with that name");
68 }
69 }
70
71 outerClassMapping.setInnerClassName(obf, deobfName);
72 }
73 }
74
75 public void removeClassMapping(ClassEntry obf) {
76 setClassName(obf, null);
77 }
78
79 public void markClassAsDeobfuscated(ClassEntry obf) {
80 String deobfName = obf.isInnerClass() ? obf.getInnermostClassName() : obf.getName();
81 List<ClassMapping> mappingChain = getOrCreateClassMappingChain(obf);
82 if (mappingChain.size() == 1) {
83 ClassMapping classMapping = mappingChain.get(0);
84 mappings.setClassDeobfName(classMapping, deobfName);
85 } else {
86 ClassMapping outerClassMapping = mappingChain.get(mappingChain.size() - 2);
87 outerClassMapping.setInnerClassName(obf, deobfName);
88 }
89 }
90
91 public void setFieldName(FieldEntry obf, String deobfName) {
92 deobfName = NameValidator.validateFieldName(deobfName);
93 FieldEntry targetEntry = entryPool.getField(obf.getOwnerClassEntry(), deobfName, obf.getDesc());
94 ClassEntry definedClass = null;
95 if (mappings.containsDeobfField(obf.getOwnerClassEntry(), deobfName) || index.containsEntryWithSameName(targetEntry)) {
96 definedClass = obf.getOwnerClassEntry();
97 } else {
98 for (ClassEntry ancestorEntry : this.index.getTranslationIndex().getAncestry(obf.getOwnerClassEntry())) {
99 if (mappings.containsDeobfField(ancestorEntry, deobfName) || index.containsEntryWithSameName(targetEntry.updateOwnership(ancestorEntry))) {
100 definedClass = ancestorEntry;
101 break;
102 }
103 }
104 }
105
106 if (definedClass != null) {
107 Translator translator = mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index.getTranslationIndex());
108 String className = translator.getTranslatedClass(entryPool.getClass(definedClass.getClassName())).getName();
109 if (className == null)
110 className = definedClass.getClassName();
111 throw new IllegalNameException(deobfName, "There is already a field with that name in " + className);
112 }
113
114 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
115 classMapping.setFieldName(obf.getName(), obf.getDesc(), deobfName);
116 }
117
118 public void removeFieldMapping(FieldEntry obf) {
119 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
120 classMapping.removeFieldMapping(classMapping.getFieldByObf(obf.getName(), obf.getDesc()));
121 }
122
123 public void markFieldAsDeobfuscated(FieldEntry obf) {
124 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
125 classMapping.setFieldName(obf.getName(), obf.getDesc(), obf.getName());
126 }
127
128 private void validateMethodTreeName(MethodEntry entry, String deobfName) {
129 MethodEntry targetEntry = entryPool.getMethod(entry.getOwnerClassEntry(), deobfName, entry.getDesc());
130
131 // TODO: Verify if I don't break things
132 ClassMapping classMapping = mappings.getClassByObf(entry.getOwnerClassEntry());
133 if ((classMapping != null && classMapping.containsDeobfMethod(deobfName, entry.getDesc()) && classMapping.getMethodByObf(entry.getName(), entry.getDesc()) != classMapping.getMethodByDeobf(deobfName, entry.getDesc()))
134 || index.containsObfMethod(targetEntry)) {
135 Translator translator = mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index.getTranslationIndex());
136 String deobfClassName = translator.getTranslatedClass(entryPool.getClass(entry.getClassName())).getClassName();
137 if (deobfClassName == null) {
138 deobfClassName = entry.getClassName();
139 }
140 throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName);
141 }
142
143 for (ClassEntry child : index.getTranslationIndex().getSubclass(entry.getOwnerClassEntry())) {
144 validateMethodTreeName(entry.updateOwnership(child), deobfName);
145 }
146 }
147
148 public void setMethodTreeName(MethodEntry obf, String deobfName) {
149 Set<MethodEntry> implementations = index.getRelatedMethodImplementations(obf);
150
151 deobfName = NameValidator.validateMethodName(deobfName);
152 for (MethodEntry entry : implementations) {
153 validateMethodTreeName(entry, deobfName);
154 }
155
156 for (MethodEntry entry : implementations) {
157 setMethodName(entry, deobfName);
158 }
159 }
160
161 public void setMethodName(MethodEntry obf, String deobfName) {
162 deobfName = NameValidator.validateMethodName(deobfName);
163 MethodEntry targetEntry = entryPool.getMethod(obf.getOwnerClassEntry(), deobfName, obf.getDesc());
164 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
165
166 // TODO: Verify if I don't break things
167 if ((mappings.containsDeobfMethod(obf.getOwnerClassEntry(), deobfName, obf.getDesc()) && classMapping.getMethodByObf(obf.getName(), obf.getDesc()) != classMapping.getMethodByDeobf(deobfName, obf.getDesc()))
168 || index.containsObfMethod(targetEntry)) {
169 Translator translator = mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index.getTranslationIndex());
170 String deobfClassName = translator.getTranslatedClass(entryPool.getClass(obf.getClassName())).getClassName();
171 if (deobfClassName == null) {
172 deobfClassName = obf.getClassName();
173 }
174 throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName);
175 }
176
177 classMapping.setMethodName(obf.getName(), obf.getDesc(), deobfName);
178 }
179
180 public void removeMethodTreeMapping(MethodEntry obf) {
181 index.getRelatedMethodImplementations(obf).forEach(this::removeMethodMapping);
182 }
183
184 public void removeMethodMapping(MethodEntry obf) {
185 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
186 classMapping.setMethodName(obf.getName(), obf.getDesc(), null);
187 }
188
189 public void markMethodTreeAsDeobfuscated(MethodEntry obf) {
190 index.getRelatedMethodImplementations(obf).forEach(this::markMethodAsDeobfuscated);
191 }
192
193 public void markMethodAsDeobfuscated(MethodEntry obf) {
194 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
195 classMapping.setMethodName(obf.getName(), obf.getDesc(), obf.getName());
196 }
197
198 public void setLocalVariableTreeName(LocalVariableEntry obf, String deobfName) {
199 MethodEntry obfMethod = obf.getOwnerEntry();
200 if (!obf.isParameter()) {
201 setLocalVariableName(obf, deobfName);
202 return;
203 }
204
205 Set<MethodEntry> implementations = index.getRelatedMethodImplementations(obfMethod);
206 for (MethodEntry entry : implementations) {
207 ClassMapping classMapping = mappings.getClassByObf(entry.getOwnerClassEntry());
208 if (classMapping != null) {
209 MethodMapping mapping = classMapping.getMethodByObf(entry.getName(), entry.getDesc());
210 // NOTE: don't need to check arguments for name collisions with names determined by Procyon
211 // TODO: Verify if I don't break things
212 if (mapping != null) {
213 for (LocalVariableMapping localVariableMapping : Lists.newArrayList(mapping.arguments())) {
214 if (localVariableMapping.getIndex() != obf.getIndex()) {
215 if (mapping.getDeobfLocalVariableName(localVariableMapping.getIndex()).equals(deobfName)
216 || localVariableMapping.getName().equals(deobfName)) {
217 throw new IllegalNameException(deobfName, "There is already an argument with that name");
218 }
219 }
220 }
221 }
222 }
223 }
224
225 for (MethodEntry entry : implementations) {
226 setLocalVariableName(new LocalVariableEntry(entry, obf.getIndex(), obf.getName(), obf.isParameter()), deobfName);
227 }
228 }
229
230 public void setLocalVariableName(LocalVariableEntry obf, String deobfName) {
231 deobfName = NameValidator.validateArgumentName(deobfName);
232 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
233 MethodMapping mapping = classMapping.getMethodByObf(obf.getMethodName(), obf.getMethodDesc());
234 // NOTE: don't need to check arguments for name collisions with names determined by Procyon
235 // TODO: Verify if I don't break things
236 if (mapping != null) {
237 for (LocalVariableMapping localVariableMapping : Lists.newArrayList(mapping.arguments())) {
238 if (localVariableMapping.getIndex() != obf.getIndex()) {
239 if (mapping.getDeobfLocalVariableName(localVariableMapping.getIndex()).equals(deobfName)
240 || localVariableMapping.getName().equals(deobfName)) {
241 throw new IllegalNameException(deobfName, "There is already an argument with that name");
242 }
243 }
244 }
245 }
246
247 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodDesc(), obf.getIndex(), deobfName);
248 }
249
250 public void removeLocalVariableMapping(LocalVariableEntry obf) {
251 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
252 classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodDesc(), obf.getIndex());
253 }
254
255 public void markArgumentAsDeobfuscated(LocalVariableEntry obf) {
256 ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry());
257 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodDesc(), obf.getIndex(), obf.getName());
258 }
259
260 public boolean moveFieldToObfClass(ClassMapping classMapping, FieldMapping fieldMapping, ClassEntry obfClass) {
261 classMapping.removeFieldMapping(fieldMapping);
262 ClassMapping targetClassMapping = getOrCreateClassMapping(obfClass);
263 if (!targetClassMapping.containsObfField(fieldMapping.getObfName(), fieldMapping.getObfDesc())) {
264 if (!targetClassMapping.containsDeobfField(fieldMapping.getDeobfName(), fieldMapping.getObfDesc())) {
265 targetClassMapping.addFieldMapping(fieldMapping);
266 return true;
267 } else {
268 System.err.println("WARNING: deobf field was already there: " + obfClass + "." + fieldMapping.getDeobfName());
269 }
270 }
271 return false;
272 }
273
274 public boolean moveMethodToObfClass(ClassMapping classMapping, MethodMapping methodMapping, ClassEntry obfClass) {
275 classMapping.removeMethodMapping(methodMapping);
276 ClassMapping targetClassMapping = getOrCreateClassMapping(obfClass);
277 if (!targetClassMapping.containsObfMethod(methodMapping.getObfName(), methodMapping.getObfDesc())) {
278 if (!targetClassMapping.containsDeobfMethod(methodMapping.getDeobfName(), methodMapping.getObfDesc())) {
279 targetClassMapping.addMethodMapping(methodMapping);
280 return true;
281 } else {
282 System.err.println("WARNING: deobf method was already there: " + obfClass + "." + methodMapping.getDeobfName() + methodMapping.getObfDesc());
283 }
284 }
285 return false;
286 }
287
288 public void write(OutputStream out) throws IOException {
289 // TEMP: just use the object output for now. We can find a more efficient storage format later
290 GZIPOutputStream gzipout = new GZIPOutputStream(out);
291 ObjectOutputStream oout = new ObjectOutputStream(gzipout);
292 oout.writeObject(this);
293 gzipout.finish();
294 }
295
296 private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) {
297 List<ClassMapping> mappingChain = getOrCreateClassMappingChain(obfClassEntry);
298 return mappingChain.get(mappingChain.size() - 1);
299 }
300
301 private List<ClassMapping> getOrCreateClassMappingChain(ClassEntry obfClassEntry) {
302 List<ClassEntry> classChain = obfClassEntry.getClassChain();
303 List<ClassMapping> mappingChain = mappings.getClassMappingChain(obfClassEntry);
304 for (int i = 0; i < classChain.size(); i++) {
305 ClassEntry classEntry = classChain.get(i);
306 ClassMapping classMapping = mappingChain.get(i);
307 if (classMapping == null) {
308
309 // create it
310 classMapping = new ClassMapping(classEntry.getName());
311 mappingChain.set(i, classMapping);
312
313 // add it to the right parent
314 try {
315 if (i == 0) {
316 mappings.addClassMapping(classMapping);
317 } else {
318 mappingChain.get(i - 1).addInnerClassMapping(classMapping);
319 }
320 } catch (MappingConflict mappingConflict) {
321 mappingConflict.printStackTrace();
322 }
323 }
324 }
325 return mappingChain;
326 }
327
328 public void setClassModifier(ClassEntry obEntry, Mappings.EntryModifier modifier) {
329 ClassMapping classMapping = getOrCreateClassMapping(obEntry);
330 classMapping.setModifier(modifier);
331 }
332
333 public void setFieldModifier(FieldEntry obEntry, Mappings.EntryModifier modifier) {
334 ClassMapping classMapping = getOrCreateClassMapping(obEntry.getOwnerClassEntry());
335 classMapping.setFieldModifier(obEntry.getName(), obEntry.getDesc(), modifier);
336 }
337
338 public void setMethodModifier(MethodEntry obEntry, Mappings.EntryModifier modifier) {
339 ClassMapping classMapping = getOrCreateClassMapping(obEntry.getOwnerClassEntry());
340 classMapping.setMethodModifier(obEntry.getName(), obEntry.getDesc(), modifier);
341 }
342
343 public Mappings.EntryModifier getClassModifier(ClassEntry obfEntry) {
344 ClassMapping classMapping = getOrCreateClassMapping(obfEntry);
345 return classMapping.getModifier();
346 }
347
348 public Mappings.EntryModifier getFieldModifier(FieldEntry obfEntry) {
349 ClassMapping classMapping = getOrCreateClassMapping(obfEntry.getOwnerClassEntry());
350 FieldMapping fieldMapping = classMapping.getFieldByObf(obfEntry);
351 if (fieldMapping == null) {
352 return Mappings.EntryModifier.UNCHANGED;
353 }
354 return fieldMapping.getModifier();
355 }
356
357 public Mappings.EntryModifier getMethodModfifier(MethodEntry obfEntry) {
358 ClassMapping classMapping = getOrCreateClassMapping(obfEntry.getOwnerClassEntry());
359 MethodMapping methodMapping = classMapping.getMethodByObf(obfEntry);
360 if (methodMapping == null) {
361 return Mappings.EntryModifier.UNCHANGED;
362 }
363 return methodMapping.getModifier();
364 }
365}