From a88175ffc95792b88a8724f66db6dda2b8cc32ee Mon Sep 17 00:00:00 2001 From: gegy1000 Date: Tue, 17 Jul 2018 19:14:08 +0200 Subject: ASM Based Class Translator (#1) * Initial port to ASM * Package updates * Annotation + inner class translation * Fix inner class mapping * More bytecode translation * Signature refactoring * Fix highlighting of mapped names * Fix parameter name offset * Fix anonymous class generation * Fix issues with inner class signature transformation * Fix bridged method detection * Fix compile issues * Resolve all failed tests * Apply deobfuscated name to transformed classes * Fix class signatures not being translated * Fix frame array type translation * Fix frame array type translation * Fix array translation in method calls * Fix method reference and bridge detection * Fix handling of null deobf mappings * Parameter translation in interfaces * Fix enum parameter index offset * Fix parsed local variable indexing * Fix stackoverflow on rebuilding method names * Ignore invalid decompiled variable indices * basic source jar * Output directly to file on source export * Make decompile parallel * fix incorrect super calls * Use previous save state to delete old mapping files * Fix old mappings not properly being removed * Fix old mappings not properly being removed * make isMethodProvider public (cherry picked from commit ebad6a9) * speed up Deobfuscator's getSources by using a single TranslatingTypeloader and caching the ClassLoaderTypeloader * ignore .idea project folders * move SynchronizedTypeLoader to a non-inner * fix signature remap of inners for now * index & resolve method/field references for usages view * Allow reader/writer subclasses to provide the underlying file operations * fix giving obf classes a name not removing them from the panel * buffer the ParsedJar class entry inputstream, allow use with a jarinputstream * make CachingClasspathTypeLoader public * make CachingClasspathTypeLoader public * support enum switches with obfuscated SwitchMaps --- .../enigma/mapping/MappingsEnigmaReader.java | 167 +++++++++++---------- 1 file changed, 88 insertions(+), 79 deletions(-) (limited to 'src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java') diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java index a0d4313..ddbee76 100644 --- a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java +++ b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java @@ -5,8 +5,14 @@ import com.google.common.collect.Queues; import cuchaz.enigma.throwables.MappingConflict; import cuchaz.enigma.throwables.MappingParseException; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.Deque; +import java.util.function.Supplier; public class MappingsEnigmaReader { @@ -39,92 +45,95 @@ public class MappingsEnigmaReader { } public Mappings readFile(Mappings mappings, File file) throws IOException, MappingParseException { + return readFileStream(mappings, new FileInputStream(file), file::getAbsolutePath); + } - BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charsets.UTF_8)); - Deque mappingStack = Queues.newArrayDeque(); + public Mappings readFileStream(Mappings mappings, InputStream stream, Supplier filenameSupplier) throws IOException, MappingParseException { + try (BufferedReader in = new BufferedReader(new InputStreamReader(stream, Charsets.UTF_8))) { + Deque mappingStack = Queues.newArrayDeque(); - int lineNumber = 0; - String line; - while ((line = in.readLine()) != null) { - lineNumber++; + int lineNumber = 0; + String line; + while ((line = in.readLine()) != null) { + lineNumber++; - // strip comments - int commentPos = line.indexOf('#'); - if (commentPos >= 0) { - line = line.substring(0, commentPos); - } + // strip comments + int commentPos = line.indexOf('#'); + if (commentPos >= 0) { + line = line.substring(0, commentPos); + } - // skip blank lines - if (line.trim().length() <= 0) { - continue; - } + // skip blank lines + if (line.trim().length() <= 0) { + continue; + } - // get the indent of this line - int indent = 0; - for (int i = 0; i < line.length(); i++) { - if (line.charAt(i) != '\t') { - break; + // get the indent of this line + int indent = 0; + for (int i = 0; i < line.length(); i++) { + if (line.charAt(i) != '\t') { + break; + } + indent++; } - indent++; - } - // handle stack pops - while (indent < mappingStack.size()) { - mappingStack.pop(); - } + // handle stack pops + while (indent < mappingStack.size()) { + mappingStack.pop(); + } - String[] parts = line.trim().split("\\s"); - try { - // read the first token - String token = parts[0]; - - if (token.equalsIgnoreCase("CLASS")) { - ClassMapping classMapping; - if (indent <= 0) { - // outer class - classMapping = readClass(parts, false); - mappings.addClassMapping(classMapping); - } else { - - // inner class - if (!(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(file, lineNumber, "Unexpected CLASS entry here!"); + String[] parts = line.trim().split("\\s"); + try { + // read the first token + String token = parts[0]; + + if (token.equalsIgnoreCase("CLASS")) { + ClassMapping classMapping; + if (indent <= 0) { + // outer class + classMapping = readClass(parts, false); + mappings.addClassMapping(classMapping); + } else { + + // inner class + if (!(mappingStack.peek() instanceof ClassMapping)) { + throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected CLASS entry here!"); + } + + classMapping = readClass(parts, true); + ((ClassMapping) mappingStack.peek()).addInnerClassMapping(classMapping); } - - classMapping = readClass(parts, true); - ((ClassMapping) mappingStack.peek()).addInnerClassMapping(classMapping); - } - mappingStack.push(classMapping); - } else if (token.equalsIgnoreCase("FIELD")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(file, lineNumber, "Unexpected FIELD entry here!"); - } - ((ClassMapping) mappingStack.peek()).addFieldMapping(readField(parts)); - } else if (token.equalsIgnoreCase("METHOD")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(file, lineNumber, "Unexpected METHOD entry here!"); - } - MethodMapping methodMapping = readMethod(parts); - ((ClassMapping) mappingStack.peek()).addMethodMapping(methodMapping); - mappingStack.push(methodMapping); - } else if (token.equalsIgnoreCase("ARG")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof MethodMapping)) { - throw new MappingParseException(file, lineNumber, "Unexpected ARG entry here!"); + mappingStack.push(classMapping); + } else if (token.equalsIgnoreCase("FIELD")) { + if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { + throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected FIELD entry here!"); + } + ((ClassMapping) mappingStack.peek()).addFieldMapping(readField(parts)); + } else if (token.equalsIgnoreCase("METHOD")) { + if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { + throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected METHOD entry here!"); + } + MethodMapping methodMapping = readMethod(parts); + ((ClassMapping) mappingStack.peek()).addMethodMapping(methodMapping); + mappingStack.push(methodMapping); + } else if (token.equalsIgnoreCase("ARG")) { + if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof MethodMapping)) { + throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected ARG entry here!"); + } + ((MethodMapping) mappingStack.peek()).addArgumentMapping(readArgument(parts)); } - ((MethodMapping) mappingStack.peek()).addArgumentMapping(readArgument(parts)); + } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { + throw new MappingParseException(filenameSupplier, lineNumber, "Malformed line:\n" + line); + } catch (MappingConflict e) { + throw new MappingParseException(filenameSupplier, lineNumber, e.getMessage()); } - } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { - throw new MappingParseException(file, lineNumber, "Malformed line:\n" + line); - } catch (MappingConflict e) { - throw new MappingParseException(file, lineNumber, e.getMessage()); } + return mappings; } - in.close(); - return mappings; } - private ArgumentMapping readArgument(String[] parts) { - return new ArgumentMapping(Integer.parseInt(parts[1]), parts[2]); + private LocalVariableMapping readArgument(String[] parts) { + return new LocalVariableMapping(Integer.parseInt(parts[1]), parts[2]); } private ClassMapping readClass(String[] parts, boolean makeSimple) { @@ -150,27 +159,27 @@ public class MappingsEnigmaReader { if (parts.length == 4) { boolean access = parts[3].startsWith("ACC:"); if (access) - mapping = new FieldMapping(parts[1], new Type(parts[2]), null, + mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[2]), null, Mappings.EntryModifier.valueOf(parts[3].substring(4))); else - mapping = new FieldMapping(parts[1], new Type(parts[3]), parts[2], Mappings.EntryModifier.UNCHANGED); + mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[3]), parts[2], Mappings.EntryModifier.UNCHANGED); } else if (parts.length == 5) - mapping = new FieldMapping(parts[1], new Type(parts[3]), parts[2], Mappings.EntryModifier.valueOf(parts[4].substring(4))); + mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[3]), parts[2], Mappings.EntryModifier.valueOf(parts[4].substring(4))); return mapping; } private MethodMapping readMethod(String[] parts) { MethodMapping mapping = null; if (parts.length == 3) - mapping = new MethodMapping(parts[1], new Signature(parts[2])); + mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[2])); else if (parts.length == 4) { boolean access = parts[3].startsWith("ACC:"); if (access) - mapping = new MethodMapping(parts[1], new Signature(parts[2]), null, Mappings.EntryModifier.valueOf(parts[3].substring(4))); + mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[2]), null, Mappings.EntryModifier.valueOf(parts[3].substring(4))); else - mapping = new MethodMapping(parts[1], new Signature(parts[3]), parts[2]); + mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[3]), parts[2]); } else if (parts.length == 5) - mapping = new MethodMapping(parts[1], new Signature(parts[3]), parts[2], + mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[3]), parts[2], Mappings.EntryModifier.valueOf(parts[4].substring(4))); return mapping; } -- cgit v1.2.3