summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Runemoro2019-11-22 15:40:50 -0500
committerGravatar modmuss502019-11-22 20:40:50 +0000
commit37cafdb5a837cbe29e4cc9a34737e24f496bc94f (patch)
tree413ec17d5593984465ffc6005f3fa3c096d7225f /src/main
parentTweak runemoro's stats generator to be compatible with multiple services (#178) (diff)
downloadenigma-37cafdb5a837cbe29e4cc9a34737e24f496bc94f.tar.gz
enigma-37cafdb5a837cbe29e4cc9a34737e24f496bc94f.tar.xz
enigma-37cafdb5a837cbe29e4cc9a34737e24f496bc94f.zip
Correctly decompile bridges, and add command to add bridges to mappings (#180)
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/cuchaz/enigma/CommandMain.java1
-rw-r--r--src/main/java/cuchaz/enigma/EnigmaProject.java3
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java18
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java3
-rw-r--r--src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java67
5 files changed, 85 insertions, 7 deletions
diff --git a/src/main/java/cuchaz/enigma/CommandMain.java b/src/main/java/cuchaz/enigma/CommandMain.java
index 5e7a1af6..93b013d5 100644
--- a/src/main/java/cuchaz/enigma/CommandMain.java
+++ b/src/main/java/cuchaz/enigma/CommandMain.java
@@ -86,6 +86,7 @@ public class CommandMain {
86 register(new ComposeMappingsCommand()); 86 register(new ComposeMappingsCommand());
87 register(new InvertMappingsCommand()); 87 register(new InvertMappingsCommand());
88 register(new CheckMappingsCommand()); 88 register(new CheckMappingsCommand());
89 register(new MapSpecializedMethodsCommand());
89 } 90 }
90 91
91 private static final class CommandHelpException extends IllegalArgumentException { 92 private static final class CommandHelpException extends IllegalArgumentException {
diff --git a/src/main/java/cuchaz/enigma/EnigmaProject.java b/src/main/java/cuchaz/enigma/EnigmaProject.java
index 47a37907..2a7ca988 100644
--- a/src/main/java/cuchaz/enigma/EnigmaProject.java
+++ b/src/main/java/cuchaz/enigma/EnigmaProject.java
@@ -158,7 +158,7 @@ public class EnigmaProject {
158 ClassNode node = classCache.getClassNode(entry.getFullName()); 158 ClassNode node = classCache.getClassNode(entry.getFullName());
159 if (node != null) { 159 if (node != null) {
160 ClassNode translatedNode = new ClassNode(); 160 ClassNode translatedNode = new ClassNode();
161 node.accept(new TranslationClassVisitor(deobfuscator, Opcodes.ASM5, translatedNode)); 161 node.accept(new TranslationClassVisitor(deobfuscator, Opcodes.ASM5, new SourceFixVisitor(Opcodes.ASM5, translatedNode, jarIndex)));
162 return translatedNode; 162 return translatedNode;
163 } 163 }
164 164
@@ -209,7 +209,6 @@ public class EnigmaProject {
209 209
210 //create a common instance outside the loop as mappings shouldn't be changing while this is happening 210 //create a common instance outside the loop as mappings shouldn't be changing while this is happening
211 CompiledSourceTypeLoader typeLoader = new CompiledSourceTypeLoader(this.compiled::get); 211 CompiledSourceTypeLoader typeLoader = new CompiledSourceTypeLoader(this.compiled::get);
212 typeLoader.addVisitor(visitor -> new SourceFixVisitor(Opcodes.ASM5, visitor, jarIndex));
213 212
214 //synchronized to make sure the parallelStream doesn't CME with the cache 213 //synchronized to make sure the parallelStream doesn't CME with the cache
215 ITypeLoader synchronizedTypeLoader = new SynchronizedTypeLoader(typeLoader); 214 ITypeLoader synchronizedTypeLoader = new SynchronizedTypeLoader(typeLoader);
diff --git a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
index 8a9b4593..a4b1aac9 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
@@ -1,7 +1,6 @@
1package cuchaz.enigma.analysis.index; 1package cuchaz.enigma.analysis.index;
2 2
3import com.google.common.collect.Maps; 3import com.google.common.collect.Maps;
4import com.google.common.collect.Sets;
5import cuchaz.enigma.translation.representation.AccessFlags; 4import cuchaz.enigma.translation.representation.AccessFlags;
6import cuchaz.enigma.translation.representation.MethodDescriptor; 5import cuchaz.enigma.translation.representation.MethodDescriptor;
7import cuchaz.enigma.translation.representation.TypeDescriptor; 6import cuchaz.enigma.translation.representation.TypeDescriptor;
@@ -17,7 +16,7 @@ public class BridgeMethodIndex implements JarIndexer {
17 private final InheritanceIndex inheritanceIndex; 16 private final InheritanceIndex inheritanceIndex;
18 private final ReferenceIndex referenceIndex; 17 private final ReferenceIndex referenceIndex;
19 18
20 private final Set<MethodEntry> bridgeToSpecialized = Sets.newHashSet(); 19 private final Map<MethodEntry, MethodEntry> bridgeToSpecialized = Maps.newHashMap();
21 private final Map<MethodEntry, MethodEntry> specializedToBridge = Maps.newHashMap(); 20 private final Map<MethodEntry, MethodEntry> specializedToBridge = Maps.newHashMap();
22 21
23 public BridgeMethodIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex) { 22 public BridgeMethodIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex) {
@@ -52,7 +51,6 @@ public class BridgeMethodIndex implements JarIndexer {
52 } 51 }
53 52
54 MethodEntry renamedSpecializedEntry = specializedEntry.withName(bridgeEntry.getName()); 53 MethodEntry renamedSpecializedEntry = specializedEntry.withName(bridgeEntry.getName());
55 bridgeToSpecialized.add(renamedSpecializedEntry);
56 specializedToBridge.put(renamedSpecializedEntry, specializedToBridge.get(specializedEntry)); 54 specializedToBridge.put(renamedSpecializedEntry, specializedToBridge.get(specializedEntry));
57 } 55 }
58 } 56 }
@@ -64,7 +62,7 @@ public class BridgeMethodIndex implements JarIndexer {
64 } 62 }
65 63
66 if (access.isBridge() || isPotentialBridge(syntheticMethod, specializedMethod)) { 64 if (access.isBridge() || isPotentialBridge(syntheticMethod, specializedMethod)) {
67 bridgeToSpecialized.add(syntheticMethod); 65 bridgeToSpecialized.put(syntheticMethod, specializedMethod);
68 specializedToBridge.put(specializedMethod, syntheticMethod); 66 specializedToBridge.put(specializedMethod, syntheticMethod);
69 } 67 }
70 } 68 }
@@ -130,7 +128,7 @@ public class BridgeMethodIndex implements JarIndexer {
130 } 128 }
131 129
132 public boolean isBridgeMethod(MethodEntry entry) { 130 public boolean isBridgeMethod(MethodEntry entry) {
133 return bridgeToSpecialized.contains(entry); 131 return bridgeToSpecialized.containsKey(entry);
134 } 132 }
135 133
136 public boolean isSpecializedMethod(MethodEntry entry) { 134 public boolean isSpecializedMethod(MethodEntry entry) {
@@ -142,7 +140,17 @@ public class BridgeMethodIndex implements JarIndexer {
142 return specializedToBridge.get(specialized); 140 return specializedToBridge.get(specialized);
143 } 141 }
144 142
143 public MethodEntry getSpecializedFromBridge(MethodEntry bridge) {
144 return bridgeToSpecialized.get(bridge);
145 }
146
147 /** Includes "renamed specialized -> bridge" entries. */
145 public Map<MethodEntry, MethodEntry> getSpecializedToBridge() { 148 public Map<MethodEntry, MethodEntry> getSpecializedToBridge() {
146 return Collections.unmodifiableMap(specializedToBridge); 149 return Collections.unmodifiableMap(specializedToBridge);
147 } 150 }
151
152 /** Only "bridge -> original name" entries. **/
153 public Map<MethodEntry, MethodEntry> getBridgeToSpecialized() {
154 return Collections.unmodifiableMap(bridgeToSpecialized);
155 }
148} 156}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java
index 735a65f2..d672622c 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java
@@ -4,6 +4,7 @@ import cuchaz.enigma.analysis.index.BridgeMethodIndex;
4import cuchaz.enigma.analysis.index.JarIndex; 4import cuchaz.enigma.analysis.index.JarIndex;
5import cuchaz.enigma.translation.representation.entry.ClassDefEntry; 5import cuchaz.enigma.translation.representation.entry.ClassDefEntry;
6import cuchaz.enigma.translation.representation.entry.MethodDefEntry; 6import cuchaz.enigma.translation.representation.entry.MethodDefEntry;
7import cuchaz.enigma.translation.representation.entry.MethodEntry;
7import org.objectweb.asm.ClassVisitor; 8import org.objectweb.asm.ClassVisitor;
8import org.objectweb.asm.MethodVisitor; 9import org.objectweb.asm.MethodVisitor;
9import org.objectweb.asm.Opcodes; 10import org.objectweb.asm.Opcodes;
@@ -30,6 +31,8 @@ public class SourceFixVisitor extends ClassVisitor {
30 BridgeMethodIndex bridgeIndex = index.getBridgeMethodIndex(); 31 BridgeMethodIndex bridgeIndex = index.getBridgeMethodIndex();
31 if (bridgeIndex.isBridgeMethod(methodEntry)) { 32 if (bridgeIndex.isBridgeMethod(methodEntry)) {
32 access |= Opcodes.ACC_BRIDGE; 33 access |= Opcodes.ACC_BRIDGE;
34 } else if (bridgeIndex.isSpecializedMethod(methodEntry)) {
35 name = bridgeIndex.getBridgeFromSpecialized(methodEntry).getName();
33 } 36 }
34 37
35 return super.visitMethod(access, name, descriptor, signature, exceptions); 38 return super.visitMethod(access, name, descriptor, signature, exceptions);
diff --git a/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java b/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java
new file mode 100644
index 00000000..7696f0f1
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java
@@ -0,0 +1,67 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.ProgressListener;
4import cuchaz.enigma.analysis.ClassCache;
5import cuchaz.enigma.analysis.index.BridgeMethodIndex;
6import cuchaz.enigma.analysis.index.JarIndex;
7import cuchaz.enigma.throwables.MappingParseException;
8import cuchaz.enigma.translation.MappingTranslator;
9import cuchaz.enigma.translation.Translator;
10import cuchaz.enigma.translation.mapping.*;
11import cuchaz.enigma.translation.mapping.tree.EntryTree;
12import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
13import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
14import cuchaz.enigma.translation.representation.entry.MethodEntry;
15import cuchaz.enigma.utils.Utils;
16
17import java.io.IOException;
18import java.nio.file.Path;
19import java.nio.file.Paths;
20import java.util.Map;
21
22public class MapSpecializedMethodsCommand extends Command {
23 public MapSpecializedMethodsCommand() {
24 super("map-specialized-methods");
25 }
26
27 @Override
28 public String getUsage() {
29 return "<jar> <source-format> <source> <result-format> <result>";
30 }
31
32 @Override
33 public boolean isValidArgument(int length) {
34 return length == 5;
35 }
36
37 @Override
38 public void run(String... args) throws IOException, MappingParseException {
39 MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF);
40 EntryTree<EntryMapping> source = MappingCommandsUtil.read(args[1], Paths.get(args[2]), saveParameters);
41 EntryTree<EntryMapping> result = new HashEntryTree<>();
42 Path jar = Paths.get(args[0]);
43 ClassCache classCache = ClassCache.of(jar);
44 JarIndex jarIndex = classCache.index(ProgressListener.none());
45 BridgeMethodIndex bridgeMethodIndex = jarIndex.getBridgeMethodIndex();
46 Translator translator = new MappingTranslator(source, jarIndex.getEntryResolver());
47
48 // Copy all non-specialized methods
49 for (EntryTreeNode<EntryMapping> node : source) {
50 if (!(node.getEntry() instanceof MethodEntry) || !bridgeMethodIndex.isSpecializedMethod((MethodEntry) node.getEntry())) {
51 result.insert(node.getEntry(), node.getValue());
52 }
53 }
54
55 // Add correct mappings for specialized methods
56 for (Map.Entry<MethodEntry, MethodEntry> entry : bridgeMethodIndex.getBridgeToSpecialized().entrySet()) {
57 MethodEntry bridge = entry.getKey();
58 MethodEntry specialized = entry.getValue();
59 String name = translator.translate(bridge).getName();
60 result.insert(specialized, new EntryMapping(name));
61 }
62
63 Path output = Paths.get(args[4]);
64 Utils.delete(output);
65 MappingCommandsUtil.write(result, args[3], output, saveParameters);
66 }
67}