summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java')
-rw-r--r--src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java157
1 files changed, 0 insertions, 157 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java b/src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java
deleted file mode 100644
index dc3f553..0000000
--- a/src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java
+++ /dev/null
@@ -1,157 +0,0 @@
1package cuchaz.enigma.analysis;
2
3import cuchaz.enigma.api.EnigmaPlugin;
4import cuchaz.enigma.api.EnigmaPluginContext;
5import cuchaz.enigma.api.service.JarIndexerService;
6import cuchaz.enigma.api.service.NameProposalService;
7import cuchaz.enigma.source.DecompilerService;
8import cuchaz.enigma.source.Decompilers;
9import cuchaz.enigma.source.procyon.ProcyonDecompiler;
10import cuchaz.enigma.translation.representation.TypeDescriptor;
11import cuchaz.enigma.translation.representation.entry.ClassEntry;
12import cuchaz.enigma.translation.representation.entry.Entry;
13import cuchaz.enigma.translation.representation.entry.FieldEntry;
14import cuchaz.enigma.utils.Pair;
15import cuchaz.enigma.utils.Utils;
16import org.objectweb.asm.ClassReader;
17import org.objectweb.asm.ClassVisitor;
18import org.objectweb.asm.FieldVisitor;
19import org.objectweb.asm.MethodVisitor;
20import org.objectweb.asm.Opcodes;
21import org.objectweb.asm.tree.AbstractInsnNode;
22import org.objectweb.asm.tree.FieldInsnNode;
23import org.objectweb.asm.tree.InsnList;
24import org.objectweb.asm.tree.LdcInsnNode;
25import org.objectweb.asm.tree.MethodInsnNode;
26import org.objectweb.asm.tree.MethodNode;
27import org.objectweb.asm.tree.analysis.Analyzer;
28import org.objectweb.asm.tree.analysis.Frame;
29import org.objectweb.asm.tree.analysis.SourceInterpreter;
30import org.objectweb.asm.tree.analysis.SourceValue;
31
32import java.util.ArrayList;
33import java.util.HashMap;
34import java.util.HashSet;
35import java.util.List;
36import java.util.Map;
37import java.util.Optional;
38import java.util.Set;
39
40public final class BuiltinPlugin implements EnigmaPlugin {
41
42 public BuiltinPlugin() {
43 }
44
45 @Override
46 public void init(EnigmaPluginContext ctx) {
47 registerEnumNamingService(ctx);
48 registerDecompilerServices(ctx);
49 }
50
51 private void registerEnumNamingService(EnigmaPluginContext ctx) {
52 final Map<Entry<?>, String> names = new HashMap<>();
53 final EnumFieldNameFindingVisitor visitor = new EnumFieldNameFindingVisitor(names);
54
55 ctx.registerService("enigma:enum_initializer_indexer", JarIndexerService.TYPE, ctx1 -> (classCache, jarIndex) -> classCache.visit(() -> visitor, ClassReader.SKIP_FRAMES));
56 ctx.registerService("enigma:enum_name_proposer", NameProposalService.TYPE, ctx1 -> (obfEntry, remapper) -> Optional.ofNullable(names.get(obfEntry)));
57 }
58
59 private void registerDecompilerServices(EnigmaPluginContext ctx) {
60 ctx.registerService("enigma:procyon", DecompilerService.TYPE, ctx1 -> Decompilers.PROCYON);
61 ctx.registerService("enigma:cfr", DecompilerService.TYPE, ctx1 -> Decompilers.CFR);
62 }
63
64 private static final class EnumFieldNameFindingVisitor extends ClassVisitor {
65
66 private ClassEntry clazz;
67 private String className;
68 private final Map<Entry<?>, String> mappings;
69 private final Set<Pair<String, String>> enumFields = new HashSet<>();
70 private final List<MethodNode> classInits = new ArrayList<>();
71
72 EnumFieldNameFindingVisitor(Map<Entry<?>, String> mappings) {
73 super(Utils.ASM_VERSION);
74 this.mappings = mappings;
75 }
76
77 @Override
78 public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
79 super.visit(version, access, name, signature, superName, interfaces);
80 this.className = name;
81 this.clazz = new ClassEntry(name);
82 this.enumFields.clear();
83 this.classInits.clear();
84 }
85
86 @Override
87 public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
88 if ((access & Opcodes.ACC_ENUM) != 0) {
89 if (!enumFields.add(new Pair<>(name, descriptor))) {
90 throw new IllegalArgumentException("Found two enum fields with the same name \"" + name + "\" and desc \"" + descriptor + "\"!");
91 }
92 }
93 return super.visitField(access, name, descriptor, signature, value);
94 }
95
96 @Override
97 public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
98 if ("<clinit>".equals(name)) {
99 MethodNode node = new MethodNode(api, access, name, descriptor, signature, exceptions);
100 classInits.add(node);
101 return node;
102 }
103 return super.visitMethod(access, name, descriptor, signature, exceptions);
104 }
105
106 @Override
107 public void visitEnd() {
108 super.visitEnd();
109 try {
110 collectResults();
111 } catch (Exception ex) {
112 throw new RuntimeException(ex);
113 }
114 }
115
116 private void collectResults() throws Exception {
117 String owner = className;
118 Analyzer<SourceValue> analyzer = new Analyzer<>(new SourceInterpreter());
119
120 for (MethodNode mn : classInits) {
121 Frame<SourceValue>[] frames = analyzer.analyze(className, mn);
122
123 InsnList instrs = mn.instructions;
124 for (int i = 1; i < instrs.size(); i++) {
125 AbstractInsnNode instr1 = instrs.get(i - 1);
126 AbstractInsnNode instr2 = instrs.get(i);
127 String s = null;
128
129 if (instr2.getOpcode() == Opcodes.PUTSTATIC
130 && ((FieldInsnNode) instr2).owner.equals(owner)
131 && enumFields.contains(new Pair<>(((FieldInsnNode) instr2).name, ((FieldInsnNode) instr2).desc))
132 && instr1.getOpcode() == Opcodes.INVOKESPECIAL
133 && "<init>".equals(((MethodInsnNode) instr1).name)) {
134
135 for (int j = 0; j < frames[i - 1].getStackSize(); j++) {
136 SourceValue sv = frames[i - 1].getStack(j);
137 for (AbstractInsnNode ci : sv.insns) {
138 if (ci instanceof LdcInsnNode && ((LdcInsnNode) ci).cst instanceof String) {
139 //if (s == null || !s.equals(((LdcInsnNode) ci).cst)) {
140 if (s == null) {
141 s = (String) (((LdcInsnNode) ci).cst);
142 // stringsFound++;
143 }
144 }
145 }
146 }
147 }
148
149 if (s != null) {
150 mappings.put(new FieldEntry(clazz, ((FieldInsnNode) instr2).name, new TypeDescriptor(((FieldInsnNode) instr2).desc)), s);
151 }
152 // report otherwise?
153 }
154 }
155 }
156 }
157}