diff options
| author | 2014-09-24 20:32:19 -0400 | |
|---|---|---|
| committer | 2014-09-24 20:32:19 -0400 | |
| commit | 064fe6a628f23f21eb2c8f584215f439e54cfaec (patch) | |
| tree | 733f840aca8dca170e9403de51be256b24ed00b2 | |
| parent | HOW DO I WRITE SO MANY BUGS?!? (diff) | |
| download | enigma-fork-064fe6a628f23f21eb2c8f584215f439e54cfaec.tar.gz enigma-fork-064fe6a628f23f21eb2c8f584215f439e54cfaec.tar.xz enigma-fork-064fe6a628f23f21eb2c8f584215f439e54cfaec.zip | |
fixed in-jar detection for bridge-related methods
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 39 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/BridgeFixer.java | 22 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/EntryRenamer.java | 25 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 40 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java | 12 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/ClassTranslator.java | 41 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/BehaviorEntry.java | 12 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/BehaviorEntryFactory.java | 76 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MethodEntry.java | 4 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MethodMapping.java | 5 |
10 files changed, 170 insertions, 106 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index f7f7448..9a33917 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -41,6 +41,8 @@ import cuchaz.enigma.analysis.SourceIndex; | |||
| 41 | import cuchaz.enigma.analysis.SourceIndexVisitor; | 41 | import cuchaz.enigma.analysis.SourceIndexVisitor; |
| 42 | import cuchaz.enigma.analysis.Token; | 42 | import cuchaz.enigma.analysis.Token; |
| 43 | import cuchaz.enigma.mapping.ArgumentEntry; | 43 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 44 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 45 | import cuchaz.enigma.mapping.BehaviorEntryFactory; | ||
| 44 | import cuchaz.enigma.mapping.ClassEntry; | 46 | import cuchaz.enigma.mapping.ClassEntry; |
| 45 | import cuchaz.enigma.mapping.ClassMapping; | 47 | import cuchaz.enigma.mapping.ClassMapping; |
| 46 | import cuchaz.enigma.mapping.ConstructorEntry; | 48 | import cuchaz.enigma.mapping.ConstructorEntry; |
| @@ -165,6 +167,12 @@ public class Deobfuscator | |||
| 165 | // methods | 167 | // methods |
| 166 | for( MethodMapping methodMapping : Lists.newArrayList( classMapping.methods() ) ) | 168 | for( MethodMapping methodMapping : Lists.newArrayList( classMapping.methods() ) ) |
| 167 | { | 169 | { |
| 170 | // skip constructors | ||
| 171 | if( methodMapping.isConstructor() ) | ||
| 172 | { | ||
| 173 | continue; | ||
| 174 | } | ||
| 175 | |||
| 168 | MethodEntry methodEntry = new MethodEntry( obfClassEntry, methodMapping.getObfName(), methodMapping.getObfSignature() ); | 176 | MethodEntry methodEntry = new MethodEntry( obfClassEntry, methodMapping.getObfName(), methodMapping.getObfSignature() ); |
| 169 | ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( methodEntry ); | 177 | ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( methodEntry ); |
| 170 | if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( methodEntry.getClassEntry() ) ) | 178 | if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( methodEntry.getClassEntry() ) ) |
| @@ -228,33 +236,12 @@ public class Deobfuscator | |||
| 228 | // check methods | 236 | // check methods |
| 229 | for( MethodMapping methodMapping : Lists.newArrayList( classMapping.methods() ) ) | 237 | for( MethodMapping methodMapping : Lists.newArrayList( classMapping.methods() ) ) |
| 230 | { | 238 | { |
| 231 | if( methodMapping.getObfName().equals( "<clinit>" ) ) | 239 | BehaviorEntry obfBehaviorEntry = BehaviorEntryFactory.createObf( classEntry, methodMapping ); |
| 232 | { | 240 | if( !m_jarIndex.containsObfBehavior( obfBehaviorEntry ) ) |
| 233 | // skip static initializers | ||
| 234 | continue; | ||
| 235 | } | ||
| 236 | else if( methodMapping.getObfName().equals( "<init>" ) ) | ||
| 237 | { | ||
| 238 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, methodMapping.getObfSignature() ); | ||
| 239 | if( !m_jarIndex.containsObfBehavior( constructorEntry ) ) | ||
| 240 | { | ||
| 241 | System.err.println( "WARNING: unable to find constructor " + constructorEntry + ". dropping mapping." ); | ||
| 242 | classMapping.removeMethodMapping( methodMapping ); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | else | ||
| 246 | { | 241 | { |
| 247 | MethodEntry methodEntry = new MethodEntry( | 242 | System.err.println( "WARNING: unable to find behavior " + obfBehaviorEntry + ". dropping mapping." ); |
| 248 | classEntry, | 243 | classMapping.removeMethodMapping( methodMapping ); |
| 249 | methodMapping.getObfName(), | 244 | } |
| 250 | methodMapping.getObfSignature() | ||
| 251 | ); | ||
| 252 | if( !m_jarIndex.containsObfBehavior( methodEntry ) ) | ||
| 253 | { | ||
| 254 | System.err.println( "WARNING: unable to find method " + methodEntry + ". dropping mapping." ); | ||
| 255 | classMapping.removeMethodMapping( methodMapping ); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | } | 245 | } |
| 259 | 246 | ||
| 260 | // check inner classes | 247 | // check inner classes |
diff --git a/src/cuchaz/enigma/analysis/BridgeFixer.java b/src/cuchaz/enigma/analysis/BridgeFixer.java index aeaf871..112b864 100644 --- a/src/cuchaz/enigma/analysis/BridgeFixer.java +++ b/src/cuchaz/enigma/analysis/BridgeFixer.java | |||
| @@ -15,6 +15,8 @@ import javassist.CtMethod; | |||
| 15 | import javassist.bytecode.ConstPool; | 15 | import javassist.bytecode.ConstPool; |
| 16 | import javassist.bytecode.Descriptor; | 16 | import javassist.bytecode.Descriptor; |
| 17 | import cuchaz.enigma.bytecode.ConstPoolEditor; | 17 | import cuchaz.enigma.bytecode.ConstPoolEditor; |
| 18 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 19 | import cuchaz.enigma.mapping.BehaviorEntryFactory; | ||
| 18 | import cuchaz.enigma.mapping.ClassEntry; | 20 | import cuchaz.enigma.mapping.ClassEntry; |
| 19 | import cuchaz.enigma.mapping.MethodEntry; | 21 | import cuchaz.enigma.mapping.MethodEntry; |
| 20 | 22 | ||
| @@ -57,17 +59,23 @@ public class BridgeFixer | |||
| 57 | case ConstPool.CONST_Methodref: | 59 | case ConstPool.CONST_Methodref: |
| 58 | case ConstPool.CONST_InterfaceMethodref: | 60 | case ConstPool.CONST_InterfaceMethodref: |
| 59 | { | 61 | { |
| 60 | // translate the name and type | 62 | BehaviorEntry behaviorEntry = BehaviorEntryFactory.create( |
| 61 | MethodEntry methodEntry = new MethodEntry( | 63 | Descriptor.toJvmName( editor.getMemberrefClassname( i ) ), |
| 62 | new ClassEntry( Descriptor.toJvmName( editor.getMemberrefClassname( i ) ) ), | ||
| 63 | editor.getMemberrefName( i ), | 64 | editor.getMemberrefName( i ), |
| 64 | editor.getMemberrefType( i ) | 65 | editor.getMemberrefType( i ) |
| 65 | ); | 66 | ); |
| 66 | MethodEntry bridgeMethodEntry = m_index.getBridgeMethod( methodEntry ); | 67 | |
| 67 | if( bridgeMethodEntry != null ) | 68 | if( behaviorEntry instanceof MethodEntry ) |
| 68 | { | 69 | { |
| 69 | // FIXIT FIXIT FIXIT FIXIT FIXIT FIXIT FIXIT | 70 | MethodEntry methodEntry = (MethodEntry)behaviorEntry; |
| 70 | editor.changeMemberrefNameAndType( i, bridgeMethodEntry.getName(), bridgeMethodEntry.getSignature() ); | 71 | |
| 72 | // translate the name and type | ||
| 73 | MethodEntry bridgeMethodEntry = m_index.getBridgeMethod( methodEntry ); | ||
| 74 | if( bridgeMethodEntry != null ) | ||
| 75 | { | ||
| 76 | // FIXIT FIXIT FIXIT FIXIT FIXIT FIXIT FIXIT | ||
| 77 | editor.changeMemberrefNameAndType( i, bridgeMethodEntry.getName(), bridgeMethodEntry.getSignature() ); | ||
| 78 | } | ||
| 71 | } | 79 | } |
| 72 | } | 80 | } |
| 73 | break; | 81 | break; |
diff --git a/src/cuchaz/enigma/analysis/EntryRenamer.java b/src/cuchaz/enigma/analysis/EntryRenamer.java index 44e0220..2d59fe9 100644 --- a/src/cuchaz/enigma/analysis/EntryRenamer.java +++ b/src/cuchaz/enigma/analysis/EntryRenamer.java | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | package cuchaz.enigma.analysis; | 11 | package cuchaz.enigma.analysis; |
| 12 | 12 | ||
| 13 | import java.util.AbstractMap; | 13 | import java.util.AbstractMap; |
| 14 | import java.util.Iterator; | ||
| 15 | import java.util.List; | 14 | import java.util.List; |
| 16 | import java.util.Map; | 15 | import java.util.Map; |
| 17 | import java.util.Set; | 16 | import java.util.Set; |
| @@ -80,16 +79,32 @@ public class EntryRenamer | |||
| 80 | { | 79 | { |
| 81 | // for each key/value pair... | 80 | // for each key/value pair... |
| 82 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); | 81 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); |
| 83 | Iterator<Map.Entry<Key,Val>> iter = map.entries().iterator(); | 82 | for( Map.Entry<Key,Val> entry : map.entries() ) |
| 84 | while( iter.hasNext() ) | ||
| 85 | { | 83 | { |
| 86 | Map.Entry<Key,Val> entry = iter.next(); | ||
| 87 | iter.remove(); | ||
| 88 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( | 84 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( |
| 89 | renameMethodsInThing( renames, entry.getKey() ), | 85 | renameMethodsInThing( renames, entry.getKey() ), |
| 90 | renameMethodsInThing( renames, entry.getValue() ) | 86 | renameMethodsInThing( renames, entry.getValue() ) |
| 91 | ) ); | 87 | ) ); |
| 92 | } | 88 | } |
| 89 | map.clear(); | ||
| 90 | for( Map.Entry<Key,Val> entry : entriesToAdd ) | ||
| 91 | { | ||
| 92 | map.put( entry.getKey(), entry.getValue() ); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | public static <Key,Val> void renameMethodsInMap( Map<MethodEntry,MethodEntry> renames, Map<Key,Val> map ) | ||
| 97 | { | ||
| 98 | // for each key/value pair... | ||
| 99 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); | ||
| 100 | for( Map.Entry<Key,Val> entry : map.entrySet() ) | ||
| 101 | { | ||
| 102 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( | ||
| 103 | renameMethodsInThing( renames, entry.getKey() ), | ||
| 104 | renameMethodsInThing( renames, entry.getValue() ) | ||
| 105 | ) ); | ||
| 106 | } | ||
| 107 | map.clear(); | ||
| 93 | for( Map.Entry<Key,Val> entry : entriesToAdd ) | 108 | for( Map.Entry<Key,Val> entry : entriesToAdd ) |
| 94 | { | 109 | { |
| 95 | map.put( entry.getKey(), entry.getValue() ); | 110 | map.put( entry.getKey(), entry.getValue() ); |
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 9f309ce..a2f6bf3 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -44,6 +44,7 @@ import cuchaz.enigma.Constants; | |||
| 44 | import cuchaz.enigma.bytecode.ClassRenamer; | 44 | import cuchaz.enigma.bytecode.ClassRenamer; |
| 45 | import cuchaz.enigma.mapping.ArgumentEntry; | 45 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 46 | import cuchaz.enigma.mapping.BehaviorEntry; | 46 | import cuchaz.enigma.mapping.BehaviorEntry; |
| 47 | import cuchaz.enigma.mapping.BehaviorEntryFactory; | ||
| 47 | import cuchaz.enigma.mapping.ClassEntry; | 48 | import cuchaz.enigma.mapping.ClassEntry; |
| 48 | import cuchaz.enigma.mapping.ConstructorEntry; | 49 | import cuchaz.enigma.mapping.ConstructorEntry; |
| 49 | import cuchaz.enigma.mapping.Entry; | 50 | import cuchaz.enigma.mapping.Entry; |
| @@ -203,6 +204,7 @@ public class JarIndex | |||
| 203 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_methodImplementations ); | 204 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_methodImplementations ); |
| 204 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_behaviorReferences ); | 205 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_behaviorReferences ); |
| 205 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_fieldReferences ); | 206 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_fieldReferences ); |
| 207 | EntryRenamer.renameMethodsInMap( m_bridgeMethods, m_access ); | ||
| 206 | } | 208 | } |
| 207 | 209 | ||
| 208 | private void indexField( CtField field ) | 210 | private void indexField( CtField field ) |
| @@ -224,21 +226,20 @@ public class JarIndex | |||
| 224 | private void indexBehavior( CtBehavior behavior ) | 226 | private void indexBehavior( CtBehavior behavior ) |
| 225 | { | 227 | { |
| 226 | // get the behavior entry | 228 | // get the behavior entry |
| 227 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); | 229 | final BehaviorEntry behaviorEntry = BehaviorEntryFactory.create( behavior ); |
| 228 | final BehaviorEntry behaviorEntry = getBehaviorEntry( behavior ); | ||
| 229 | if( behaviorEntry instanceof MethodEntry ) | 230 | if( behaviorEntry instanceof MethodEntry ) |
| 230 | { | 231 | { |
| 231 | MethodEntry methodEntry = (MethodEntry)behaviorEntry; | 232 | MethodEntry methodEntry = (MethodEntry)behaviorEntry; |
| 232 | 233 | ||
| 233 | // index implementation | 234 | // index implementation |
| 234 | m_methodImplementations.put( className, methodEntry ); | 235 | m_methodImplementations.put( behaviorEntry.getClassName(), methodEntry ); |
| 235 | 236 | ||
| 236 | // look for bridge methods | 237 | // look for bridge methods |
| 237 | CtMethod bridgedMethod = getBridgedMethod( (CtMethod)behavior ); | 238 | CtMethod bridgedMethod = getBridgedMethod( (CtMethod)behavior ); |
| 238 | if( bridgedMethod != null ) | 239 | if( bridgedMethod != null ) |
| 239 | { | 240 | { |
| 240 | MethodEntry bridgedMethodEntry = new MethodEntry( | 241 | MethodEntry bridgedMethodEntry = new MethodEntry( |
| 241 | new ClassEntry( className ), | 242 | behaviorEntry.getClassEntry(), |
| 242 | bridgedMethod.getName(), | 243 | bridgedMethod.getName(), |
| 243 | bridgedMethod.getSignature() | 244 | bridgedMethod.getSignature() |
| 244 | ); | 245 | ); |
| @@ -251,7 +252,7 @@ public class JarIndex | |||
| 251 | private void indexBehaviorReferences( CtBehavior behavior ) | 252 | private void indexBehaviorReferences( CtBehavior behavior ) |
| 252 | { | 253 | { |
| 253 | // index method calls | 254 | // index method calls |
| 254 | final BehaviorEntry behaviorEntry = getBehaviorEntry( behavior ); | 255 | final BehaviorEntry behaviorEntry = BehaviorEntryFactory.create( behavior ); |
| 255 | try | 256 | try |
| 256 | { | 257 | { |
| 257 | behavior.instrument( new ExprEditor( ) | 258 | behavior.instrument( new ExprEditor( ) |
| @@ -344,35 +345,6 @@ public class JarIndex | |||
| 344 | } | 345 | } |
| 345 | } | 346 | } |
| 346 | 347 | ||
| 347 | private BehaviorEntry getBehaviorEntry( CtBehavior behavior ) | ||
| 348 | { | ||
| 349 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); | ||
| 350 | if( behavior instanceof CtMethod ) | ||
| 351 | { | ||
| 352 | return new MethodEntry( | ||
| 353 | new ClassEntry( className ), | ||
| 354 | behavior.getName(), | ||
| 355 | behavior.getSignature() | ||
| 356 | ); | ||
| 357 | } | ||
| 358 | else if( behavior instanceof CtConstructor ) | ||
| 359 | { | ||
| 360 | boolean isStatic = behavior.getName().equals( "<clinit>" ); | ||
| 361 | if( isStatic ) | ||
| 362 | { | ||
| 363 | return new ConstructorEntry( new ClassEntry( className ) ); | ||
| 364 | } | ||
| 365 | else | ||
| 366 | { | ||
| 367 | return new ConstructorEntry( new ClassEntry( className ), behavior.getSignature() ); | ||
| 368 | } | ||
| 369 | } | ||
| 370 | else | ||
| 371 | { | ||
| 372 | throw new IllegalArgumentException( "behavior must be a method or a constructor!" ); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | public ClassEntry resolveEntryClass( Entry obfEntry ) | 348 | public ClassEntry resolveEntryClass( Entry obfEntry ) |
| 377 | { | 349 | { |
| 378 | // this entry could refer to a method on a class where the method is not actually implemented | 350 | // this entry could refer to a method on a class where the method is not actually implemented |
diff --git a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java index b789726..5d8a383 100644 --- a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java +++ b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java | |||
| @@ -25,11 +25,11 @@ import com.strobel.decompiler.languages.java.ast.TypeDeclaration; | |||
| 25 | import com.strobel.decompiler.languages.java.ast.VariableInitializer; | 25 | import com.strobel.decompiler.languages.java.ast.VariableInitializer; |
| 26 | 26 | ||
| 27 | import cuchaz.enigma.mapping.BehaviorEntry; | 27 | import cuchaz.enigma.mapping.BehaviorEntry; |
| 28 | import cuchaz.enigma.mapping.BehaviorEntryFactory; | ||
| 28 | import cuchaz.enigma.mapping.ClassEntry; | 29 | import cuchaz.enigma.mapping.ClassEntry; |
| 29 | import cuchaz.enigma.mapping.ConstructorEntry; | 30 | import cuchaz.enigma.mapping.ConstructorEntry; |
| 30 | import cuchaz.enigma.mapping.Entry; | 31 | import cuchaz.enigma.mapping.Entry; |
| 31 | import cuchaz.enigma.mapping.FieldEntry; | 32 | import cuchaz.enigma.mapping.FieldEntry; |
| 32 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 33 | 33 | ||
| 34 | public class SourceIndexClassVisitor extends SourceIndexVisitor | 34 | public class SourceIndexClassVisitor extends SourceIndexVisitor |
| 35 | { | 35 | { |
| @@ -77,15 +77,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor | |||
| 77 | { | 77 | { |
| 78 | MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); | 78 | MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); |
| 79 | ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); | 79 | ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); |
| 80 | BehaviorEntry behaviorEntry; | 80 | BehaviorEntry behaviorEntry = BehaviorEntryFactory.create( classEntry, def.getName(), def.getSignature() ); |
| 81 | if( def.getName().equals( "<clinit>" ) ) | ||
| 82 | { | ||
| 83 | behaviorEntry = new ConstructorEntry( classEntry ); | ||
| 84 | } | ||
| 85 | else | ||
| 86 | { | ||
| 87 | behaviorEntry = new MethodEntry( classEntry, def.getName(), def.getSignature() ); | ||
| 88 | } | ||
| 89 | index.addDeclaration( node.getNameToken(), behaviorEntry ); | 81 | index.addDeclaration( node.getNameToken(), behaviorEntry ); |
| 90 | return node.acceptVisitor( new SourceIndexBehaviorVisitor( behaviorEntry ), index ); | 82 | return node.acceptVisitor( new SourceIndexBehaviorVisitor( behaviorEntry ), index ); |
| 91 | } | 83 | } |
diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java index 8892692..db28f21 100644 --- a/src/cuchaz/enigma/bytecode/ClassTranslator.java +++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java | |||
| @@ -21,6 +21,8 @@ import javassist.bytecode.Descriptor; | |||
| 21 | 21 | ||
| 22 | import com.google.common.collect.Maps; | 22 | import com.google.common.collect.Maps; |
| 23 | 23 | ||
| 24 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 25 | import cuchaz.enigma.mapping.BehaviorEntryFactory; | ||
| 24 | import cuchaz.enigma.mapping.ClassEntry; | 26 | import cuchaz.enigma.mapping.ClassEntry; |
| 25 | import cuchaz.enigma.mapping.FieldEntry; | 27 | import cuchaz.enigma.mapping.FieldEntry; |
| 26 | import cuchaz.enigma.mapping.MethodEntry; | 28 | import cuchaz.enigma.mapping.MethodEntry; |
| @@ -53,19 +55,15 @@ public class ClassTranslator | |||
| 53 | new ClassEntry( Descriptor.toJvmName( constants.getFieldrefClassName( i ) ) ), | 55 | new ClassEntry( Descriptor.toJvmName( constants.getFieldrefClassName( i ) ) ), |
| 54 | constants.getFieldrefName( i ) | 56 | constants.getFieldrefName( i ) |
| 55 | ); | 57 | ); |
| 56 | String translatedName = m_translator.translate( entry ); | 58 | FieldEntry translatedEntry = m_translator.translateEntry( entry ); |
| 57 | if( translatedName == null ) | ||
| 58 | { | ||
| 59 | translatedName = entry.getName(); | ||
| 60 | } | ||
| 61 | 59 | ||
| 62 | // translate the type | 60 | // translate the type |
| 63 | String type = constants.getFieldrefType( i ); | 61 | String type = constants.getFieldrefType( i ); |
| 64 | String translatedType = m_translator.translateSignature( type ); | 62 | String translatedType = m_translator.translateSignature( type ); |
| 65 | 63 | ||
| 66 | if( !entry.getName().equals( translatedName ) || !type.equals( translatedType ) ) | 64 | if( !entry.equals( translatedEntry ) || !type.equals( translatedType ) ) |
| 67 | { | 65 | { |
| 68 | editor.changeMemberrefNameAndType( i, translatedName, translatedType ); | 66 | editor.changeMemberrefNameAndType( i, translatedEntry.getName(), translatedType ); |
| 69 | } | 67 | } |
| 70 | } | 68 | } |
| 71 | break; | 69 | break; |
| @@ -74,21 +72,16 @@ public class ClassTranslator | |||
| 74 | case ConstPool.CONST_InterfaceMethodref: | 72 | case ConstPool.CONST_InterfaceMethodref: |
| 75 | { | 73 | { |
| 76 | // translate the name and type | 74 | // translate the name and type |
| 77 | MethodEntry entry = new MethodEntry( | 75 | BehaviorEntry entry = BehaviorEntryFactory.create( |
| 78 | new ClassEntry( Descriptor.toJvmName( editor.getMemberrefClassname( i ) ) ), | 76 | Descriptor.toJvmName( editor.getMemberrefClassname( i ) ), |
| 79 | editor.getMemberrefName( i ), | 77 | editor.getMemberrefName( i ), |
| 80 | editor.getMemberrefType( i ) | 78 | editor.getMemberrefType( i ) |
| 81 | ); | 79 | ); |
| 82 | String translatedName = m_translator.translate( entry ); | 80 | BehaviorEntry translatedEntry = m_translator.translateEntry( entry ); |
| 83 | if( translatedName == null ) | ||
| 84 | { | ||
| 85 | translatedName = entry.getName(); | ||
| 86 | } | ||
| 87 | String translatedSignature = m_translator.translateSignature( entry.getSignature() ); | ||
| 88 | 81 | ||
| 89 | if( !entry.getName().equals( translatedName ) || !entry.getSignature().equals( translatedSignature ) ) | 82 | if( !entry.getName().equals( translatedEntry.getName() ) || !entry.getSignature().equals( translatedEntry.getSignature() ) ) |
| 90 | { | 83 | { |
| 91 | editor.changeMemberrefNameAndType( i, translatedName, translatedSignature ); | 84 | editor.changeMemberrefNameAndType( i, translatedEntry.getName(), translatedEntry.getSignature() ); |
| 92 | } | 85 | } |
| 93 | } | 86 | } |
| 94 | break; | 87 | break; |
| @@ -116,14 +109,16 @@ public class ClassTranslator | |||
| 116 | // translate all the methods and constructors | 109 | // translate all the methods and constructors |
| 117 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) | 110 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) |
| 118 | { | 111 | { |
| 119 | // translate the name | 112 | if( behavior instanceof CtMethod ) |
| 120 | MethodEntry entry = new MethodEntry( classEntry, behavior.getName(), behavior.getSignature() ); | ||
| 121 | String translatedName = m_translator.translate( entry ); | ||
| 122 | if( translatedName != null ) | ||
| 123 | { | 113 | { |
| 124 | if( behavior instanceof CtMethod ) | 114 | CtMethod method = (CtMethod)behavior; |
| 115 | |||
| 116 | // translate the name | ||
| 117 | MethodEntry entry = new MethodEntry( classEntry, method.getName(), method.getSignature() ); | ||
| 118 | String translatedName = m_translator.translate( entry ); | ||
| 119 | if( translatedName != null ) | ||
| 125 | { | 120 | { |
| 126 | ((CtMethod)behavior).setName( translatedName ); | 121 | method.setName( translatedName ); |
| 127 | } | 122 | } |
| 128 | } | 123 | } |
| 129 | 124 | ||
diff --git a/src/cuchaz/enigma/mapping/BehaviorEntry.java b/src/cuchaz/enigma/mapping/BehaviorEntry.java index 99fdd28..8fc4eaf 100644 --- a/src/cuchaz/enigma/mapping/BehaviorEntry.java +++ b/src/cuchaz/enigma/mapping/BehaviorEntry.java | |||
| @@ -1,6 +1,16 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 1 | package cuchaz.enigma.mapping; | 11 | package cuchaz.enigma.mapping; |
| 2 | 12 | ||
| 3 | public interface BehaviorEntry extends Entry | 13 | public interface BehaviorEntry extends Entry |
| 4 | { | 14 | { |
| 5 | public String getSignature(); | 15 | String getSignature(); |
| 6 | } | 16 | } |
diff --git a/src/cuchaz/enigma/mapping/BehaviorEntryFactory.java b/src/cuchaz/enigma/mapping/BehaviorEntryFactory.java new file mode 100644 index 0000000..d3cfb93 --- /dev/null +++ b/src/cuchaz/enigma/mapping/BehaviorEntryFactory.java | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.mapping; | ||
| 12 | |||
| 13 | import javassist.CtBehavior; | ||
| 14 | import javassist.CtConstructor; | ||
| 15 | import javassist.CtMethod; | ||
| 16 | import javassist.bytecode.Descriptor; | ||
| 17 | |||
| 18 | |||
| 19 | public class BehaviorEntryFactory | ||
| 20 | { | ||
| 21 | public static BehaviorEntry create( String className, String name, String signature ) | ||
| 22 | { | ||
| 23 | return create( new ClassEntry( className ), name, signature ); | ||
| 24 | } | ||
| 25 | |||
| 26 | public static BehaviorEntry create( ClassEntry classEntry, String name, String signature ) | ||
| 27 | { | ||
| 28 | if( name.equals( "<init>" ) ) | ||
| 29 | { | ||
| 30 | return new ConstructorEntry( classEntry, signature ); | ||
| 31 | } | ||
| 32 | else if( name.equals( "<clinit>" ) ) | ||
| 33 | { | ||
| 34 | return new ConstructorEntry( classEntry ); | ||
| 35 | } | ||
| 36 | else | ||
| 37 | { | ||
| 38 | return new MethodEntry( classEntry, name, signature ); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | public static BehaviorEntry create( CtBehavior behavior ) | ||
| 43 | { | ||
| 44 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); | ||
| 45 | if( behavior instanceof CtMethod ) | ||
| 46 | { | ||
| 47 | return create( className, behavior.getName(), behavior.getSignature() ); | ||
| 48 | } | ||
| 49 | else if( behavior instanceof CtConstructor ) | ||
| 50 | { | ||
| 51 | CtConstructor constructor = (CtConstructor)behavior; | ||
| 52 | if( constructor.isClassInitializer() ) | ||
| 53 | { | ||
| 54 | return create( className, "<clinit>", null ); | ||
| 55 | } | ||
| 56 | else | ||
| 57 | { | ||
| 58 | return create( className, "<init>", constructor.getSignature() ); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | else | ||
| 62 | { | ||
| 63 | throw new IllegalArgumentException( "Unable to create BehaviorEntry from " + behavior ); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | public static BehaviorEntry createObf( ClassEntry classEntry, MethodMapping methodMapping ) | ||
| 68 | { | ||
| 69 | return create( classEntry, methodMapping.getObfName(), methodMapping.getObfSignature() ); | ||
| 70 | } | ||
| 71 | |||
| 72 | public static BehaviorEntry createDeobf( ClassEntry classEntry, MethodMapping methodMapping ) | ||
| 73 | { | ||
| 74 | return create( classEntry, methodMapping.getDeobfName(), methodMapping.getObfSignature() ); | ||
| 75 | } | ||
| 76 | } | ||
diff --git a/src/cuchaz/enigma/mapping/MethodEntry.java b/src/cuchaz/enigma/mapping/MethodEntry.java index 8adbfe9..dbc1885 100644 --- a/src/cuchaz/enigma/mapping/MethodEntry.java +++ b/src/cuchaz/enigma/mapping/MethodEntry.java | |||
| @@ -36,6 +36,10 @@ public class MethodEntry implements BehaviorEntry, Serializable | |||
| 36 | { | 36 | { |
| 37 | throw new IllegalArgumentException( "Method signature cannot be null!" ); | 37 | throw new IllegalArgumentException( "Method signature cannot be null!" ); |
| 38 | } | 38 | } |
| 39 | if( name.startsWith( "<" ) ) | ||
| 40 | { | ||
| 41 | throw new IllegalArgumentException( "Don't use MethodEntry for a constructor!" ); | ||
| 42 | } | ||
| 39 | 43 | ||
| 40 | m_classEntry = classEntry; | 44 | m_classEntry = classEntry; |
| 41 | m_name = name; | 45 | m_name = name; |
diff --git a/src/cuchaz/enigma/mapping/MethodMapping.java b/src/cuchaz/enigma/mapping/MethodMapping.java index 6210fd0..b076fa3 100644 --- a/src/cuchaz/enigma/mapping/MethodMapping.java +++ b/src/cuchaz/enigma/mapping/MethodMapping.java | |||
| @@ -70,6 +70,11 @@ public class MethodMapping implements Serializable, Comparable<MethodMapping> | |||
| 70 | return m_arguments.values(); | 70 | return m_arguments.values(); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | public boolean isConstructor( ) | ||
| 74 | { | ||
| 75 | return m_obfName.startsWith( "<" ); | ||
| 76 | } | ||
| 77 | |||
| 73 | public void addArgumentMapping( ArgumentMapping argumentMapping ) | 78 | public void addArgumentMapping( ArgumentMapping argumentMapping ) |
| 74 | { | 79 | { |
| 75 | boolean wasAdded = m_arguments.put( argumentMapping.getIndex(), argumentMapping ) == null; | 80 | boolean wasAdded = m_arguments.put( argumentMapping.getIndex(), argumentMapping ) == null; |