diff options
Diffstat (limited to 'src/main/java/cuchaz/enigma/mapping')
| -rw-r--r-- | src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java | 58 | ||||
| -rw-r--r-- | src/main/java/cuchaz/enigma/mapping/Translator.java | 48 |
2 files changed, 93 insertions, 13 deletions
diff --git a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java b/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java index 7af1a52..dec5acf 100644 --- a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java +++ b/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java | |||
| @@ -15,13 +15,19 @@ import com.google.common.collect.Lists; | |||
| 15 | import com.google.common.collect.Maps; | 15 | import com.google.common.collect.Maps; |
| 16 | import cuchaz.enigma.analysis.TranslationIndex; | 16 | import cuchaz.enigma.analysis.TranslationIndex; |
| 17 | import cuchaz.enigma.bytecode.AccessFlags; | 17 | import cuchaz.enigma.bytecode.AccessFlags; |
| 18 | import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor; | ||
| 18 | import cuchaz.enigma.mapping.entry.*; | 19 | import cuchaz.enigma.mapping.entry.*; |
| 20 | import org.objectweb.asm.signature.SignatureReader; | ||
| 21 | import org.objectweb.asm.signature.SignatureVisitor; | ||
| 22 | import org.objectweb.asm.signature.SignatureWriter; | ||
| 19 | 23 | ||
| 20 | import java.util.ArrayList; | 24 | import java.util.ArrayList; |
| 21 | import java.util.List; | 25 | import java.util.List; |
| 22 | import java.util.Map; | 26 | import java.util.Map; |
| 27 | import java.util.regex.Pattern; | ||
| 23 | 28 | ||
| 24 | public class DirectionalTranslator implements Translator { | 29 | public class DirectionalTranslator implements Translator { |
| 30 | private static final Pattern OBJECT_PATTERN = Pattern.compile(".*:Ljava/lang/Object;:.*"); | ||
| 25 | 31 | ||
| 26 | private final TranslationDirection direction; | 32 | private final TranslationDirection direction; |
| 27 | private final Map<String, ClassMapping> classes; | 33 | private final Map<String, ClassMapping> classes; |
| @@ -98,7 +104,7 @@ public class DirectionalTranslator implements Translator { | |||
| 98 | public FieldDefEntry getTranslatedFieldDef(FieldDefEntry entry) { | 104 | public FieldDefEntry getTranslatedFieldDef(FieldDefEntry entry) { |
| 99 | String translatedName = translateFieldName(entry); | 105 | String translatedName = translateFieldName(entry); |
| 100 | if (translatedName == null) { | 106 | if (translatedName == null) { |
| 101 | return entry; | 107 | translatedName = entry.getName(); |
| 102 | } | 108 | } |
| 103 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); | 109 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); |
| 104 | TypeDescriptor translatedDesc = getTranslatedTypeDesc(entry.getDesc()); | 110 | TypeDescriptor translatedDesc = getTranslatedTypeDesc(entry.getDesc()); |
| @@ -110,7 +116,7 @@ public class DirectionalTranslator implements Translator { | |||
| 110 | public FieldEntry getTranslatedField(FieldEntry entry) { | 116 | public FieldEntry getTranslatedField(FieldEntry entry) { |
| 111 | String translatedName = translateFieldName(entry); | 117 | String translatedName = translateFieldName(entry); |
| 112 | if (translatedName == null) { | 118 | if (translatedName == null) { |
| 113 | return null; | 119 | translatedName = entry.getName(); |
| 114 | } | 120 | } |
| 115 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); | 121 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); |
| 116 | TypeDescriptor translatedDesc = getTranslatedTypeDesc(entry.getDesc()); | 122 | TypeDescriptor translatedDesc = getTranslatedTypeDesc(entry.getDesc()); |
| @@ -138,7 +144,7 @@ public class DirectionalTranslator implements Translator { | |||
| 138 | public MethodDefEntry getTranslatedMethodDef(MethodDefEntry entry) { | 144 | public MethodDefEntry getTranslatedMethodDef(MethodDefEntry entry) { |
| 139 | String translatedName = translateMethodName(entry); | 145 | String translatedName = translateMethodName(entry); |
| 140 | if (translatedName == null) { | 146 | if (translatedName == null) { |
| 141 | return entry; | 147 | translatedName = entry.getName(); |
| 142 | } | 148 | } |
| 143 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); | 149 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); |
| 144 | MethodDescriptor translatedDesc = getTranslatedMethodDesc(entry.getDesc()); | 150 | MethodDescriptor translatedDesc = getTranslatedMethodDesc(entry.getDesc()); |
| @@ -150,7 +156,7 @@ public class DirectionalTranslator implements Translator { | |||
| 150 | public MethodEntry getTranslatedMethod(MethodEntry entry) { | 156 | public MethodEntry getTranslatedMethod(MethodEntry entry) { |
| 151 | String translatedName = translateMethodName(entry); | 157 | String translatedName = translateMethodName(entry); |
| 152 | if (translatedName == null) { | 158 | if (translatedName == null) { |
| 153 | return null; | 159 | translatedName = entry.getName(); |
| 154 | } | 160 | } |
| 155 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); | 161 | ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); |
| 156 | MethodDescriptor translatedDesc = getTranslatedMethodDesc(entry.getDesc()); | 162 | MethodDescriptor translatedDesc = getTranslatedMethodDesc(entry.getDesc()); |
| @@ -181,11 +187,11 @@ public class DirectionalTranslator implements Translator { | |||
| 181 | translatedArgumentName = inheritLocalVariableName(entry); | 187 | translatedArgumentName = inheritLocalVariableName(entry); |
| 182 | } | 188 | } |
| 183 | if (translatedArgumentName == null) { | 189 | if (translatedArgumentName == null) { |
| 184 | return null; | 190 | translatedArgumentName = entry.getName(); |
| 185 | } | 191 | } |
| 186 | // TODO: Translating arguments calls method translation.. Can we refactor the code in such a way that we don't need this? | 192 | // TODO: Translating arguments calls method translation.. Can we refactor the code in such a way that we don't need this? |
| 187 | MethodEntry translatedOwner = getTranslatedMethod(entry.getOwnerEntry()); | 193 | MethodEntry translatedOwner = getTranslatedMethod(entry.getOwnerEntry()); |
| 188 | return new LocalVariableEntry(translatedOwner != null ? translatedOwner : entry.getOwnerEntry(), entry.getIndex(), translatedArgumentName); | 194 | return new LocalVariableEntry(translatedOwner, entry.getIndex(), translatedArgumentName); |
| 189 | } | 195 | } |
| 190 | 196 | ||
| 191 | @Override | 197 | @Override |
| @@ -200,6 +206,26 @@ public class DirectionalTranslator implements Translator { | |||
| 200 | return new LocalVariableDefEntry(translatedOwner, entry.getIndex(), translatedArgumentName != null ? translatedArgumentName : entry.getName(), translatedTypeDesc); | 206 | return new LocalVariableDefEntry(translatedOwner, entry.getIndex(), translatedArgumentName != null ? translatedArgumentName : entry.getName(), translatedTypeDesc); |
| 201 | } | 207 | } |
| 202 | 208 | ||
| 209 | @Override | ||
| 210 | public boolean hasClassMapping(ClassEntry entry) { | ||
| 211 | return classes.containsKey(entry.getName()); | ||
| 212 | } | ||
| 213 | |||
| 214 | @Override | ||
| 215 | public boolean hasFieldMapping(FieldEntry entry) { | ||
| 216 | return translateFieldName(entry) != null; | ||
| 217 | } | ||
| 218 | |||
| 219 | @Override | ||
| 220 | public boolean hasMethodMapping(MethodEntry entry) { | ||
| 221 | return translateMethodName(entry) != null; | ||
| 222 | } | ||
| 223 | |||
| 224 | @Override | ||
| 225 | public boolean hasLocalVariableMapping(LocalVariableEntry entry) { | ||
| 226 | return translateLocalVariableName(entry) != null || inheritLocalVariableName(entry) != null; | ||
| 227 | } | ||
| 228 | |||
| 203 | // TODO: support not identical behavior (specific to constructor) | 229 | // TODO: support not identical behavior (specific to constructor) |
| 204 | private String translateLocalVariableName(LocalVariableEntry entry) { | 230 | private String translateLocalVariableName(LocalVariableEntry entry) { |
| 205 | // look for identical behavior in superclasses | 231 | // look for identical behavior in superclasses |
| @@ -252,6 +278,26 @@ public class DirectionalTranslator implements Translator { | |||
| 252 | return new MethodDescriptor(translatedArguments, getTranslatedTypeDesc(descriptor.getReturnDesc())); | 278 | return new MethodDescriptor(translatedArguments, getTranslatedTypeDesc(descriptor.getReturnDesc())); |
| 253 | } | 279 | } |
| 254 | 280 | ||
| 281 | @Override | ||
| 282 | public String getTranslatedSignature(String signature, boolean isType, int api) { | ||
| 283 | if (signature == null) { | ||
| 284 | return null; | ||
| 285 | } | ||
| 286 | SignatureReader reader = new SignatureReader(signature); | ||
| 287 | SignatureWriter writer = new SignatureWriter(); | ||
| 288 | SignatureVisitor visitor = new TranslationSignatureVisitor(this, api, writer); | ||
| 289 | if (isType) { | ||
| 290 | reader.acceptType(visitor); | ||
| 291 | } else { | ||
| 292 | reader.accept(visitor); | ||
| 293 | } | ||
| 294 | String translatedSignature = writer.toString(); | ||
| 295 | if (OBJECT_PATTERN.matcher(signature).matches()) { | ||
| 296 | translatedSignature = signature.replaceAll(":Ljava/lang/Object;:", "::"); | ||
| 297 | } | ||
| 298 | return translatedSignature; | ||
| 299 | } | ||
| 300 | |||
| 255 | private ClassMapping findClassMapping(ClassEntry entry) { | 301 | private ClassMapping findClassMapping(ClassEntry entry) { |
| 256 | List<ClassMapping> mappingChain = getClassMappingChain(entry); | 302 | List<ClassMapping> mappingChain = getClassMappingChain(entry); |
| 257 | return mappingChain.get(mappingChain.size() - 1); | 303 | return mappingChain.get(mappingChain.size() - 1); |
diff --git a/src/main/java/cuchaz/enigma/mapping/Translator.java b/src/main/java/cuchaz/enigma/mapping/Translator.java index 6373da7..1bc2f37 100644 --- a/src/main/java/cuchaz/enigma/mapping/Translator.java +++ b/src/main/java/cuchaz/enigma/mapping/Translator.java | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | package cuchaz.enigma.mapping; | 12 | package cuchaz.enigma.mapping; |
| 13 | 13 | ||
| 14 | import cuchaz.enigma.mapping.entry.*; | 14 | import cuchaz.enigma.mapping.entry.*; |
| 15 | import org.objectweb.asm.Handle; | ||
| 15 | import org.objectweb.asm.Type; | 16 | import org.objectweb.asm.Type; |
| 16 | 17 | ||
| 17 | public interface Translator { | 18 | public interface Translator { |
| @@ -31,20 +32,53 @@ public interface Translator { | |||
| 31 | 32 | ||
| 32 | LocalVariableDefEntry getTranslatedVariableDef(LocalVariableDefEntry entry); | 33 | LocalVariableDefEntry getTranslatedVariableDef(LocalVariableDefEntry entry); |
| 33 | 34 | ||
| 35 | boolean hasClassMapping(ClassEntry entry); | ||
| 36 | |||
| 37 | boolean hasFieldMapping(FieldEntry entry); | ||
| 38 | |||
| 39 | boolean hasMethodMapping(MethodEntry entry); | ||
| 40 | |||
| 41 | boolean hasLocalVariableMapping(LocalVariableEntry entry); | ||
| 42 | |||
| 34 | TypeDescriptor getTranslatedTypeDesc(TypeDescriptor desc); | 43 | TypeDescriptor getTranslatedTypeDesc(TypeDescriptor desc); |
| 35 | 44 | ||
| 36 | MethodDescriptor getTranslatedMethodDesc(MethodDescriptor descriptor); | 45 | MethodDescriptor getTranslatedMethodDesc(MethodDescriptor descriptor); |
| 37 | 46 | ||
| 47 | String getTranslatedSignature(String signature, boolean isType, int api); | ||
| 48 | |||
| 38 | default Type getTranslatedType(Type type) { | 49 | default Type getTranslatedType(Type type) { |
| 39 | String descString = type.getDescriptor(); | 50 | String descString = type.getDescriptor(); |
| 40 | // If this is a method | 51 | switch (type.getSort()) { |
| 41 | if (descString.contains("(")) { | 52 | case Type.OBJECT: { |
| 42 | MethodDescriptor descriptor = new MethodDescriptor(descString); | 53 | ClassEntry classEntry = new ClassEntry(type.getInternalName()); |
| 43 | return Type.getMethodType(getTranslatedMethodDesc(descriptor).toString()); | 54 | return Type.getObjectType(getTranslatedClass(classEntry).getName()); |
| 44 | } else { | 55 | } |
| 45 | TypeDescriptor descriptor = new TypeDescriptor(descString); | 56 | case Type.ARRAY: { |
| 46 | return Type.getType(getTranslatedTypeDesc(descriptor).toString()); | 57 | TypeDescriptor descriptor = new TypeDescriptor(descString); |
| 58 | return Type.getType(getTranslatedTypeDesc(descriptor).toString()); | ||
| 59 | } | ||
| 60 | case Type.METHOD: { | ||
| 61 | MethodDescriptor descriptor = new MethodDescriptor(descString); | ||
| 62 | return Type.getMethodType(getTranslatedMethodDesc(descriptor).toString()); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | return type; | ||
| 66 | } | ||
| 67 | |||
| 68 | default Handle getTranslatedHandle(Handle handle) { | ||
| 69 | MethodEntry entry = new MethodEntry(new ClassEntry(handle.getOwner()), handle.getName(), new MethodDescriptor(handle.getDesc())); | ||
| 70 | MethodEntry translatedMethod = getTranslatedMethod(entry); | ||
| 71 | ClassEntry ownerClass = translatedMethod.getOwnerClassEntry(); | ||
| 72 | return new Handle(handle.getTag(), ownerClass.getName(), translatedMethod.getName(), translatedMethod.getDesc().toString(), handle.isInterface()); | ||
| 73 | } | ||
| 74 | |||
| 75 | default Object getTranslatedValue(Object value) { | ||
| 76 | if (value instanceof Type) { | ||
| 77 | return this.getTranslatedType((Type) value); | ||
| 78 | } else if (value instanceof Handle) { | ||
| 79 | return getTranslatedHandle((Handle) value); | ||
| 47 | } | 80 | } |
| 81 | return value; | ||
| 48 | } | 82 | } |
| 49 | 83 | ||
| 50 | @SuppressWarnings("unchecked") | 84 | @SuppressWarnings("unchecked") |