summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz
diff options
context:
space:
mode:
authorGravatar Adrian Siekierka2018-10-26 19:42:24 +0200
committerGravatar Adrian Siekierka2018-10-26 19:42:42 +0200
commit97056986946cafdf79005721161edea2087c3b67 (patch)
tree020fede2de6dcb120ebc74569b856bb9f7e2e59d /src/main/java/cuchaz
parentmake rebuild method names discard child-only names. imperfect, but eh (diff)
parent"make sure this is actually a field" properly (diff)
downloadenigma-97056986946cafdf79005721161edea2087c3b67.tar.gz
enigma-97056986946cafdf79005721161edea2087c3b67.tar.xz
enigma-97056986946cafdf79005721161edea2087c3b67.zip
update ASM/Guava, merge ASM port fixes
Diffstat (limited to 'src/main/java/cuchaz')
-rw-r--r--src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java12
-rw-r--r--src/main/java/cuchaz/enigma/Deobfuscator.java69
-rw-r--r--src/main/java/cuchaz/enigma/TranslatingTypeLoader.java28
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndex.java12
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java2
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/AccessFlags.java2
-rw-r--r--src/main/java/cuchaz/enigma/config/Config.java4
-rw-r--r--src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java2
8 files changed, 112 insertions, 19 deletions
diff --git a/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java b/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java
index 58682e23..fe13321c 100644
--- a/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java
+++ b/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java
@@ -8,6 +8,12 @@ import com.strobel.assembler.metadata.ITypeLoader;
8 * Caching version of {@link ClasspathTypeLoader} 8 * Caching version of {@link ClasspathTypeLoader}
9 */ 9 */
10public class CachingClasspathTypeLoader extends CachingTypeLoader { 10public class CachingClasspathTypeLoader extends CachingTypeLoader {
11 private static ITypeLoader extraClassPathLoader = null;
12
13 public static void setExtraClassPathLoader(ITypeLoader loader){
14 extraClassPathLoader = loader;
15 }
16
11 private final ITypeLoader classpathLoader = new ClasspathTypeLoader(); 17 private final ITypeLoader classpathLoader = new ClasspathTypeLoader();
12 18
13 protected byte[] doLoad(String className) { 19 protected byte[] doLoad(String className) {
@@ -15,6 +21,12 @@ public class CachingClasspathTypeLoader extends CachingTypeLoader {
15 if (classpathLoader.tryLoadType(className, parentBuf)) { 21 if (classpathLoader.tryLoadType(className, parentBuf)) {
16 return parentBuf.array(); 22 return parentBuf.array();
17 } 23 }
24 if (extraClassPathLoader != null){
25 parentBuf.reset();
26 if (extraClassPathLoader.tryLoadType(className, parentBuf)){
27 return parentBuf.array();
28 }
29 }
18 return EMPTY_ARRAY;//need to return *something* as null means no store 30 return EMPTY_ARRAY;//need to return *something* as null means no store
19 } 31 }
20} 32}
diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java
index 5980f1fc..0c671589 100644
--- a/src/main/java/cuchaz/enigma/Deobfuscator.java
+++ b/src/main/java/cuchaz/enigma/Deobfuscator.java
@@ -15,6 +15,7 @@ import com.google.common.base.Stopwatch;
15import com.google.common.collect.Lists; 15import com.google.common.collect.Lists;
16import com.google.common.collect.Maps; 16import com.google.common.collect.Maps;
17import com.google.common.collect.Sets; 17import com.google.common.collect.Sets;
18import com.strobel.assembler.metadata.ITypeLoader;
18import com.strobel.assembler.metadata.MetadataSystem; 19import com.strobel.assembler.metadata.MetadataSystem;
19import com.strobel.assembler.metadata.TypeDefinition; 20import com.strobel.assembler.metadata.TypeDefinition;
20import com.strobel.assembler.metadata.TypeReference; 21import com.strobel.assembler.metadata.TypeReference;
@@ -33,14 +34,18 @@ import cuchaz.enigma.mapping.*;
33import cuchaz.enigma.mapping.entry.*; 34import cuchaz.enigma.mapping.entry.*;
34import cuchaz.enigma.throwables.IllegalNameException; 35import cuchaz.enigma.throwables.IllegalNameException;
35import cuchaz.enigma.utils.Utils; 36import cuchaz.enigma.utils.Utils;
37import oml.ast.transformers.InvalidIdentifierFix;
38import oml.ast.transformers.Java8Generics;
36import oml.ast.transformers.ObfuscatedEnumSwitchRewriterTransform; 39import oml.ast.transformers.ObfuscatedEnumSwitchRewriterTransform;
37import oml.ast.transformers.RemoveObjectCasts; 40import oml.ast.transformers.RemoveObjectCasts;
41import oml.ast.transformers.VarargsFixer;
38import org.objectweb.asm.ClassWriter; 42import org.objectweb.asm.ClassWriter;
39import org.objectweb.asm.Opcodes; 43import org.objectweb.asm.Opcodes;
40import org.objectweb.asm.tree.ClassNode; 44import org.objectweb.asm.tree.ClassNode;
41 45
42import java.io.*; 46import java.io.*;
43import java.util.*; 47import java.util.*;
48import java.util.concurrent.ConcurrentHashMap;
44import java.util.concurrent.atomic.AtomicInteger; 49import java.util.concurrent.atomic.AtomicInteger;
45import java.util.jar.JarEntry; 50import java.util.jar.JarEntry;
46import java.util.jar.JarFile; 51import java.util.jar.JarFile;
@@ -170,6 +175,10 @@ public class Deobfuscator {
170 } 175 }
171 176
172 public CompilationUnit getSourceTree(String className, ITranslatingTypeLoader loader) { 177 public CompilationUnit getSourceTree(String className, ITranslatingTypeLoader loader) {
178 return getSourceTree(className, loader, new NoRetryMetadataSystem(loader));
179 }
180
181 public CompilationUnit getSourceTree(String className, ITranslatingTypeLoader loader, MetadataSystem metadataSystem) {
173 182
174 // we don't know if this class name is obfuscated or deobfuscated 183 // we don't know if this class name is obfuscated or deobfuscated
175 // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out 184 // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out
@@ -188,7 +197,7 @@ public class Deobfuscator {
188 this.settings.setTypeLoader(loader); 197 this.settings.setTypeLoader(loader);
189 198
190 // see if procyon can find the desc 199 // see if procyon can find the desc
191 TypeReference type = new MetadataSystem(loader).lookupType(deobfClassName); 200 TypeReference type = metadataSystem.lookupType(deobfClassName);
192 if (type == null) { 201 if (type == null) {
193 throw new Error(String.format("Unable to find desc: %s (deobf: %s)\nTried class names: %s", 202 throw new Error(String.format("Unable to find desc: %s (deobf: %s)\nTried class names: %s",
194 className, deobfClassName, loader.getClassNamesToTry(deobfClassName) 203 className, deobfClassName, loader.getClassNamesToTry(deobfClassName)
@@ -278,6 +287,9 @@ public class Deobfuscator {
278 //synchronized to make sure the parallelStream doesn't CME with the cache 287 //synchronized to make sure the parallelStream doesn't CME with the cache
279 ITranslatingTypeLoader typeLoader = new SynchronizedTypeLoader(createTypeLoader()); 288 ITranslatingTypeLoader typeLoader = new SynchronizedTypeLoader(createTypeLoader());
280 289
290 MetadataSystem metadataSystem = new NoRetryMetadataSystem(typeLoader);
291 metadataSystem.setEagerMethodLoadingEnabled(true);//ensures methods are loaded on classload and prevents race conditions
292
281 // DEOBFUSCATE ALL THE THINGS!! @_@ 293 // DEOBFUSCATE ALL THE THINGS!! @_@
282 Stopwatch stopwatch = Stopwatch.createStarted(); 294 Stopwatch stopwatch = Stopwatch.createStarted();
283 AtomicInteger count = new AtomicInteger(); 295 AtomicInteger count = new AtomicInteger();
@@ -289,7 +301,7 @@ public class Deobfuscator {
289 301
290 try { 302 try {
291 // get the source 303 // get the source
292 CompilationUnit sourceTree = getSourceTree(obfClassEntry.getName(), typeLoader); 304 CompilationUnit sourceTree = getSourceTree(obfClassEntry.getName(), typeLoader, metadataSystem);
293 305
294 // write the file 306 // write the file
295 File file = new File(dirOut, deobfClassEntry.getName().replace('.', '/') + ".java"); 307 File file = new File(dirOut, deobfClassEntry.getName().replace('.', '/') + ".java");
@@ -355,28 +367,28 @@ public class Deobfuscator {
355 } 367 }
356 368
357 public void rebuildMethodNames(ProgressListener progress) { 369 public void rebuildMethodNames(ProgressListener progress) {
358 int i = 0; 370 final AtomicInteger i = new AtomicInteger();
359 Map<ClassMapping, Map<Entry, String>> renameClassMap = new HashMap<>(); 371 Map<ClassMapping, Map<Entry, String>> renameClassMap = new HashMap<>();
360 372
361 progress.init(getMappings().classes().size() * 3, "Rebuilding method names"); 373 progress.init(getMappings().classes().size() * 3, "Rebuilding method names");
362 374
363 for (ClassMapping classMapping : Lists.newArrayList(getMappings().classes())) { 375 Lists.newArrayList(getMappings().classes()).parallelStream().forEach(classMapping -> {
364 progress.onProgress(i++, classMapping.getDeobfName()); 376 progress.onProgress(i.getAndIncrement(), classMapping.getDeobfName());
365 rebuildMethodNames(classMapping, renameClassMap); 377 rebuildMethodNames(classMapping, renameClassMap);
366 } 378 });
367 379
368 for (Map.Entry<ClassMapping, Map<Entry, String>> renameClassMapEntry : renameClassMap.entrySet()) {
369 progress.onProgress(i++, renameClassMapEntry.getKey().getDeobfName());
370 380
381 renameClassMap.entrySet().parallelStream().forEach(renameClassMapEntry -> {
382 progress.onProgress(i.getAndIncrement(), renameClassMapEntry.getKey().getDeobfName());
371 for (Map.Entry<Entry, String> entry : renameClassMapEntry.getValue().entrySet()) { 383 for (Map.Entry<Entry, String> entry : renameClassMapEntry.getValue().entrySet()) {
372 Entry obfEntry = entry.getKey(); 384 Entry obfEntry = entry.getKey();
373 385
374 removeMapping(obfEntry); 386 removeMapping(obfEntry);
375 } 387 }
376 } 388 });
377 389
378 for (Map.Entry<ClassMapping, Map<Entry, String>> renameClassMapEntry : renameClassMap.entrySet()) { 390 renameClassMap.entrySet().parallelStream().forEach(renameClassMapEntry -> {
379 progress.onProgress(i++, renameClassMapEntry.getKey().getDeobfName()); 391 progress.onProgress(i.getAndIncrement(), renameClassMapEntry.getKey().getDeobfName());
380 392
381 for (Map.Entry<Entry, String> entry : renameClassMapEntry.getValue().entrySet()) { 393 for (Map.Entry<Entry, String> entry : renameClassMapEntry.getValue().entrySet()) {
382 Entry obfEntry = entry.getKey(); 394 Entry obfEntry = entry.getKey();
@@ -390,7 +402,7 @@ public class Deobfuscator {
390 } 402 }
391 } 403 }
392 } 404 }
393 } 405 });
394 } 406 }
395 407
396 private void rebuildMethodNames(ClassMapping classMapping, Map<ClassMapping, Map<Entry, String>> renameClassMap) { 408 private void rebuildMethodNames(ClassMapping classMapping, Map<ClassMapping, Map<Entry, String>> renameClassMap) {
@@ -680,9 +692,12 @@ public class Deobfuscator {
680 public static void runCustomTransforms(AstBuilder builder, DecompilerContext context){ 692 public static void runCustomTransforms(AstBuilder builder, DecompilerContext context){
681 List<IAstTransform> transformers = Arrays.asList( 693 List<IAstTransform> transformers = Arrays.asList(
682 new ObfuscatedEnumSwitchRewriterTransform(context), 694 new ObfuscatedEnumSwitchRewriterTransform(context),
683 new RemoveObjectCasts(context) 695 new VarargsFixer(context),
696 new RemoveObjectCasts(context),
697 new Java8Generics(),
698 new InvalidIdentifierFix()
684 ); 699 );
685 for (IAstTransform transform : transformers){ 700 for (IAstTransform transform : transformers) {
686 transform.run(builder.getCompilationUnit()); 701 transform.run(builder.getCompilationUnit());
687 } 702 }
688 } 703 }
@@ -697,4 +712,30 @@ public class Deobfuscator {
697 String transform(ClassNode node, ClassWriter writer); 712 String transform(ClassNode node, ClassWriter writer);
698 } 713 }
699 714
715 public static class NoRetryMetadataSystem extends MetadataSystem {
716 private final Set<String> _failedTypes = Collections.newSetFromMap(new ConcurrentHashMap<>());
717
718 public NoRetryMetadataSystem(final ITypeLoader typeLoader) {
719 super(typeLoader);
720 }
721
722 @Override
723 protected synchronized TypeDefinition resolveType(final String descriptor, final boolean mightBePrimitive) {
724 if (_failedTypes.contains(descriptor)) {
725 return null;
726 }
727
728 final TypeDefinition result = super.resolveType(descriptor, mightBePrimitive);
729
730 if (result == null) {
731 _failedTypes.add(descriptor);
732 }
733
734 return result;
735 }
736
737 public synchronized TypeDefinition resolve(final TypeReference type) {
738 return super.resolve(type);
739 }
740 }
700} 741}
diff --git a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java
index eb780ee9..42ceec4d 100644
--- a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java
+++ b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java
@@ -22,7 +22,10 @@ import cuchaz.enigma.mapping.entry.ReferencedEntryPool;
22import cuchaz.enigma.mapping.Translator; 22import cuchaz.enigma.mapping.Translator;
23import org.objectweb.asm.ClassWriter; 23import org.objectweb.asm.ClassWriter;
24import org.objectweb.asm.Opcodes; 24import org.objectweb.asm.Opcodes;
25import org.objectweb.asm.tree.AbstractInsnNode;
25import org.objectweb.asm.tree.ClassNode; 26import org.objectweb.asm.tree.ClassNode;
27import org.objectweb.asm.tree.MethodInsnNode;
28import org.objectweb.asm.tree.MethodNode;
26 29
27import java.util.List; 30import java.util.List;
28 31
@@ -89,6 +92,31 @@ public class TranslatingTypeLoader extends CachingTypeLoader implements ITransla
89 return null; 92 return null;
90 } 93 }
91 94
95
96 // remove <obj>.getClass() calls that are seemingly injected
97 // DUP
98 // INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
99 // POP
100 for (MethodNode methodNode : node.methods){
101 AbstractInsnNode insnNode = methodNode.instructions.getFirst();
102 while (insnNode != null){
103 if (insnNode instanceof MethodInsnNode && insnNode.getOpcode() == Opcodes.INVOKEVIRTUAL){
104 MethodInsnNode methodInsnNode = (MethodInsnNode)insnNode;
105 if (methodInsnNode.name.equals("getClass") && methodInsnNode.owner.equals("java/lang/Object") && methodInsnNode.desc.equals("()Ljava/lang/Class;")){
106 AbstractInsnNode previous = methodInsnNode.getPrevious();
107 AbstractInsnNode next = methodInsnNode.getNext();
108 if (previous.getOpcode() == Opcodes.DUP && next.getOpcode() == Opcodes.POP){
109 insnNode = previous.getPrevious();//reset the iterator so it gets the new next instruction
110 methodNode.instructions.remove(previous);
111 methodNode.instructions.remove(methodInsnNode);
112 methodNode.instructions.remove(next);
113 }
114 }
115 }
116 insnNode = insnNode.getNext();
117 }
118 }
119
92 ClassWriter writer = new ClassWriter(0); 120 ClassWriter writer = new ClassWriter(0);
93 transformInto(node, writer); 121 transformInto(node, writer);
94 122
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
index 14b2e768..78195cb7 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
@@ -17,15 +17,19 @@ import com.google.common.collect.Maps;
17import com.google.common.collect.Multimap; 17import com.google.common.collect.Multimap;
18import com.strobel.decompiler.languages.Region; 18import com.strobel.decompiler.languages.Region;
19import com.strobel.decompiler.languages.java.ast.AstNode; 19import com.strobel.decompiler.languages.java.ast.AstNode;
20import com.strobel.decompiler.languages.java.ast.ConstructorDeclaration;
20import com.strobel.decompiler.languages.java.ast.Identifier; 21import com.strobel.decompiler.languages.java.ast.Identifier;
22import com.strobel.decompiler.languages.java.ast.TypeDeclaration;
21import cuchaz.enigma.mapping.entry.Entry; 23import cuchaz.enigma.mapping.entry.Entry;
22 24
23import java.util.Collection; 25import java.util.Collection;
24import java.util.List; 26import java.util.List;
25import java.util.Map; 27import java.util.Map;
26import java.util.TreeMap; 28import java.util.TreeMap;
29import java.util.regex.Pattern;
27 30
28public class SourceIndex { 31public class SourceIndex {
32 private static Pattern ANONYMOUS_INNER = Pattern.compile("\\$\\d+$");
29 33
30 private String source; 34 private String source;
31 private TreeMap<Token, EntryReference<Entry, Entry>> tokenToReference; 35 private TreeMap<Token, EntryReference<Entry, Entry>> tokenToReference;
@@ -81,6 +85,14 @@ public class SourceIndex {
81 return null; 85 return null;
82 } 86 }
83 87
88 if (node instanceof Identifier && name.indexOf('$') >=0 && node.getParent() instanceof ConstructorDeclaration && name.lastIndexOf('$') >= 0 && !ANONYMOUS_INNER.matcher(name).matches()){
89 TypeDeclaration type = node.getParent().getParent() instanceof TypeDeclaration ? (TypeDeclaration) node.getParent().getParent() : null;
90 if (type != null){
91 name = type.getName();
92 token.end = token.start + name.length();
93 }
94 }
95
84 // DEBUG 96 // DEBUG
85 // System.out.println( String.format( "%s \"%s\" region: %s", node.getNodeType(), name, region ) ); 97 // System.out.println( String.format( "%s \"%s\" region: %s", node.getNodeType(), name, region ) );
86 98
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
index 83fe296c..83e5e04f 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
@@ -76,7 +76,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
76 @Override 76 @Override
77 public Void visitMemberReferenceExpression(MemberReferenceExpression node, SourceIndex index) { 77 public Void visitMemberReferenceExpression(MemberReferenceExpression node, SourceIndex index) {
78 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); 78 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
79 if (ref != null) { 79 if (ref instanceof FieldReference) {
80 // make sure this is actually a field 80 // make sure this is actually a field
81 String erasedSignature = ref.getErasedSignature(); 81 String erasedSignature = ref.getErasedSignature();
82 if (erasedSignature.indexOf('(') >= 0) { 82 if (erasedSignature.indexOf('(') >= 0) {
diff --git a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
index 21b24897..0bfc59bd 100644
--- a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
+++ b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java
@@ -51,7 +51,7 @@ public class AccessFlags {
51 } 51 }
52 52
53 public AccessFlags setBridged() { 53 public AccessFlags setBridged() {
54 this.setVisibility(Opcodes.ACC_BRIDGE); 54 flags |= Opcodes.ACC_BRIDGE;
55 return this; 55 return this;
56 } 56 }
57 57
diff --git a/src/main/java/cuchaz/enigma/config/Config.java b/src/main/java/cuchaz/enigma/config/Config.java
index 87ef3531..75ced70c 100644
--- a/src/main/java/cuchaz/enigma/config/Config.java
+++ b/src/main/java/cuchaz/enigma/config/Config.java
@@ -62,7 +62,7 @@ public class Config {
62 public void loadConfig() throws IOException { 62 public void loadConfig() throws IOException {
63 if (!ENIGMA_DIR.exists()) ENIGMA_DIR.mkdirs(); 63 if (!ENIGMA_DIR.exists()) ENIGMA_DIR.mkdirs();
64 File configFile = new File(ENIGMA_DIR, "config.json"); 64 File configFile = new File(ENIGMA_DIR, "config.json");
65 if (configFile.exists()) gson.fromJson(Files.toString(configFile, Charset.defaultCharset()), Config.class); 65 if (configFile.exists()) gson.fromJson(Files.asCharSource(configFile, Charset.defaultCharset()).read(), Config.class);
66 else { 66 else {
67 this.reset(); 67 this.reset();
68 Files.touch(configFile); 68 Files.touch(configFile);
@@ -71,7 +71,7 @@ public class Config {
71 } 71 }
72 72
73 public void saveConfig() throws IOException { 73 public void saveConfig() throws IOException {
74 Files.write(gson.toJson(this), CONFIG_FILE, Charset.defaultCharset()); 74 Files.asCharSink(CONFIG_FILE, Charset.defaultCharset()).write(gson.toJson(this));
75 } 75 }
76 76
77 public void reset() throws IOException { 77 public void reset() throws IOException {
diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
index fd30e389..ffceae12 100644
--- a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
+++ b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
@@ -56,7 +56,7 @@ public class PanelEditor extends JEditorPane {
56 gui.popupMenu.showCallsMenu.doClick(); 56 gui.popupMenu.showCallsMenu.doClick();
57 break; 57 break;
58 58
59 case KeyEvent.VK_T: 59 case KeyEvent.VK_O:
60 gui.popupMenu.toggleMappingMenu.doClick(); 60 gui.popupMenu.toggleMappingMenu.doClick();
61 break; 61 break;
62 case KeyEvent.VK_F5: 62 case KeyEvent.VK_F5: