From 360bbd1c2fca8cbd575907b7d930a8072fccb0c2 Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 1 Sep 2014 22:52:07 -0400 Subject: refactored jar,translation index. fixed bug with field renaming when fields are shadowed by subclasses --- src/cuchaz/enigma/mapping/Mappings.java | 22 +++- src/cuchaz/enigma/mapping/MappingsRenamer.java | 164 +++++++++++++++++++++++++ src/cuchaz/enigma/mapping/Renamer.java | 160 ------------------------ src/cuchaz/enigma/mapping/Translator.java | 21 ++-- 4 files changed, 196 insertions(+), 171 deletions(-) create mode 100644 src/cuchaz/enigma/mapping/MappingsRenamer.java delete mode 100644 src/cuchaz/enigma/mapping/Renamer.java (limited to 'src/cuchaz/enigma/mapping') diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index 378d4c0..f52094f 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java @@ -24,8 +24,7 @@ import com.beust.jcommander.internal.Sets; import com.google.common.collect.Maps; import cuchaz.enigma.Util; -import cuchaz.enigma.analysis.Ancestries; -import cuchaz.enigma.analysis.DeobfuscatedAncestries; +import cuchaz.enigma.analysis.TranslationIndex; import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; public class Mappings implements Serializable @@ -108,12 +107,27 @@ public class Mappings implements Serializable return m_classesByDeobf.get( deobfName ); } - public Translator getTranslator( Ancestries ancestries, TranslationDirection direction ) + public Translator getTranslator( TranslationIndex index, TranslationDirection direction ) { + if( direction == TranslationDirection.Obfuscating ) + { + // deobfuscate the index + index = new TranslationIndex( index ); + Map renames = Maps.newHashMap(); + for( ClassMapping classMapping : classes() ) + { + renames.put( classMapping.getObfName(), classMapping.getDeobfName() ); + for( ClassMapping innerClassMapping : classMapping.innerClasses() ) + { + renames.put( innerClassMapping.getObfName(), innerClassMapping.getDeobfName() ); + } + } + index.renameClasses( renames ); + } return new Translator( direction, direction.choose( m_classesByObf, m_classesByDeobf ), - direction.choose( ancestries, new DeobfuscatedAncestries( ancestries, m_classesByObf, m_classesByDeobf ) ) + index ); } diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java new file mode 100644 index 0000000..9d036d8 --- /dev/null +++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.mapping; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.util.Set; +import java.util.zip.GZIPOutputStream; + +import cuchaz.enigma.analysis.JarIndex; + +public class MappingsRenamer +{ + private JarIndex m_index; + private Mappings m_mappings; + + public MappingsRenamer( JarIndex index, Mappings mappings ) + { + m_index = index; + m_mappings = mappings; + } + + public void setClassName( ClassEntry obf, String deobfName ) + { + deobfName = NameValidator.validateClassName( deobfName ); + ClassEntry targetEntry = new ClassEntry( deobfName ); + if( m_mappings.containsDeobfClass( deobfName ) || m_index.containsObfClass( targetEntry ) ) + { + throw new IllegalNameException( deobfName, "There is already a class with that name" ); + } + + ClassMapping classMapping = getOrCreateClassMapping( obf ); + + if( obf.isInnerClass() ) + { + classMapping.setInnerClassName( obf.getInnerClassName(), deobfName ); + } + else + { + m_mappings.m_classesByDeobf.remove( classMapping.getDeobfName() ); + classMapping.setDeobfName( deobfName ); + m_mappings.m_classesByDeobf.put( deobfName, classMapping ); + } + + updateDeobfMethodSignatures(); + } + + public void setFieldName( FieldEntry obf, String deobfName ) + { + deobfName = NameValidator.validateFieldName( deobfName ); + FieldEntry targetEntry = new FieldEntry( obf.getClassEntry(), deobfName ); + if( m_mappings.containsDeobfField( obf.getClassEntry(), deobfName ) || m_index.containsObfField( targetEntry ) ) + { + throw new IllegalNameException( deobfName, "There is already a field with that name" ); + } + + ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); + classMapping.setFieldName( obf.getName(), deobfName ); + } + + public void setMethodTreeName( MethodEntry obf, String deobfName ) + { + Set implementations = m_index.getRelatedMethodImplementations( obf ); + + deobfName = NameValidator.validateMethodName( deobfName ); + for( MethodEntry entry : implementations ) + { + MethodEntry targetEntry = new MethodEntry( entry.getClassEntry(), deobfName, entry.getSignature() ); + if( m_mappings.containsDeobfMethod( entry.getClassEntry(), deobfName, entry.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) + { + String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( entry.getClassName() ); + throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); + } + } + + for( MethodEntry entry : implementations ) + { + setMethodName( entry, deobfName ); + } + } + + public void setMethodName( MethodEntry obf, String deobfName ) + { + deobfName = NameValidator.validateMethodName( deobfName ); + MethodEntry targetEntry = new MethodEntry( obf.getClassEntry(), deobfName, obf.getSignature() ); + if( m_mappings.containsDeobfMethod( obf.getClassEntry(), deobfName, obf.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) + { + String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( obf.getClassName() ); + throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); + } + + ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); + String deobfSignature = getTranslator( TranslationDirection.Deobfuscating ).translateSignature( obf.getSignature() ); + classMapping.setMethodNameAndSignature( obf.getName(), obf.getSignature(), deobfName, deobfSignature ); + } + + public void setArgumentName( ArgumentEntry obf, String deobfName ) + { + deobfName = NameValidator.validateArgumentName( deobfName ); + // NOTE: don't need to check arguments for name collisions with names determined by Procyon + if( m_mappings.containsArgument( obf.getMethodEntry(), deobfName ) ) + { + throw new IllegalNameException( deobfName, "There is already an argument with that name" ); + } + + ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); + classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName ); + } + + public void write( OutputStream out ) + throws IOException + { + // TEMP: just use the object output for now. We can find a more efficient storage format later + GZIPOutputStream gzipout = new GZIPOutputStream( out ); + ObjectOutputStream oout = new ObjectOutputStream( gzipout ); + oout.writeObject( this ); + gzipout.finish(); + } + + private ClassMapping getOrCreateClassMapping( ClassEntry obfClassEntry ) + { + String obfClassName = obfClassEntry.getOuterClassName(); + ClassMapping classMapping = m_mappings.m_classesByObf.get( obfClassName ); + if( classMapping == null ) + { + classMapping = new ClassMapping( obfClassName, obfClassName ); + m_mappings.m_classesByObf.put( classMapping.getObfName(), classMapping ); + m_mappings.m_classesByDeobf.put( classMapping.getDeobfName(), classMapping ); + } + return classMapping; + } + + private ClassMapping getOrCreateClassMappingOrInnerClassMapping( ClassEntry obfClassEntry ) + { + ClassMapping classMapping = getOrCreateClassMapping( obfClassEntry ); + if( obfClassEntry.isInnerClass() ) + { + classMapping = classMapping.getOrCreateInnerClass( obfClassEntry.getInnerClassName() ); + } + return classMapping; + } + + private void updateDeobfMethodSignatures( ) + { + for( ClassMapping classMapping : m_mappings.m_classesByObf.values() ) + { + classMapping.updateDeobfMethodSignatures( getTranslator( TranslationDirection.Deobfuscating ) ); + } + } + + private Translator getTranslator( TranslationDirection direction ) + { + return m_mappings.getTranslator( m_index.getTranslationIndex(), direction ); + } +} diff --git a/src/cuchaz/enigma/mapping/Renamer.java b/src/cuchaz/enigma/mapping/Renamer.java deleted file mode 100644 index 15d9af4..0000000 --- a/src/cuchaz/enigma/mapping/Renamer.java +++ /dev/null @@ -1,160 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - * - * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.mapping; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.util.Set; -import java.util.zip.GZIPOutputStream; - -import cuchaz.enigma.analysis.JarIndex; - -public class Renamer -{ - private JarIndex m_index; - private Mappings m_mappings; - - public Renamer( JarIndex index, Mappings mappings ) - { - m_index = index; - m_mappings = mappings; - } - - public void setClassName( ClassEntry obf, String deobfName ) - { - deobfName = NameValidator.validateClassName( deobfName ); - ClassEntry targetEntry = new ClassEntry( deobfName ); - if( m_mappings.containsDeobfClass( deobfName ) || m_index.containsObfClass( targetEntry ) ) - { - throw new IllegalNameException( deobfName, "There is already a class with that name" ); - } - - ClassMapping classMapping = getOrCreateClassMapping( obf ); - - if( obf.isInnerClass() ) - { - classMapping.setInnerClassName( obf.getInnerClassName(), deobfName ); - } - else - { - m_mappings.m_classesByDeobf.remove( classMapping.getDeobfName() ); - classMapping.setDeobfName( deobfName ); - m_mappings.m_classesByDeobf.put( deobfName, classMapping ); - } - - updateDeobfMethodSignatures(); - } - - public void setFieldName( FieldEntry obf, String deobfName ) - { - deobfName = NameValidator.validateFieldName( deobfName ); - FieldEntry targetEntry = new FieldEntry( obf.getClassEntry(), deobfName ); - if( m_mappings.containsDeobfField( obf.getClassEntry(), deobfName ) || m_index.containsObfField( targetEntry ) ) - { - throw new IllegalNameException( deobfName, "There is already a field with that name" ); - } - - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); - classMapping.setFieldName( obf.getName(), deobfName ); - } - - public void setMethodTreeName( MethodEntry obf, String deobfName ) - { - Set implementations = m_index.getRelatedMethodImplementations( obf ); - - deobfName = NameValidator.validateMethodName( deobfName ); - for( MethodEntry entry : implementations ) - { - MethodEntry targetEntry = new MethodEntry( entry.getClassEntry(), deobfName, entry.getSignature() ); - if( m_mappings.containsDeobfMethod( entry.getClassEntry(), deobfName, entry.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) - { - String className = m_mappings.getTranslator( m_index.getAncestries(), TranslationDirection.Deobfuscating ).translateClass( entry.getClassName() ); - throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + className ); - } - } - - for( MethodEntry entry : implementations ) - { - setMethodName( entry, deobfName ); - } - } - - public void setMethodName( MethodEntry obf, String deobfName ) - { - deobfName = NameValidator.validateMethodName( deobfName ); - MethodEntry targetEntry = new MethodEntry( obf.getClassEntry(), deobfName, obf.getSignature() ); - if( m_mappings.containsDeobfMethod( obf.getClassEntry(), deobfName, obf.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) - { - String className = m_mappings.getTranslator( m_index.getAncestries(), TranslationDirection.Deobfuscating ).translateClass( obf.getClassName() ); - throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + className ); - } - - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); - String deobfSignature = m_mappings.getTranslator( m_index.getAncestries(), TranslationDirection.Deobfuscating ).translateSignature( obf.getSignature() ); - classMapping.setMethodNameAndSignature( obf.getName(), obf.getSignature(), deobfName, deobfSignature ); - } - - public void setArgumentName( ArgumentEntry obf, String deobfName ) - { - deobfName = NameValidator.validateArgumentName( deobfName ); - // NOTE: don't need to check arguments for name collisions with names determined by Procyon - if( m_mappings.containsArgument( obf.getMethodEntry(), deobfName ) ) - { - throw new IllegalNameException( deobfName, "There is already an argument with that name" ); - } - - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); - classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName ); - } - - public void write( OutputStream out ) - throws IOException - { - // TEMP: just use the object output for now. We can find a more efficient storage format later - GZIPOutputStream gzipout = new GZIPOutputStream( out ); - ObjectOutputStream oout = new ObjectOutputStream( gzipout ); - oout.writeObject( this ); - gzipout.finish(); - } - - private ClassMapping getOrCreateClassMapping( ClassEntry obfClassEntry ) - { - String obfClassName = obfClassEntry.getOuterClassName(); - ClassMapping classMapping = m_mappings.m_classesByObf.get( obfClassName ); - if( classMapping == null ) - { - classMapping = new ClassMapping( obfClassName, obfClassName ); - m_mappings.m_classesByObf.put( classMapping.getObfName(), classMapping ); - m_mappings.m_classesByDeobf.put( classMapping.getDeobfName(), classMapping ); - } - return classMapping; - } - - private ClassMapping getOrCreateClassMappingOrInnerClassMapping( ClassEntry obfClassEntry ) - { - ClassMapping classMapping = getOrCreateClassMapping( obfClassEntry ); - if( obfClassEntry.isInnerClass() ) - { - classMapping = classMapping.getOrCreateInnerClass( obfClassEntry.getInnerClassName() ); - } - return classMapping; - } - - private void updateDeobfMethodSignatures( ) - { - Translator translator = m_mappings.getTranslator( m_index.getAncestries(), TranslationDirection.Deobfuscating ); - for( ClassMapping classMapping : m_mappings.m_classesByObf.values() ) - { - classMapping.updateDeobfMethodSignatures( translator ); - } - } -} diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java index 23bf095..f5aafdd 100644 --- a/src/cuchaz/enigma/mapping/Translator.java +++ b/src/cuchaz/enigma/mapping/Translator.java @@ -16,27 +16,27 @@ import java.util.Map; import com.beust.jcommander.internal.Maps; -import cuchaz.enigma.analysis.Ancestries; +import cuchaz.enigma.analysis.TranslationIndex; import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; public class Translator { private TranslationDirection m_direction; - public Map m_classes; - private Ancestries m_ancestries; + private Map m_classes; + private TranslationIndex m_index; public Translator( ) { m_direction = null; m_classes = Maps.newHashMap(); - m_ancestries = new Ancestries(); + m_index = new TranslationIndex(); } - protected Translator( TranslationDirection direction, Map classes, Ancestries ancestries ) + public Translator( TranslationDirection direction, Map classes, TranslationIndex index ) { m_direction = direction; m_classes = classes; - m_ancestries = ancestries; + m_index = index; } @SuppressWarnings( "unchecked" ) @@ -145,6 +145,13 @@ public class Translator return translatedName; } } + + // is the field implemented in this class? + if( m_index.containsField( className, in.getName() ) ) + { + // stop traversing the superclass chain + break; + } } return null; } @@ -291,7 +298,7 @@ public class Translator { List ancestry = new ArrayList(); ancestry.add( className ); - ancestry.addAll( m_ancestries.getAncestry( className ) ); + ancestry.addAll( m_index.getAncestry( className ) ); return ancestry; } -- cgit v1.2.3