summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Runemoro2019-11-08 17:35:26 -0500
committerGravatar modmuss502019-11-08 22:35:26 +0000
commit1d3bc532d88602e536b32db1c894d1873ae1e823 (patch)
treed75605c5429111e28a16939ee529a91da92f50c2 /src
parentAllow multiple services for enigma (#168) (diff)
downloadenigma-1d3bc532d88602e536b32db1c894d1873ae1e823.tar.gz
enigma-1d3bc532d88602e536b32db1c894d1873ae1e823.tar.xz
enigma-1d3bc532d88602e536b32db1c894d1873ae1e823.zip
Fix local variable fixer (#172)
* Fix local variable fixer * LVT index -> LV index * Small fix * Use LocalNameGenerator
Diffstat (limited to 'src')
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java88
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java81
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java16
3 files changed, 92 insertions, 93 deletions
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java
index 16dbba1b..cfd8fbee 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java
@@ -1,14 +1,18 @@
1package cuchaz.enigma.bytecode.translators; 1package cuchaz.enigma.bytecode.translators;
2 2
3import com.google.common.base.CharMatcher; 3import com.google.common.base.CharMatcher;
4import cuchaz.enigma.translation.LocalNameGenerator;
4import cuchaz.enigma.translation.representation.TypeDescriptor; 5import cuchaz.enigma.translation.representation.TypeDescriptor;
5import cuchaz.enigma.translation.representation.entry.ClassDefEntry; 6import cuchaz.enigma.translation.representation.entry.ClassDefEntry;
6import cuchaz.enigma.translation.representation.entry.MethodDefEntry; 7import cuchaz.enigma.translation.representation.entry.MethodDefEntry;
7import org.objectweb.asm.ClassVisitor; 8import org.objectweb.asm.ClassVisitor;
8import org.objectweb.asm.Label; 9import org.objectweb.asm.Label;
9import org.objectweb.asm.MethodVisitor; 10import org.objectweb.asm.MethodVisitor;
11import org.objectweb.asm.Opcodes;
10 12
13import java.util.HashMap;
11import java.util.List; 14import java.util.List;
15import java.util.Map;
12 16
13public class LocalVariableFixVisitor extends ClassVisitor { 17public class LocalVariableFixVisitor extends ClassVisitor {
14 private ClassDefEntry ownerEntry; 18 private ClassDefEntry ownerEntry;
@@ -31,50 +35,92 @@ public class LocalVariableFixVisitor extends ClassVisitor {
31 35
32 private class Method extends MethodVisitor { 36 private class Method extends MethodVisitor {
33 private final MethodDefEntry methodEntry; 37 private final MethodDefEntry methodEntry;
34 private boolean hasLvt; 38 private final Map<Integer, String> parameterNames = new HashMap<>();
39 private final Map<Integer, Integer> parameterIndices = new HashMap<>();
40 private boolean hasParameterTable;
41 private int parameterIndex = 0;
35 42
36 Method(int api, MethodDefEntry methodEntry, MethodVisitor visitor) { 43 Method(int api, MethodDefEntry methodEntry, MethodVisitor visitor) {
37 super(api, visitor); 44 super(api, visitor);
38 this.methodEntry = methodEntry; 45 this.methodEntry = methodEntry;
46
47 int lvIndex = methodEntry.getAccess().isStatic() ? 0 : 1;
48 List<TypeDescriptor> parameters = methodEntry.getDesc().getArgumentDescs();
49 for (int parameterIndex = 0; parameterIndex < parameters.size(); parameterIndex++) {
50 TypeDescriptor param = parameters.get(parameterIndex);
51 parameterIndices.put(lvIndex, parameterIndex);
52 lvIndex += param.getSize();
53 }
39 } 54 }
40 55
41 @Override 56 @Override
42 public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { 57 public void visitParameter(String name, int access) {
43 hasLvt = true; 58 hasParameterTable = true;
44 59 super.visitParameter(fixParameterName(parameterIndex, name), fixParameterAccess(parameterIndex, access));
45 String translatedName = name; 60 parameterIndex++;
61 }
46 62
47 if (isInvalidName(name)) { 63 @Override
48 int argumentIndex = methodEntry.getArgumentIndex(ownerEntry, index); 64 public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
49 65 if (index == 0 && !methodEntry.getAccess().isStatic()) {
50 if (argumentIndex >= 0) { 66 name = "this";
51 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs(); 67 } else if (parameterIndices.containsKey(index)) {
52 boolean argument = argumentIndex < arguments.size(); 68 name = fixParameterName(parameterIndices.get(index), name);
53 if (argument) { 69 } else if (isInvalidName(name)) {
54 translatedName = "arg" + (argumentIndex + 1); 70 name = LocalNameGenerator.generateLocalVariableName(index, new TypeDescriptor(desc));
55 } else {
56 translatedName = "var" + (argumentIndex + 1);
57 }
58 }
59 } 71 }
60 72
61 super.visitLocalVariable(translatedName, desc, signature, start, end, index); 73 super.visitLocalVariable(name, desc, signature, start, end, index);
62 } 74 }
63 75
64 private boolean isInvalidName(String name) { 76 private boolean isInvalidName(String name) {
65 return !CharMatcher.ascii().matchesAllOf(name); 77 return name == null || name.isEmpty() || !CharMatcher.ascii().matchesAllOf(name);
66 } 78 }
67 79
68 @Override 80 @Override
69 public void visitEnd() { 81 public void visitEnd() {
70 if (!hasLvt) { 82 if (!hasParameterTable) {
71 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs(); 83 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs();
72 for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) { 84 for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) {
73 super.visitParameter("arg" + (argumentIndex + 1), 0); 85 super.visitParameter(fixParameterName(argumentIndex, null), fixParameterAccess(argumentIndex, 0));
74 } 86 }
75 } 87 }
76 88
77 super.visitEnd(); 89 super.visitEnd();
78 } 90 }
91
92 private String fixParameterName(int index, String name) {
93 if (parameterNames.get(index) != null) {
94 return parameterNames.get(index); // to make sure that LVT names are consistent with parameter table names
95 }
96
97 if (isInvalidName(name)) {
98 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs();
99 name = LocalNameGenerator.generateArgumentName(index, arguments.get(index), arguments);
100 }
101
102 if (index == 0 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("<init>")) {
103 name = "name";
104 }
105
106 if (index == 1 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("<init>")) {
107 name = "ordinal";
108 }
109
110 parameterNames.put(index, name);
111 return name;
112 }
113
114 private int fixParameterAccess(int index, int access) {
115 if (index == 0 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("<init>")) {
116 access |= Opcodes.ACC_SYNTHETIC;
117 }
118
119 if (index == 1 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("<init>")) {
120 access |= Opcodes.ACC_SYNTHETIC;
121 }
122
123 return access;
124 }
79 } 125 }
80} 126}
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
index c824265f..4bce5333 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
@@ -1,6 +1,5 @@
1package cuchaz.enigma.bytecode.translators; 1package cuchaz.enigma.bytecode.translators;
2 2
3import cuchaz.enigma.translation.LocalNameGenerator;
4import cuchaz.enigma.translation.Translator; 3import cuchaz.enigma.translation.Translator;
5import cuchaz.enigma.translation.representation.MethodDescriptor; 4import cuchaz.enigma.translation.representation.MethodDescriptor;
6import cuchaz.enigma.translation.representation.Signature; 5import cuchaz.enigma.translation.representation.Signature;
@@ -8,21 +7,27 @@ import cuchaz.enigma.translation.representation.TypeDescriptor;
8import cuchaz.enigma.translation.representation.entry.*; 7import cuchaz.enigma.translation.representation.entry.*;
9import org.objectweb.asm.*; 8import org.objectweb.asm.*;
10 9
11import java.util.List;
12import java.util.stream.Collectors;
13
14public class TranslationMethodVisitor extends MethodVisitor { 10public class TranslationMethodVisitor extends MethodVisitor {
15 private final ClassDefEntry ownerEntry;
16 private final MethodDefEntry methodEntry; 11 private final MethodDefEntry methodEntry;
17 private final Translator translator; 12 private final Translator translator;
18 13
19 private boolean hasParameterMeta; 14 private int parameterIndex = 0;
15 private int parameterLvIndex;
20 16
21 public TranslationMethodVisitor(Translator translator, ClassDefEntry ownerEntry, MethodDefEntry methodEntry, int api, MethodVisitor mv) { 17 public TranslationMethodVisitor(Translator translator, ClassDefEntry ownerEntry, MethodDefEntry methodEntry, int api, MethodVisitor mv) {
22 super(api, mv); 18 super(api, mv);
23 this.translator = translator; 19 this.translator = translator;
24 this.ownerEntry = ownerEntry;
25 this.methodEntry = methodEntry; 20 this.methodEntry = methodEntry;
21
22 parameterLvIndex = methodEntry.getAccess().isStatic() ? 0 : 1;
23 }
24
25 @Override
26 public void visitParameter(String name, int access) {
27 name = translateVariableName(parameterLvIndex, name);
28 parameterLvIndex += methodEntry.getDesc().getArgumentDescs().get(parameterIndex++).getSize();
29
30 super.visitParameter(name, access);
26 } 31 }
27 32
28 @Override 33 @Override
@@ -119,58 +124,22 @@ public class TranslationMethodVisitor extends MethodVisitor {
119 124
120 @Override 125 @Override
121 public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { 126 public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
122 hasParameterMeta = true; 127 signature = translator.translate(Signature.createTypedSignature(signature)).toString();
123 128 name = translateVariableName(index, name);
124 String translatedSignature = translator.translate(Signature.createTypedSignature(signature)).toString(); 129 desc = translator.translate(new TypeDescriptor(desc)).toString();
125 int argumentIndex = methodEntry.getArgumentIndex(ownerEntry, index);
126
127 if (argumentIndex >= 0) {
128 LocalVariableDefEntry entry = new LocalVariableDefEntry(methodEntry, index, name, true, new TypeDescriptor(desc));
129 LocalVariableDefEntry translatedEntry = translator.translate(entry);
130 String translatedName = translatedEntry.getName();
131
132 if (translatedName.equals(entry.getName())) {
133 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs();
134 List<TypeDescriptor> translatedArguments = arguments.stream()
135 .map(translator::translate)
136 .collect(Collectors.toList());
137
138 boolean argument = argumentIndex < arguments.size();
139 if (argument) {
140 translatedName = LocalNameGenerator.generateArgumentName(argumentIndex, translatedEntry.getDesc(), translatedArguments);
141 } else {
142 translatedName = LocalNameGenerator.generateLocalVariableName(argumentIndex, translatedEntry.getDesc());
143 }
144 }
145 130
146 super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), translatedSignature, start, end, index); 131 super.visitLocalVariable(name, desc, signature, start, end, index);
147 } else {
148 // Handle "this" variable
149 TypeDescriptor translatedDesc = translator.translate(new TypeDescriptor(desc));
150 super.visitLocalVariable(name, translatedDesc.toString(), translatedSignature, start, end, index);
151 }
152 } 132 }
153 133
154 @Override 134 private String translateVariableName(int index, String name) {
155 public void visitEnd() { 135 LocalVariableEntry entry = new LocalVariableEntry(methodEntry, index, "", true);
156 // If we didn't receive any parameter metadata, generate it 136 LocalVariableEntry translatedEntry = translator.translate(entry);
157 if (!hasParameterMeta) { 137 String translatedName = translatedEntry.getName();
158 List<TypeDescriptor> arguments = translator.translate(methodEntry.getDesc()).getArgumentDescs(); 138
159 int offset = ((methodEntry.getAccess().getFlags() & Opcodes.ACC_ABSTRACT) != 0) ? 1 : 0; 139 if (!translatedName.isEmpty()) {
160 140 return translatedName;
161 for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) {
162 LocalVariableEntry entry = new LocalVariableEntry(methodEntry, offset, "", true);
163 LocalVariableEntry translatedEntry = translator.translate(entry);
164 String translatedName = translatedEntry.getName();
165 if (translatedName.equals(entry.getName())) {
166 super.visitParameter(LocalNameGenerator.generateArgumentName(argumentIndex, arguments.get(argumentIndex), arguments), 0);
167 } else {
168 super.visitParameter(translatedName, 0);
169 }
170
171 offset += arguments.get(argumentIndex).getSize();
172 }
173 } 141 }
174 super.visitEnd(); 142
143 return name;
175 } 144 }
176} 145}
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java
index bbcaf235..7e89f6a6 100644
--- a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java
+++ b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java
@@ -72,20 +72,4 @@ public class MethodDefEntry extends MethodEntry implements DefEntry<ClassEntry>
72 public MethodDefEntry withParent(ClassEntry parent) { 72 public MethodDefEntry withParent(ClassEntry parent) {
73 return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access); 73 return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access);
74 } 74 }
75
76 public int getArgumentIndex(ClassDefEntry ownerEntry, int localVariableIndex) {
77 int argumentIndex = localVariableIndex;
78
79 // Enum constructors have an implicit "name" and "ordinal" parameter as well as "this"
80 if (ownerEntry.getAccess().isEnum() && getName().startsWith("<")) {
81 argumentIndex -= 2;
82 }
83
84 // If we're not static, "this" is bound to index 0
85 if (!getAccess().isStatic()) {
86 argumentIndex -= 1;
87 }
88
89 return argumentIndex;
90 }
91} 75}