summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/Deobfuscator.java
diff options
context:
space:
mode:
authorGravatar gegy10002018-05-19 17:02:46 +0200
committerGravatar gegy10002018-05-19 17:02:46 +0200
commit2b2249e873c4adfd2dd6e8f1f2489ccd9f6aa021 (patch)
tree14c8b1e806449ace1641a1dbafae162855f79670 /src/main/java/cuchaz/enigma/Deobfuscator.java
parentFix build (diff)
downloadenigma-fork-2b2249e873c4adfd2dd6e8f1f2489ccd9f6aa021.tar.gz
enigma-fork-2b2249e873c4adfd2dd6e8f1f2489ccd9f6aa021.tar.xz
enigma-fork-2b2249e873c4adfd2dd6e8f1f2489ccd9f6aa021.zip
Initial port to ASM
Diffstat (limited to 'src/main/java/cuchaz/enigma/Deobfuscator.java')
-rw-r--r--src/main/java/cuchaz/enigma/Deobfuscator.java225
1 files changed, 119 insertions, 106 deletions
diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java
index 1e99af2..e1454c7 100644
--- a/src/main/java/cuchaz/enigma/Deobfuscator.java
+++ b/src/main/java/cuchaz/enigma/Deobfuscator.java
@@ -31,50 +31,55 @@ import cuchaz.enigma.bytecode.ClassPublifier;
31import cuchaz.enigma.mapping.*; 31import cuchaz.enigma.mapping.*;
32import cuchaz.enigma.throwables.IllegalNameException; 32import cuchaz.enigma.throwables.IllegalNameException;
33import cuchaz.enigma.utils.Utils; 33import cuchaz.enigma.utils.Utils;
34import javassist.CtClass; 34import org.objectweb.asm.ClassWriter;
35import javassist.bytecode.Descriptor; 35import org.objectweb.asm.Opcodes;
36import org.objectweb.asm.tree.ClassNode;
36 37
37import java.io.*; 38import java.io.*;
38import java.util.*; 39import java.util.*;
40import java.util.concurrent.atomic.AtomicInteger;
39import java.util.jar.JarEntry; 41import java.util.jar.JarEntry;
40import java.util.jar.JarFile; 42import java.util.jar.JarFile;
41import java.util.jar.JarOutputStream; 43import java.util.jar.JarOutputStream;
42 44
43public class Deobfuscator { 45public class Deobfuscator {
44 46
47 private final ReferencedEntryPool entryPool = new ReferencedEntryPool();
45 private final JarFile jar; 48 private final JarFile jar;
49 private final ParsedJar parsedJar;
46 private final DecompilerSettings settings; 50 private final DecompilerSettings settings;
47 private final JarIndex jarIndex; 51 private final JarIndex jarIndex;
48 private final MappingsRenamer renamer; 52 private final MappingsRenamer renamer;
49 private final Map<TranslationDirection, Translator> translatorCache; 53 private final Map<TranslationDirection, Translator> translatorCache;
50 private Mappings mappings; 54 private Mappings mappings;
51 55
52 public Deobfuscator(JarFile jar) { 56 public Deobfuscator(JarFile jar) throws IOException {
53 this.jar = jar; 57 this.jar = jar;
58 this.parsedJar = new ParsedJar(jar);
54 59
55 // build the jar index 60 // build the jar index
56 this.jarIndex = new JarIndex(); 61 this.jarIndex = new JarIndex(entryPool);
57 this.jarIndex.indexJar(this.jar, true); 62 this.jarIndex.indexJar(this.parsedJar, true);
58 63
59 // config the decompiler 64 // config the decompiler
60 this.settings = DecompilerSettings.javaDefaults(); 65 this.settings = DecompilerSettings.javaDefaults();
61 this.settings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true)); 66 this.settings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true));
62 this.settings.setForceExplicitImports(Utils.getSystemPropertyAsBoolean("enigma.forceExplicitImports", true)); 67 this.settings.setForceExplicitImports(Utils.getSystemPropertyAsBoolean("enigma.forceExplicitImports", true));
63 this.settings.setForceExplicitTypeArguments( 68 this.settings.setForceExplicitTypeArguments(
64 Utils.getSystemPropertyAsBoolean("enigma.forceExplicitTypeArguments", true)); 69 Utils.getSystemPropertyAsBoolean("enigma.forceExplicitTypeArguments", true));
65 // DEBUG 70 // DEBUG
66 this.settings.setShowDebugLineNumbers(Utils.getSystemPropertyAsBoolean("enigma.showDebugLineNumbers", false)); 71 this.settings.setShowDebugLineNumbers(Utils.getSystemPropertyAsBoolean("enigma.showDebugLineNumbers", false));
67 this.settings.setShowSyntheticMembers(Utils.getSystemPropertyAsBoolean("enigma.showSyntheticMembers", false)); 72 this.settings.setShowSyntheticMembers(Utils.getSystemPropertyAsBoolean("enigma.showSyntheticMembers", false));
68 73
69 // init defaults 74 // init defaults
70 this.translatorCache = Maps.newTreeMap(); 75 this.translatorCache = Maps.newTreeMap();
71 this.renamer = new MappingsRenamer(this.jarIndex, null); 76 this.renamer = new MappingsRenamer(this.jarIndex, null, this.entryPool);
72 // init mappings 77 // init mappings
73 setMappings(new Mappings()); 78 setMappings(new Mappings());
74 } 79 }
75 80
76 public JarFile getJar() { 81 public ParsedJar getJar() {
77 return this.jar; 82 return this.parsedJar;
78 } 83 }
79 84
80 public String getJarName() { 85 public String getJarName() {
@@ -102,16 +107,16 @@ public class Deobfuscator {
102 MappingsChecker checker = new MappingsChecker(this.jarIndex); 107 MappingsChecker checker = new MappingsChecker(this.jarIndex);
103 checker.dropBrokenMappings(val); 108 checker.dropBrokenMappings(val);
104 if (warnAboutDrops) { 109 if (warnAboutDrops) {
105 for (java.util.Map.Entry<ClassEntry, ClassMapping> mapping : checker.getDroppedClassMappings().entrySet()) { 110 for (Map.Entry<ClassEntry, ClassMapping> mapping : checker.getDroppedClassMappings().entrySet()) {
106 System.out.println("WARNING: Couldn't find class entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped."); 111 System.out.println("WARNING: Couldn't find class entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped.");
107 } 112 }
108 for (java.util.Map.Entry<ClassEntry, ClassMapping> mapping : checker.getDroppedInnerClassMappings().entrySet()) { 113 for (Map.Entry<ClassEntry, ClassMapping> mapping : checker.getDroppedInnerClassMappings().entrySet()) {
109 System.out.println("WARNING: Couldn't find inner class entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped."); 114 System.out.println("WARNING: Couldn't find inner class entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped.");
110 } 115 }
111 for (java.util.Map.Entry<FieldEntry, FieldMapping> mapping : checker.getDroppedFieldMappings().entrySet()) { 116 for (Map.Entry<FieldEntry, FieldMapping> mapping : checker.getDroppedFieldMappings().entrySet()) {
112 System.out.println("WARNING: Couldn't find field entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped."); 117 System.out.println("WARNING: Couldn't find field entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped.");
113 } 118 }
114 for (java.util.Map.Entry<BehaviorEntry, MethodMapping> mapping : checker.getDroppedMethodMappings().entrySet()) { 119 for (Map.Entry<MethodEntry, MethodMapping> mapping : checker.getDroppedMethodMappings().entrySet()) {
115 System.out.println("WARNING: Couldn't find behavior entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped."); 120 System.out.println("WARNING: Couldn't find behavior entry " + mapping.getKey() + " (" + mapping.getValue().getDeobfName() + ") in jar. Mapping was dropped.");
116 } 121 }
117 } 122 }
@@ -123,7 +128,7 @@ public class Deobfuscator {
123 128
124 public Translator getTranslator(TranslationDirection direction) { 129 public Translator getTranslator(TranslationDirection direction) {
125 return this.translatorCache.computeIfAbsent(direction, 130 return this.translatorCache.computeIfAbsent(direction,
126 k -> this.mappings.getTranslator(direction, this.jarIndex.getTranslationIndex())); 131 k -> this.mappings.getTranslator(direction, this.jarIndex.getTranslationIndex()));
127 } 132 }
128 133
129 public void getSeparatedClasses(List<ClassEntry> obfClasses, List<ClassEntry> deobfClasses) { 134 public void getSeparatedClasses(List<ClassEntry> obfClasses, List<ClassEntry> deobfClasses) {
@@ -150,10 +155,11 @@ public class Deobfuscator {
150 155
151 public TranslatingTypeLoader createTypeLoader() { 156 public TranslatingTypeLoader createTypeLoader() {
152 return new TranslatingTypeLoader( 157 return new TranslatingTypeLoader(
153 this.jar, 158 this.parsedJar,
154 this.jarIndex, 159 this.jarIndex,
155 getTranslator(TranslationDirection.Obfuscating), 160 this.entryPool,
156 getTranslator(TranslationDirection.Deobfuscating) 161 getTranslator(TranslationDirection.OBFUSCATING),
162 getTranslator(TranslationDirection.DEOBFUSCATING)
157 ); 163 );
158 } 164 }
159 165
@@ -172,15 +178,15 @@ public class Deobfuscator {
172 deobfClassName = classMapping.getDeobfName(); 178 deobfClassName = classMapping.getDeobfName();
173 } 179 }
174 180
175 // set the type loader 181 // set the desc loader
176 TranslatingTypeLoader loader = createTypeLoader(); 182 TranslatingTypeLoader loader = createTypeLoader();
177 this.settings.setTypeLoader(loader); 183 this.settings.setTypeLoader(loader);
178 184
179 // see if procyon can find the type 185 // see if procyon can find the desc
180 TypeReference type = new MetadataSystem(loader).lookupType(deobfClassName); 186 TypeReference type = new MetadataSystem(loader).lookupType(deobfClassName);
181 if (type == null) { 187 if (type == null) {
182 throw new Error(String.format("Unable to find type: %s (deobf: %s)\nTried class names: %s", 188 throw new Error(String.format("Unable to find desc: %s (deobf: %s)\nTried class names: %s",
183 className, deobfClassName, loader.getClassNamesToTry(deobfClassName) 189 className, deobfClassName, loader.getClassNamesToTry(deobfClassName)
184 )); 190 ));
185 } 191 }
186 TypeDefinition resolvedType = type.resolve(); 192 TypeDefinition resolvedType = type.resolve();
@@ -208,7 +214,7 @@ public class Deobfuscator {
208 } else { 214 } else {
209 index = new SourceIndex(source); 215 index = new SourceIndex(source);
210 } 216 }
211 sourceTree.acceptVisitor(new SourceIndexVisitor(), index); 217 sourceTree.acceptVisitor(new SourceIndexVisitor(entryPool), index);
212 218
213 // DEBUG 219 // DEBUG
214 // sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); 220 // sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null );
@@ -221,10 +227,10 @@ public class Deobfuscator {
221 Entry obfEntry = obfuscateEntry(deobfReference.entry); 227 Entry obfEntry = obfuscateEntry(deobfReference.entry);
222 228
223 // try to resolve the class 229 // try to resolve the class
224 ClassEntry resolvedObfClassEntry = this.jarIndex.getTranslationIndex().resolveEntryClass(obfEntry); 230 ClassEntry resolvedObfClassEntry = this.jarIndex.getTranslationIndex().resolveEntryOwner(obfEntry);
225 if (resolvedObfClassEntry != null && !resolvedObfClassEntry.equals(obfEntry.getClassEntry())) { 231 if (resolvedObfClassEntry != null && !resolvedObfClassEntry.equals(obfEntry.getOwnerClassEntry())) {
226 // change the class of the entry 232 // change the class of the entry
227 obfEntry = obfEntry.cloneToNewClass(resolvedObfClassEntry); 233 obfEntry = obfEntry.updateOwnership(resolvedObfClassEntry);
228 234
229 // save the new deobfuscated reference 235 // save the new deobfuscated reference
230 deobfReference.entry = deobfuscateEntry(obfEntry); 236 deobfReference.entry = deobfuscateEntry(obfEntry);
@@ -305,18 +311,14 @@ public class Deobfuscator {
305 } 311 }
306 } 312 }
307 313
308 private boolean isBehaviorProvider(ClassEntry classObfEntry, BehaviorEntry behaviorEntry) { 314 private boolean isMethodProvider(ClassEntry classObfEntry, MethodEntry methodEntry) {
309 if (behaviorEntry instanceof MethodEntry) { 315 Set<ClassEntry> classEntries = new HashSet<>();
310 MethodEntry methodEntry = (MethodEntry) behaviorEntry; 316 addAllPotentialAncestors(classEntries, classObfEntry);
311 317
312 Set<ClassEntry> classEntries = new HashSet<>(); 318 for (ClassEntry parentEntry : classEntries) {
313 addAllPotentialAncestors(classEntries, classObfEntry); 319 MethodEntry ancestorMethodEntry = entryPool.getMethod(parentEntry, methodEntry.getName(), methodEntry.getDesc());
314 320 if (jarIndex.containsObfMethod(ancestorMethodEntry)) {
315 for (ClassEntry parentEntry : classEntries) { 321 return false;
316 MethodEntry ancestorMethodEntry = new MethodEntry(parentEntry, methodEntry.getName(), methodEntry.getSignature());
317 if (jarIndex.containsObfBehavior(ancestorMethodEntry)) {
318 return false;
319 }
320 } 322 }
321 } 323 }
322 324
@@ -332,7 +334,7 @@ public class Deobfuscator {
332 for (ClassMapping classMapping : Lists.newArrayList(getMappings().classes())) { 334 for (ClassMapping classMapping : Lists.newArrayList(getMappings().classes())) {
333 progress.onProgress(i++, classMapping.getDeobfName()); 335 progress.onProgress(i++, classMapping.getDeobfName());
334 rebuildMethodNames(classMapping, renameClassMap); 336 rebuildMethodNames(classMapping, renameClassMap);
335 for(ClassMapping innerClass : classMapping.innerClasses()){ 337 for (ClassMapping innerClass : classMapping.innerClasses()) {
336 rebuildMethodNames(innerClass, renameClassMap); 338 rebuildMethodNames(innerClass, renameClassMap);
337 } 339 }
338 } 340 }
@@ -356,29 +358,29 @@ public class Deobfuscator {
356 358
357 try { 359 try {
358 rename(obfEntry, name); 360 rename(obfEntry, name);
359 } catch (IllegalNameException exception) 361 } catch (IllegalNameException exception) {
360 {
361 System.out.println("WARNING: " + exception.getMessage()); 362 System.out.println("WARNING: " + exception.getMessage());
362 } 363 }
363 } 364 }
364 } 365 }
365 } 366 }
366 367
367 private void rebuildMethodNames(ClassMapping classMapping, Map<ClassMapping, Map<Entry, String>> renameClassMap){ 368 private void rebuildMethodNames(ClassMapping classMapping, Map<ClassMapping, Map<Entry, String>> renameClassMap) {
368 Map<Entry, String> renameEntries = new HashMap<>(); 369 Map<Entry, String> renameEntries = new HashMap<>();
369 370
370 for (MethodMapping methodMapping : Lists.newArrayList(classMapping.methods())) { 371 for (MethodMapping methodMapping : Lists.newArrayList(classMapping.methods())) {
371 ClassEntry classObfEntry = classMapping.getObfEntry(); 372 ClassEntry classObfEntry = classMapping.getObfEntry();
372 BehaviorEntry obfEntry = methodMapping.getObfEntry(classObfEntry); 373 MethodEntry obfEntry = methodMapping.getObfEntry(classObfEntry);
373 374
374 if (isBehaviorProvider(classObfEntry, obfEntry)) { 375 if (isMethodProvider(classObfEntry, obfEntry)) {
375 if (hasDeobfuscatedName(obfEntry) && !(obfEntry instanceof ConstructorEntry) 376 if (hasDeobfuscatedName(obfEntry)
376 && !(methodMapping.getDeobfName().equals(methodMapping.getObfName()))) { 377 && !(methodMapping.getDeobfName().equals(methodMapping.getObfName()))) {
377 renameEntries.put(obfEntry, methodMapping.getDeobfName()); 378 renameEntries.put(obfEntry, methodMapping.getDeobfName());
378 } 379 }
379 380
380 for (ArgumentMapping argumentMapping : Lists.newArrayList(methodMapping.arguments())) { 381 ArrayList<LocalVariableMapping> arguments = Lists.newArrayList(methodMapping.arguments());
381 Entry argObfEntry = argumentMapping.getObfEntry(obfEntry); 382 for (LocalVariableMapping localVariableMapping : arguments) {
383 Entry argObfEntry = localVariableMapping.getObfEntry(obfEntry);
382 if (hasDeobfuscatedName(argObfEntry)) { 384 if (hasDeobfuscatedName(argObfEntry)) {
383 renameEntries.put(argObfEntry, deobfuscateEntry(argObfEntry).getName()); 385 renameEntries.put(argObfEntry, deobfuscateEntry(argObfEntry).getName());
384 } 386 }
@@ -390,45 +392,44 @@ public class Deobfuscator {
390 } 392 }
391 393
392 394
393
394 public void writeJar(File out, ProgressListener progress) { 395 public void writeJar(File out, ProgressListener progress) {
395 transformJar(out, progress, createTypeLoader()::transformClass); 396 transformJar(out, progress, createTypeLoader()::createTransformer);
396 } 397 }
397 398
398 public void protectifyJar(File out, ProgressListener progress) { 399 public void protectifyJar(File out, ProgressListener progress) {
399 transformJar(out, progress, ClassProtectifier::protectify); 400 transformJar(out, progress, (node, writer) -> node.accept(new ClassProtectifier(Opcodes.ASM5, writer)));
400 } 401 }
401 402
402 public void publifyJar(File out, ProgressListener progress) { 403 public void publifyJar(File out, ProgressListener progress) {
403 transformJar(out, progress, ClassPublifier::publify); 404 transformJar(out, progress, (node, writer) -> node.accept(new ClassPublifier(Opcodes.ASM5, writer)));
404 } 405 }
405 406
406 public void transformJar(File out, ProgressListener progress, ClassTransformer transformer) { 407 public void transformJar(File out, ProgressListener progress, ClassTransformer transformer) {
407 try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) { 408 try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) {
408 if (progress != null) { 409 if (progress != null) {
409 progress.init(JarClassIterator.getClassEntries(this.jar).size(), "Transforming classes..."); 410 progress.init(parsedJar.getClassCount(), "Transforming classes...");
410 } 411 }
411 412
412 int i = 0; 413 AtomicInteger i = new AtomicInteger();
413 for (CtClass c : JarClassIterator.classes(this.jar)) { 414 parsedJar.visit(node -> {
414 if (progress != null) { 415 if (progress != null) {
415 progress.onProgress(i++, c.getName()); 416 progress.onProgress(i.getAndIncrement(), node.name);
416 } 417 }
417 418
418 try { 419 try {
419 c = transformer.transform(c); 420 ClassWriter writer = new ClassWriter(0);
420 outJar.putNextEntry(new JarEntry(c.getName().replace('.', '/') + ".class")); 421 transformer.write(node, writer);
421 outJar.write(c.toBytecode()); 422 outJar.putNextEntry(new JarEntry(node.name.replace('.', '/') + ".class"));
423 outJar.write(writer.toByteArray());
422 outJar.closeEntry(); 424 outJar.closeEntry();
423 } catch (Throwable t) { 425 } catch (Throwable t) {
424 throw new Error("Unable to transform class " + c.getName(), t); 426 throw new Error("Unable to transform class " + node.name, t);
425 } 427 }
426 } 428 });
429
427 if (progress != null) { 430 if (progress != null) {
428 progress.onProgress(i, "Done!"); 431 progress.onProgress(i.get(), "Done!");
429 } 432 }
430
431 outJar.close();
432 } catch (IOException ex) { 433 } catch (IOException ex) {
433 throw new Error("Unable to write to Jar file!"); 434 throw new Error("Unable to write to Jar file!");
434 } 435 }
@@ -438,14 +439,22 @@ public class Deobfuscator {
438 if (deobfEntry == null) { 439 if (deobfEntry == null) {
439 return null; 440 return null;
440 } 441 }
441 return getTranslator(TranslationDirection.Obfuscating).translateEntry(deobfEntry); 442 T translatedEntry = getTranslator(TranslationDirection.OBFUSCATING).getTranslatedEntry(deobfEntry);
443 if (translatedEntry == null) {
444 return deobfEntry;
445 }
446 return translatedEntry;
442 } 447 }
443 448
444 public <T extends Entry> T deobfuscateEntry(T obfEntry) { 449 public <T extends Entry> T deobfuscateEntry(T obfEntry) {
445 if (obfEntry == null) { 450 if (obfEntry == null) {
446 return null; 451 return null;
447 } 452 }
448 return getTranslator(TranslationDirection.Deobfuscating).translateEntry(obfEntry); 453 T translatedEntry = getTranslator(TranslationDirection.DEOBFUSCATING).getTranslatedEntry(obfEntry);
454 if (translatedEntry == null) {
455 return obfEntry;
456 }
457 return translatedEntry;
449 } 458 }
450 459
451 public <E extends Entry, C extends Entry> EntryReference<E, C> obfuscateReference(EntryReference<E, C> deobfReference) { 460 public <E extends Entry, C extends Entry> EntryReference<E, C> obfuscateReference(EntryReference<E, C> deobfReference) {
@@ -473,7 +482,7 @@ public class Deobfuscator {
473 // HACKHACK: Object methods are not obfuscated identifiers 482 // HACKHACK: Object methods are not obfuscated identifiers
474 MethodEntry obfMethodEntry = (MethodEntry) obfEntry; 483 MethodEntry obfMethodEntry = (MethodEntry) obfEntry;
475 String name = obfMethodEntry.getName(); 484 String name = obfMethodEntry.getName();
476 String sig = obfMethodEntry.getSignature().toString(); 485 String sig = obfMethodEntry.getDesc().toString();
477 if (name.equals("clone") && sig.equals("()Ljava/lang/Object;")) { 486 if (name.equals("clone") && sig.equals("()Ljava/lang/Object;")) {
478 return false; 487 return false;
479 } else if (name.equals("equals") && sig.equals("(Ljava/lang/Object;)Z")) { 488 } else if (name.equals("equals") && sig.equals("(Ljava/lang/Object;)Z")) {
@@ -499,7 +508,7 @@ public class Deobfuscator {
499 } 508 }
500 509
501 // FIXME: HACK EVEN MORE HACK! 510 // FIXME: HACK EVEN MORE HACK!
502 if (hack && this.jarIndex.containsObfEntry(obfEntry.getClassEntry())) 511 if (hack && this.jarIndex.containsObfEntry(obfEntry.getOwnerClassEntry()))
503 return true; 512 return true;
504 } 513 }
505 514
@@ -515,27 +524,24 @@ public class Deobfuscator {
515 } 524 }
516 525
517 public boolean hasDeobfuscatedName(Entry obfEntry) { 526 public boolean hasDeobfuscatedName(Entry obfEntry) {
518 Translator translator = getTranslator(TranslationDirection.Deobfuscating); 527 Translator translator = getTranslator(TranslationDirection.DEOBFUSCATING);
519 if (obfEntry instanceof ClassEntry) { 528 if (obfEntry instanceof ClassEntry) {
520 ClassEntry obfClass = (ClassEntry) obfEntry; 529 ClassEntry obfClass = (ClassEntry) obfEntry;
521 List<ClassMapping> mappingChain = this.mappings.getClassMappingChain(obfClass); 530 List<ClassMapping> mappingChain = this.mappings.getClassMappingChain(obfClass);
522 ClassMapping classMapping = mappingChain.get(mappingChain.size() - 1); 531 ClassMapping classMapping = mappingChain.get(mappingChain.size() - 1);
523 return classMapping != null && classMapping.getDeobfName() != null; 532 return classMapping != null && classMapping.getDeobfName() != null;
524 } else if (obfEntry instanceof FieldEntry) { 533 } else if (obfEntry instanceof FieldEntry) {
525 return translator.translate((FieldEntry) obfEntry) != null; 534 return translator.getTranslatedField((FieldEntry) obfEntry) != null;
526 } else if (obfEntry instanceof MethodEntry) { 535 } else if (obfEntry instanceof MethodEntry) {
527 return translator.translate((MethodEntry) obfEntry) != null; 536 MethodEntry methodEntry = (MethodEntry) obfEntry;
528 } else if (obfEntry instanceof ConstructorEntry) { 537 if (methodEntry.isConstructor()) {
529 // constructors have no names 538 return false;
530 return false; 539 }
531 } else if (obfEntry instanceof ArgumentEntry) { 540 return translator.getTranslatedMethod(methodEntry) != null;
532 return translator.translate((ArgumentEntry) obfEntry) != null;
533 } else if (obfEntry instanceof LocalVariableEntry) { 541 } else if (obfEntry instanceof LocalVariableEntry) {
534 // TODO: Implement it 542 return translator.getTranslatedVariable((LocalVariableEntry) obfEntry) != null;
535 //return translator.translate((LocalVariableEntry)obfEntry) != null;
536 return false;
537 } else { 543 } else {
538 throw new Error("Unknown entry type: " + obfEntry.getClass().getName()); 544 throw new Error("Unknown entry desc: " + obfEntry.getClass().getName());
539 } 545 }
540 } 546 }
541 547
@@ -547,19 +553,18 @@ public class Deobfuscator {
547 553
548 public void rename(Entry obfEntry, String newName, boolean clearCache) { 554 public void rename(Entry obfEntry, String newName, boolean clearCache) {
549 if (obfEntry instanceof ClassEntry) { 555 if (obfEntry instanceof ClassEntry) {
550 this.renamer.setClassName((ClassEntry) obfEntry, Descriptor.toJvmName(newName)); 556 this.renamer.setClassName((ClassEntry) obfEntry, newName);
551 } else if (obfEntry instanceof FieldEntry) { 557 } else if (obfEntry instanceof FieldEntry) {
552 this.renamer.setFieldName((FieldEntry) obfEntry, newName); 558 this.renamer.setFieldName((FieldEntry) obfEntry, newName);
553 } else if (obfEntry instanceof MethodEntry) { 559 } else if (obfEntry instanceof MethodEntry) {
560 if (((MethodEntry) obfEntry).isConstructor()) {
561 throw new IllegalArgumentException("Cannot rename constructors");
562 }
554 this.renamer.setMethodTreeName((MethodEntry) obfEntry, newName); 563 this.renamer.setMethodTreeName((MethodEntry) obfEntry, newName);
555 } else if (obfEntry instanceof ConstructorEntry) {
556 throw new IllegalArgumentException("Cannot rename constructors");
557 } else if (obfEntry instanceof ArgumentEntry) {
558 this.renamer.setArgumentTreeName((ArgumentEntry) obfEntry, newName);
559 } else if (obfEntry instanceof LocalVariableEntry) { 564 } else if (obfEntry instanceof LocalVariableEntry) {
560 // TODO: Implement it 565 this.renamer.setLocalVariableTreeName((LocalVariableEntry) obfEntry, newName);
561 } else { 566 } else {
562 throw new Error("Unknown entry type: " + obfEntry.getClass().getName()); 567 throw new Error("Unknown entry desc: " + obfEntry.getClass().getName());
563 } 568 }
564 569
565 // clear caches 570 // clear caches
@@ -573,13 +578,14 @@ public class Deobfuscator {
573 } else if (obfEntry instanceof FieldEntry) { 578 } else if (obfEntry instanceof FieldEntry) {
574 this.renamer.removeFieldMapping((FieldEntry) obfEntry); 579 this.renamer.removeFieldMapping((FieldEntry) obfEntry);
575 } else if (obfEntry instanceof MethodEntry) { 580 } else if (obfEntry instanceof MethodEntry) {
581 if (((MethodEntry) obfEntry).isConstructor()) {
582 throw new IllegalArgumentException("Cannot rename constructors");
583 }
576 this.renamer.removeMethodTreeMapping((MethodEntry) obfEntry); 584 this.renamer.removeMethodTreeMapping((MethodEntry) obfEntry);
577 } else if (obfEntry instanceof ConstructorEntry) { 585 } else if (obfEntry instanceof LocalVariableEntry) {
578 throw new IllegalArgumentException("Cannot rename constructors"); 586 this.renamer.removeLocalVariableMapping((LocalVariableEntry) obfEntry);
579 } else if (obfEntry instanceof ArgumentEntry) {
580 this.renamer.removeArgumentMapping((ArgumentEntry) obfEntry);
581 } else { 587 } else {
582 throw new Error("Unknown entry type: " + obfEntry); 588 throw new Error("Unknown entry desc: " + obfEntry);
583 } 589 }
584 590
585 // clear caches 591 // clear caches
@@ -592,15 +598,15 @@ public class Deobfuscator {
592 } else if (obfEntry instanceof FieldEntry) { 598 } else if (obfEntry instanceof FieldEntry) {
593 this.renamer.markFieldAsDeobfuscated((FieldEntry) obfEntry); 599 this.renamer.markFieldAsDeobfuscated((FieldEntry) obfEntry);
594 } else if (obfEntry instanceof MethodEntry) { 600 } else if (obfEntry instanceof MethodEntry) {
595 this.renamer.markMethodTreeAsDeobfuscated((MethodEntry) obfEntry); 601 MethodEntry methodEntry = (MethodEntry) obfEntry;
596 } else if (obfEntry instanceof ConstructorEntry) { 602 if (methodEntry.isConstructor()) {
597 throw new IllegalArgumentException("Cannot rename constructors"); 603 throw new IllegalArgumentException("Cannot rename constructors");
598 } else if (obfEntry instanceof ArgumentEntry) { 604 }
599 this.renamer.markArgumentAsDeobfuscated((ArgumentEntry) obfEntry); 605 this.renamer.markMethodTreeAsDeobfuscated(methodEntry);
600 } else if (obfEntry instanceof LocalVariableEntry) { 606 } else if (obfEntry instanceof LocalVariableEntry) {
601 // TODO: Implement it 607 this.renamer.markArgumentAsDeobfuscated((LocalVariableEntry) obfEntry);
602 } else { 608 } else {
603 throw new Error("Unknown entry type: " + obfEntry); 609 throw new Error("Unknown entry desc: " + obfEntry);
604 } 610 }
605 611
606 // clear caches 612 // clear caches
@@ -613,17 +619,24 @@ public class Deobfuscator {
613 this.renamer.setClassModifier((ClassEntry) obfEntry, modifierEntry); 619 this.renamer.setClassModifier((ClassEntry) obfEntry, modifierEntry);
614 else if (obfEntry instanceof FieldEntry) 620 else if (obfEntry instanceof FieldEntry)
615 this.renamer.setFieldModifier((FieldEntry) obfEntry, modifierEntry); 621 this.renamer.setFieldModifier((FieldEntry) obfEntry, modifierEntry);
616 else if (obfEntry instanceof BehaviorEntry) 622 else if (obfEntry instanceof MethodEntry)
617 this.renamer.setMethodModifier((BehaviorEntry) obfEntry, modifierEntry); 623 this.renamer.setMethodModifier((MethodEntry) obfEntry, modifierEntry);
618 else 624 else
619 throw new Error("Unknown entry type: " + obfEntry); 625 throw new Error("Unknown entry desc: " + obfEntry);
620 } 626 }
621 627
622 public Mappings.EntryModifier getModifier(Entry obEntry) { 628 public Mappings.EntryModifier getModifier(Entry obfEntry) {
623 Entry entry = obfuscateEntry(obEntry); 629 Entry entry = obfuscateEntry(obfEntry);
624 if (entry != null) 630 if (entry != null)
625 obEntry = entry; 631 obfEntry = entry;
626 return getTranslator(TranslationDirection.Deobfuscating).getModifier(obEntry); 632 if (obfEntry instanceof ClassEntry)
633 return this.renamer.getClassModifier((ClassEntry) obfEntry);
634 else if (obfEntry instanceof FieldEntry)
635 return this.renamer.getFieldModifier((FieldEntry) obfEntry);
636 else if (obfEntry instanceof MethodEntry)
637 return this.renamer.getMethodModfifier((MethodEntry) obfEntry);
638 else
639 throw new Error("Unknown entry desc: " + obfEntry);
627 } 640 }
628 641
629 public interface ProgressListener { 642 public interface ProgressListener {
@@ -633,6 +646,6 @@ public class Deobfuscator {
633 } 646 }
634 647
635 public interface ClassTransformer { 648 public interface ClassTransformer {
636 CtClass transform(CtClass c) throws Exception; 649 void write(ClassNode node, ClassWriter writer);
637 } 650 }
638} 651}