diff options
| author | 2019-11-08 17:35:26 -0500 | |
|---|---|---|
| committer | 2019-11-08 22:35:26 +0000 | |
| commit | 1d3bc532d88602e536b32db1c894d1873ae1e823 (patch) | |
| tree | d75605c5429111e28a16939ee529a91da92f50c2 /src | |
| parent | Allow multiple services for enigma (#168) (diff) | |
| download | enigma-fork-1d3bc532d88602e536b32db1c894d1873ae1e823.tar.gz enigma-fork-1d3bc532d88602e536b32db1c894d1873ae1e823.tar.xz enigma-fork-1d3bc532d88602e536b32db1c894d1873ae1e823.zip | |
Fix local variable fixer (#172)
* Fix local variable fixer
* LVT index -> LV index
* Small fix
* Use LocalNameGenerator
Diffstat (limited to 'src')
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 16dbba1..cfd8fbe 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 @@ | |||
| 1 | package cuchaz.enigma.bytecode.translators; | 1 | package cuchaz.enigma.bytecode.translators; |
| 2 | 2 | ||
| 3 | import com.google.common.base.CharMatcher; | 3 | import com.google.common.base.CharMatcher; |
| 4 | import cuchaz.enigma.translation.LocalNameGenerator; | ||
| 4 | import cuchaz.enigma.translation.representation.TypeDescriptor; | 5 | import cuchaz.enigma.translation.representation.TypeDescriptor; |
| 5 | import cuchaz.enigma.translation.representation.entry.ClassDefEntry; | 6 | import cuchaz.enigma.translation.representation.entry.ClassDefEntry; |
| 6 | import cuchaz.enigma.translation.representation.entry.MethodDefEntry; | 7 | import cuchaz.enigma.translation.representation.entry.MethodDefEntry; |
| 7 | import org.objectweb.asm.ClassVisitor; | 8 | import org.objectweb.asm.ClassVisitor; |
| 8 | import org.objectweb.asm.Label; | 9 | import org.objectweb.asm.Label; |
| 9 | import org.objectweb.asm.MethodVisitor; | 10 | import org.objectweb.asm.MethodVisitor; |
| 11 | import org.objectweb.asm.Opcodes; | ||
| 10 | 12 | ||
| 13 | import java.util.HashMap; | ||
| 11 | import java.util.List; | 14 | import java.util.List; |
| 15 | import java.util.Map; | ||
| 12 | 16 | ||
| 13 | public class LocalVariableFixVisitor extends ClassVisitor { | 17 | public 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 c824265..4bce533 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 @@ | |||
| 1 | package cuchaz.enigma.bytecode.translators; | 1 | package cuchaz.enigma.bytecode.translators; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.LocalNameGenerator; | ||
| 4 | import cuchaz.enigma.translation.Translator; | 3 | import cuchaz.enigma.translation.Translator; |
| 5 | import cuchaz.enigma.translation.representation.MethodDescriptor; | 4 | import cuchaz.enigma.translation.representation.MethodDescriptor; |
| 6 | import cuchaz.enigma.translation.representation.Signature; | 5 | import cuchaz.enigma.translation.representation.Signature; |
| @@ -8,21 +7,27 @@ import cuchaz.enigma.translation.representation.TypeDescriptor; | |||
| 8 | import cuchaz.enigma.translation.representation.entry.*; | 7 | import cuchaz.enigma.translation.representation.entry.*; |
| 9 | import org.objectweb.asm.*; | 8 | import org.objectweb.asm.*; |
| 10 | 9 | ||
| 11 | import java.util.List; | ||
| 12 | import java.util.stream.Collectors; | ||
| 13 | |||
| 14 | public class TranslationMethodVisitor extends MethodVisitor { | 10 | public 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 bbcaf23..7e89f6a 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 | } |