From 71ec7b53a1b4ecce0623dded1e445818a757b695 Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 9 Feb 2015 12:17:26 -0500 Subject: add converter to update old mappings format fix a few decompiler issues too --- src/cuchaz/enigma/MainFormatConverter.java | 120 +++++++++++++++++++++ .../analysis/SourceIndexBehaviorVisitor.java | 12 +-- .../enigma/bytecode/MethodParameterWriter.java | 8 +- src/cuchaz/enigma/mapping/MappingsReader.java | 36 ++++--- 4 files changed, 152 insertions(+), 24 deletions(-) create mode 100644 src/cuchaz/enigma/MainFormatConverter.java (limited to 'src/cuchaz') diff --git a/src/cuchaz/enigma/MainFormatConverter.java b/src/cuchaz/enigma/MainFormatConverter.java new file mode 100644 index 00000000..1848144d --- /dev/null +++ b/src/cuchaz/enigma/MainFormatConverter.java @@ -0,0 +1,120 @@ +package cuchaz.enigma; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.jar.JarFile; + +import javassist.CtClass; +import javassist.CtField; + +import com.google.common.collect.Maps; + +import cuchaz.enigma.analysis.JarClassIterator; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.ClassMapping; +import cuchaz.enigma.mapping.ClassNameReplacer; +import cuchaz.enigma.mapping.FieldEntry; +import cuchaz.enigma.mapping.FieldMapping; +import cuchaz.enigma.mapping.JavassistUtil; +import cuchaz.enigma.mapping.Mappings; +import cuchaz.enigma.mapping.MappingsReader; +import cuchaz.enigma.mapping.MappingsWriter; +import cuchaz.enigma.mapping.Type; + +public class MainFormatConverter { + + public static void main(String[] args) + throws Exception { + + System.out.println("Getting field types from jar..."); + + JarFile jar = new JarFile(System.getProperty("user.home") + "/.minecraft/versions/1.8/1.8.jar"); + Map fieldTypes = Maps.newHashMap(); + for (CtClass c : JarClassIterator.classes(jar)) { + for (CtField field : c.getDeclaredFields()) { + FieldEntry fieldEntry = JavassistUtil.getFieldEntry(field); + fieldTypes.put(getFieldKey(fieldEntry), moveClasssesOutOfDefaultPackage(fieldEntry.getType())); + } + } + + System.out.println("Reading mappings..."); + + File fileMappings = new File("../Enigma Mappings/1.8.mappings"); + MappingsReader mappingsReader = new MappingsReader() { + + @Override + protected FieldMapping readField(String[] parts) { + // assume the void type for now + return new FieldMapping(parts[1], new Type("V"), parts[2]); + } + }; + Mappings mappings = mappingsReader.read(new FileReader(fileMappings)); + + System.out.println("Updating field types..."); + + for (ClassMapping classMapping : mappings.classes()) { + updateFieldsInClass(fieldTypes, classMapping); + } + + System.out.println("Saving mappings..."); + + try (FileWriter writer = new FileWriter(fileMappings)) { + new MappingsWriter().write(writer, mappings); + } + + System.out.println("Done!"); + } + + private static Type moveClasssesOutOfDefaultPackage(Type type) { + return new Type(type, new ClassNameReplacer() { + @Override + public String replace(String className) { + ClassEntry entry = new ClassEntry(className); + if (entry.isInDefaultPackage()) { + return Constants.NonePackage + "/" + className; + } + return null; + } + }); + } + + private static void updateFieldsInClass(Map fieldTypes, ClassMapping classMapping) + throws Exception { + + // update the fields + for (FieldMapping fieldMapping : classMapping.fields()) { + setFieldType(fieldTypes, classMapping, fieldMapping); + } + + // recurse + for (ClassMapping innerClassMapping : classMapping.innerClasses()) { + updateFieldsInClass(fieldTypes, innerClassMapping); + } + } + + private static void setFieldType(Map fieldTypes, ClassMapping classMapping, FieldMapping fieldMapping) + throws Exception { + + // get the new type + Type newType = fieldTypes.get(getFieldKey(classMapping, fieldMapping)); + if (newType == null) { + throw new Error("Can't find type for field: " + getFieldKey(classMapping, fieldMapping)); + } + + // hack in the new field type + Field field = fieldMapping.getClass().getDeclaredField("m_obfType"); + field.setAccessible(true); + field.set(fieldMapping, newType); + } + + private static Object getFieldKey(ClassMapping classMapping, FieldMapping fieldMapping) { + return new ClassEntry(classMapping.getObfName()).getSimpleName() + "." + fieldMapping.getObfName(); + } + + private static String getFieldKey(FieldEntry obfFieldEntry) { + return obfFieldEntry.getClassEntry().getSimpleName() + "." + obfFieldEntry.getName(); + } +} diff --git a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java index f15a724b..b4094d9e 100644 --- a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java +++ b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java @@ -66,11 +66,11 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor { if (ref instanceof MethodReference) { MethodReference methodRef = (MethodReference)ref; if (methodRef.isConstructor()) { - behaviorEntry = new ConstructorEntry(classEntry, new Signature(ref.getSignature())); + behaviorEntry = new ConstructorEntry(classEntry, new Signature(ref.getErasedSignature())); } else if (methodRef.isTypeInitializer()) { behaviorEntry = new ConstructorEntry(classEntry); } else { - behaviorEntry = new MethodEntry(classEntry, ref.getName(), new Signature(ref.getSignature())); + behaviorEntry = new MethodEntry(classEntry, ref.getName(), new Signature(ref.getErasedSignature())); } } if (behaviorEntry != null) { @@ -96,12 +96,12 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor { MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); if (ref != null) { // make sure this is actually a field - if (ref.getSignature().indexOf('(') >= 0) { + if (ref.getErasedSignature().indexOf('(') >= 0) { throw new Error("Expected a field here! got " + ref); } ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new Type(ref.getSignature())); + FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new Type(ref.getErasedSignature())); index.addReference(node.getMemberNameToken(), fieldEntry, m_behaviorEntry); } @@ -141,7 +141,7 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor { MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); if (ref != null) { ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new Type(ref.getSignature())); + FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new Type(ref.getErasedSignature())); index.addReference(node.getIdentifierToken(), fieldEntry, m_behaviorEntry); } @@ -153,7 +153,7 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor { MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); if (ref != null) { ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - ConstructorEntry constructorEntry = new ConstructorEntry(classEntry, new Signature(ref.getSignature())); + ConstructorEntry constructorEntry = new ConstructorEntry(classEntry, new Signature(ref.getErasedSignature())); if (node.getType() instanceof SimpleType) { SimpleType simpleTypeNode = (SimpleType)node.getType(); index.addReference(simpleTypeNode.getIdentifierToken(), constructorEntry, m_behaviorEntry); diff --git a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java index 5d4ca1ad..853928c7 100644 --- a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java +++ b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java @@ -18,6 +18,7 @@ import javassist.CtClass; import cuchaz.enigma.mapping.ArgumentEntry; import cuchaz.enigma.mapping.BehaviorEntry; import cuchaz.enigma.mapping.BehaviorEntryFactory; +import cuchaz.enigma.mapping.Signature; import cuchaz.enigma.mapping.Translator; public class MethodParameterWriter { @@ -35,7 +36,12 @@ public class MethodParameterWriter { BehaviorEntry behaviorEntry = BehaviorEntryFactory.create(behavior); // get the number of arguments - int numParams = behaviorEntry.getSignature().getArgumentTypes().size(); + Signature signature = behaviorEntry.getSignature(); + if (signature == null) { + // static initializers have no signatures, or arguments + continue; + } + int numParams = signature.getArgumentTypes().size(); if (numParams <= 0) { continue; } diff --git a/src/cuchaz/enigma/mapping/MappingsReader.java b/src/cuchaz/enigma/mapping/MappingsReader.java index 1e7b6e3d..bfb27319 100644 --- a/src/cuchaz/enigma/mapping/MappingsReader.java +++ b/src/cuchaz/enigma/mapping/MappingsReader.java @@ -19,11 +19,13 @@ import com.google.common.collect.Queues; public class MappingsReader { - public Mappings read(Reader in) throws IOException, MappingParseException { + public Mappings read(Reader in) + throws IOException, MappingParseException { return read(new BufferedReader(in)); } - public Mappings read(BufferedReader in) throws IOException, MappingParseException { + public Mappings read(BufferedReader in) + throws IOException, MappingParseException { Mappings mappings = new Mappings(); Deque mappingStack = Queues.newArrayDeque(); @@ -64,42 +66,41 @@ public class MappingsReader { if (token.equalsIgnoreCase("CLASS")) { ClassMapping classMapping; - if (indent == 0) { + if (indent <= 0) { // outer class classMapping = readClass(parts, false); mappings.addClassMapping(classMapping); - } else if (indent == 1) { + } else { + // inner class - if (! (mappingStack.getFirst() instanceof ClassMapping)) { + if (!(mappingStack.peek() instanceof ClassMapping)) { throw new MappingParseException(lineNumber, "Unexpected CLASS entry here!"); } classMapping = readClass(parts, true); - ((ClassMapping)mappingStack.getFirst()).addInnerClassMapping(classMapping); - } else { - throw new MappingParseException(lineNumber, "Unexpected CLASS entry nesting!"); + ((ClassMapping)mappingStack.peek()).addInnerClassMapping(classMapping); } mappingStack.push(classMapping); } else if (token.equalsIgnoreCase("FIELD")) { - if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof ClassMapping)) { + if (mappingStack.isEmpty() || ! (mappingStack.peek() instanceof ClassMapping)) { throw new MappingParseException(lineNumber, "Unexpected FIELD entry here!"); } - ((ClassMapping)mappingStack.getFirst()).addFieldMapping(readField(parts)); + ((ClassMapping)mappingStack.peek()).addFieldMapping(readField(parts)); } else if (token.equalsIgnoreCase("METHOD")) { - if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof ClassMapping)) { + if (mappingStack.isEmpty() || ! (mappingStack.peek() instanceof ClassMapping)) { throw new MappingParseException(lineNumber, "Unexpected METHOD entry here!"); } MethodMapping methodMapping = readMethod(parts); - ((ClassMapping)mappingStack.getFirst()).addMethodMapping(methodMapping); + ((ClassMapping)mappingStack.peek()).addMethodMapping(methodMapping); mappingStack.push(methodMapping); } else if (token.equalsIgnoreCase("ARG")) { - if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof MethodMapping)) { + if (mappingStack.isEmpty() || ! (mappingStack.peek() instanceof MethodMapping)) { throw new MappingParseException(lineNumber, "Unexpected ARG entry here!"); } - ((MethodMapping)mappingStack.getFirst()).addArgumentMapping(readArgument(parts)); + ((MethodMapping)mappingStack.peek()).addArgumentMapping(readArgument(parts)); } - } catch (ArrayIndexOutOfBoundsException | NumberFormatException ex) { - throw new MappingParseException(lineNumber, "Malformed line!"); + } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { + throw new MappingParseException(lineNumber, "Malformed line:\n" + line); } } @@ -118,7 +119,8 @@ public class MappingsReader { } } - private FieldMapping readField(String[] parts) { + /* TEMP */ + protected FieldMapping readField(String[] parts) { return new FieldMapping(parts[1], new Type(parts[3]), parts[2]); } -- cgit v1.2.3