From ba7a354efae7d49833c887cf147ac940c975a1fa Mon Sep 17 00:00:00 2001 From: Gegy Date: Wed, 30 Jan 2019 21:05:32 +0200 Subject: Remap sources (#106) * Source remapping beginnings * Fix navigation to remapped classes * Translate identifier info reference * Remap local variables with default names in source * Caching translator * Fix lack of highlighting for first opened class * Fix unicode variable names * Unicode checker shouldn't be checking just alphanumeric * Fix package tree being built from obf names * Don't index `this` as method call for method::reference * Apply proposed names * Fix source export issues * Replace unicode var names at bytecode level uniquely * Drop imports from editor source * Class selector fixes * Delta keep track of base mappings to enable lookup of old names * Optimize source remapping by remapping source with a StringBuffer instead of copying * Bump version --- .../translators/LocalVariableFixVisitor.java | 80 +++++++++++++++ .../translators/TranslationClassVisitor.java | 7 +- .../translators/TranslationMethodVisitor.java | 111 +++++++-------------- 3 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java (limited to 'src/main/java/cuchaz/enigma/bytecode') diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java new file mode 100644 index 0000000..16dbba1 --- /dev/null +++ b/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java @@ -0,0 +1,80 @@ +package cuchaz.enigma.bytecode.translators; + +import com.google.common.base.CharMatcher; +import cuchaz.enigma.translation.representation.TypeDescriptor; +import cuchaz.enigma.translation.representation.entry.ClassDefEntry; +import cuchaz.enigma.translation.representation.entry.MethodDefEntry; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import java.util.List; + +public class LocalVariableFixVisitor extends ClassVisitor { + private ClassDefEntry ownerEntry; + + public LocalVariableFixVisitor(int api, ClassVisitor visitor) { + super(api, visitor); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + ownerEntry = ClassDefEntry.parse(access, name, signature, superName, interfaces); + super.visit(version, access, name, signature, superName, interfaces); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + MethodDefEntry methodEntry = MethodDefEntry.parse(ownerEntry, access, name, descriptor, signature); + return new Method(api, methodEntry, super.visitMethod(access, name, descriptor, signature, exceptions)); + } + + private class Method extends MethodVisitor { + private final MethodDefEntry methodEntry; + private boolean hasLvt; + + Method(int api, MethodDefEntry methodEntry, MethodVisitor visitor) { + super(api, visitor); + this.methodEntry = methodEntry; + } + + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { + hasLvt = true; + + String translatedName = name; + + if (isInvalidName(name)) { + int argumentIndex = methodEntry.getArgumentIndex(ownerEntry, index); + + if (argumentIndex >= 0) { + List arguments = methodEntry.getDesc().getArgumentDescs(); + boolean argument = argumentIndex < arguments.size(); + if (argument) { + translatedName = "arg" + (argumentIndex + 1); + } else { + translatedName = "var" + (argumentIndex + 1); + } + } + } + + super.visitLocalVariable(translatedName, desc, signature, start, end, index); + } + + private boolean isInvalidName(String name) { + return !CharMatcher.ascii().matchesAllOf(name); + } + + @Override + public void visitEnd() { + if (!hasLvt) { + List arguments = methodEntry.getDesc().getArgumentDescs(); + for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) { + super.visitParameter("arg" + (argumentIndex + 1), 0); + } + } + + super.visitEnd(); + } + } +} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java index 53d09bb..e4c41d3 100644 --- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java +++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java @@ -13,7 +13,6 @@ package cuchaz.enigma.bytecode.translators; import cuchaz.enigma.translation.Translator; import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.ReferencedEntryPool; import cuchaz.enigma.translation.representation.TypeDescriptor; import cuchaz.enigma.translation.representation.entry.*; import org.objectweb.asm.*; @@ -22,14 +21,12 @@ import java.util.Arrays; public class TranslationClassVisitor extends ClassVisitor { private final Translator translator; - private final ReferencedEntryPool entryPool; private ClassDefEntry obfClassEntry; - public TranslationClassVisitor(Translator translator, ReferencedEntryPool entryPool, int api, ClassVisitor cv) { + public TranslationClassVisitor(Translator translator, int api, ClassVisitor cv) { super(api, cv); this.translator = translator; - this.entryPool = entryPool; } @Override @@ -57,7 +54,7 @@ public class TranslationClassVisitor extends ClassVisitor { MethodDefEntry translatedEntry = translator.translate(entry); String[] translatedExceptions = new String[exceptions.length]; for (int i = 0; i < exceptions.length; i++) { - translatedExceptions[i] = translator.translate(entryPool.getClass(exceptions[i])).getFullName(); + translatedExceptions[i] = translator.translate(new ClassEntry(exceptions[i])).getFullName(); } MethodVisitor mv = super.visitMethod(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), translatedEntry.getSignature().toString(), translatedExceptions); return new TranslationMethodVisitor(translator, obfClassEntry, entry, api, mv); diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java index a5a33e6..c824265 100644 --- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java +++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java @@ -1,16 +1,14 @@ package cuchaz.enigma.bytecode.translators; +import cuchaz.enigma.translation.LocalNameGenerator; import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.NameValidator; import cuchaz.enigma.translation.representation.MethodDescriptor; import cuchaz.enigma.translation.representation.Signature; import cuchaz.enigma.translation.representation.TypeDescriptor; import cuchaz.enigma.translation.representation.entry.*; import org.objectweb.asm.*; -import java.util.Collection; import java.util.List; -import java.util.Locale; import java.util.stream.Collectors; public class TranslationMethodVisitor extends MethodVisitor { @@ -83,40 +81,6 @@ public class TranslationMethodVisitor extends MethodVisitor { return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av); } - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { - hasParameterMeta = true; - - String translatedSignature = translator.translate(Signature.createTypedSignature(signature)).toString(); - int argumentIndex = methodEntry.getArgumentIndex(ownerEntry, index); - - if (argumentIndex >= 0) { - LocalVariableDefEntry entry = new LocalVariableDefEntry(methodEntry, index, name, true, new TypeDescriptor(desc)); - LocalVariableDefEntry translatedEntry = translator.translate(entry); - String translatedName = translatedEntry.getName(); - - if (translatedName.equals(entry.getName())) { - List arguments = methodEntry.getDesc().getArgumentDescs(); - List translatedArguments = arguments.stream() - .map(translator::translate) - .collect(Collectors.toList()); - - boolean argument = argumentIndex < arguments.size(); - if (argument) { - translatedName = inferArgumentName(argumentIndex, translatedEntry.getDesc(), translatedArguments); - } else { - translatedName = inferLocalVariableName(argumentIndex, translatedEntry.getDesc()); - } - } - - super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), translatedSignature, start, end, index); - } else { - // Handle "this" variable - TypeDescriptor translatedDesc = translator.translate(new TypeDescriptor(desc)); - super.visitLocalVariable(name, translatedDesc.toString(), translatedSignature, start, end, index); - } - } - @Override public void visitTypeInsn(int opcode, String type) { ClassEntry translatedEntry = translator.translate(new ClassEntry(type)); @@ -153,11 +117,45 @@ public class TranslationMethodVisitor extends MethodVisitor { } } + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { + hasParameterMeta = true; + + String translatedSignature = translator.translate(Signature.createTypedSignature(signature)).toString(); + int argumentIndex = methodEntry.getArgumentIndex(ownerEntry, index); + + if (argumentIndex >= 0) { + LocalVariableDefEntry entry = new LocalVariableDefEntry(methodEntry, index, name, true, new TypeDescriptor(desc)); + LocalVariableDefEntry translatedEntry = translator.translate(entry); + String translatedName = translatedEntry.getName(); + + if (translatedName.equals(entry.getName())) { + List arguments = methodEntry.getDesc().getArgumentDescs(); + List translatedArguments = arguments.stream() + .map(translator::translate) + .collect(Collectors.toList()); + + boolean argument = argumentIndex < arguments.size(); + if (argument) { + translatedName = LocalNameGenerator.generateArgumentName(argumentIndex, translatedEntry.getDesc(), translatedArguments); + } else { + translatedName = LocalNameGenerator.generateLocalVariableName(argumentIndex, translatedEntry.getDesc()); + } + } + + super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), translatedSignature, start, end, index); + } else { + // Handle "this" variable + TypeDescriptor translatedDesc = translator.translate(new TypeDescriptor(desc)); + super.visitLocalVariable(name, translatedDesc.toString(), translatedSignature, start, end, index); + } + } + @Override public void visitEnd() { // If we didn't receive any parameter metadata, generate it if (!hasParameterMeta) { - List arguments = methodEntry.getDesc().getArgumentDescs(); + List arguments = translator.translate(methodEntry.getDesc()).getArgumentDescs(); int offset = ((methodEntry.getAccess().getFlags() & Opcodes.ACC_ABSTRACT) != 0) ? 1 : 0; for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) { @@ -165,7 +163,7 @@ public class TranslationMethodVisitor extends MethodVisitor { LocalVariableEntry translatedEntry = translator.translate(entry); String translatedName = translatedEntry.getName(); if (translatedName.equals(entry.getName())) { - super.visitParameter(inferArgumentName(argumentIndex, arguments.get(argumentIndex), arguments), 0); + super.visitParameter(LocalNameGenerator.generateArgumentName(argumentIndex, arguments.get(argumentIndex), arguments), 0); } else { super.visitParameter(translatedName, 0); } @@ -175,39 +173,4 @@ public class TranslationMethodVisitor extends MethodVisitor { } super.visitEnd(); } - - private String inferArgumentName(int index, TypeDescriptor desc, Collection arguments) { - boolean uniqueType = arguments.stream().filter(desc::equals).count() <= 1; - String translatedName; - int nameIndex = index + 1; - StringBuilder nameBuilder = new StringBuilder(getTypeName(desc)); - if (!uniqueType || NameValidator.isReserved(nameBuilder.toString())) { - nameBuilder.append(nameIndex); - } - translatedName = nameBuilder.toString(); - return translatedName; - } - - private String inferLocalVariableName(int index, TypeDescriptor desc) { - int nameIndex = index + 1; - return getTypeName(desc) + nameIndex; - } - - private String getTypeName(TypeDescriptor desc) { - // Unfortunately each of these have different name getters, so they have different code paths - if (desc.isPrimitive()) { - TypeDescriptor.Primitive argCls = desc.getPrimitive(); - return argCls.name().toLowerCase(Locale.ROOT); - } else if (desc.isArray()) { - // List types would require this whole block again, so just go with aListx - return "arr"; - } else if (desc.isType()) { - String typeName = desc.getTypeEntry().getSimpleName().replace("$", ""); - typeName = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1); - return typeName; - } else { - System.err.println("Encountered invalid argument type descriptor " + desc.toString()); - return "var"; - } - } } -- cgit v1.2.3