diff options
| author | 2014-09-24 01:00:54 -0400 | |
|---|---|---|
| committer | 2014-09-24 01:00:54 -0400 | |
| commit | 8776a8ba38123c822530e5f659c626c8db616217 (patch) | |
| tree | 8138a4e4447552e598bb99cfd8fb23a5f27f840b /src | |
| parent | trying to figure out why some mappings to correspond to anything in the jar f... (diff) | |
| download | enigma-8776a8ba38123c822530e5f659c626c8db616217.tar.gz enigma-8776a8ba38123c822530e5f659c626c8db616217.tar.xz enigma-8776a8ba38123c822530e5f659c626c8db616217.zip | |
HOW DO I WRITE SO MANY BUGS?!?
Diffstat (limited to 'src')
21 files changed, 335 insertions, 111 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 03c35113..f7f74480 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -39,6 +39,7 @@ import cuchaz.enigma.analysis.EntryReference; | |||
| 39 | import cuchaz.enigma.analysis.JarIndex; | 39 | import cuchaz.enigma.analysis.JarIndex; |
| 40 | import cuchaz.enigma.analysis.SourceIndex; | 40 | 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.mapping.ArgumentEntry; | 43 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 43 | import cuchaz.enigma.mapping.ClassEntry; | 44 | import cuchaz.enigma.mapping.ClassEntry; |
| 44 | import cuchaz.enigma.mapping.ClassMapping; | 45 | import cuchaz.enigma.mapping.ClassMapping; |
| @@ -115,7 +116,7 @@ public class Deobfuscator | |||
| 115 | val = new Mappings(); | 116 | val = new Mappings(); |
| 116 | } | 117 | } |
| 117 | 118 | ||
| 118 | // look for any classes that got moved to inner classes | 119 | // pass 1: look for any classes that got moved to inner classes |
| 119 | Map<String,String> renames = Maps.newHashMap(); | 120 | Map<String,String> renames = Maps.newHashMap(); |
| 120 | for( ClassMapping classMapping : val.classes() ) | 121 | for( ClassMapping classMapping : val.classes() ) |
| 121 | { | 122 | { |
| @@ -136,6 +137,53 @@ public class Deobfuscator | |||
| 136 | val.renameObfClass( entry.getKey(), entry.getValue() ); | 137 | val.renameObfClass( entry.getKey(), entry.getValue() ); |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 140 | // pass 2: look for fields/methods that are actually declared in superclasses | ||
| 141 | MappingsRenamer renamer = new MappingsRenamer( m_jarIndex, val ); | ||
| 142 | for( ClassMapping classMapping : val.classes() ) | ||
| 143 | { | ||
| 144 | ClassEntry obfClassEntry = new ClassEntry( classMapping.getObfName() ); | ||
| 145 | |||
| 146 | // fields | ||
| 147 | for( FieldMapping fieldMapping : Lists.newArrayList( classMapping.fields() ) ) | ||
| 148 | { | ||
| 149 | FieldEntry fieldEntry = new FieldEntry( obfClassEntry, fieldMapping.getObfName() ); | ||
| 150 | ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( fieldEntry ); | ||
| 151 | if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( fieldEntry.getClassEntry() ) ) | ||
| 152 | { | ||
| 153 | boolean wasMoved = renamer.moveFieldToObfClass( classMapping, fieldMapping, resolvedObfClassEntry ); | ||
| 154 | if( wasMoved ) | ||
| 155 | { | ||
| 156 | System.out.println( String.format( "Moved field %s to class %s", fieldEntry, resolvedObfClassEntry ) ); | ||
| 157 | } | ||
| 158 | else | ||
| 159 | { | ||
| 160 | System.err.println( String.format( "WARNING: Would move field %s to class %s but the field was already there. Dropping instead.", fieldEntry, resolvedObfClassEntry ) ); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | // methods | ||
| 166 | for( MethodMapping methodMapping : Lists.newArrayList( classMapping.methods() ) ) | ||
| 167 | { | ||
| 168 | MethodEntry methodEntry = new MethodEntry( obfClassEntry, methodMapping.getObfName(), methodMapping.getObfSignature() ); | ||
| 169 | ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( methodEntry ); | ||
| 170 | if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( methodEntry.getClassEntry() ) ) | ||
| 171 | { | ||
| 172 | boolean wasMoved = renamer.moveMethodToObfClass( classMapping, methodMapping, resolvedObfClassEntry ); | ||
| 173 | if( wasMoved ) | ||
| 174 | { | ||
| 175 | System.out.println( String.format( "Moved method %s to class %s", methodEntry, resolvedObfClassEntry ) ); | ||
| 176 | } | ||
| 177 | else | ||
| 178 | { | ||
| 179 | System.err.println( String.format( "WARNING: Would move method %s to class %s but the method was already there. Dropping instead.", methodEntry, resolvedObfClassEntry ) ); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | // TODO: recurse to inner classes? | ||
| 185 | } | ||
| 186 | |||
| 139 | // drop mappings that don't match the jar | 187 | // drop mappings that don't match the jar |
| 140 | List<ClassEntry> unknownClasses = Lists.newArrayList(); | 188 | List<ClassEntry> unknownClasses = Lists.newArrayList(); |
| 141 | for( ClassMapping classMapping : val.classes() ) | 189 | for( ClassMapping classMapping : val.classes() ) |
| @@ -148,7 +196,7 @@ public class Deobfuscator | |||
| 148 | } | 196 | } |
| 149 | 197 | ||
| 150 | m_mappings = val; | 198 | m_mappings = val; |
| 151 | m_renamer = new MappingsRenamer( m_jarIndex, m_mappings ); | 199 | m_renamer = renamer; |
| 152 | m_translatorCache.clear(); | 200 | m_translatorCache.clear(); |
| 153 | } | 201 | } |
| 154 | 202 | ||
| @@ -170,7 +218,7 @@ public class Deobfuscator | |||
| 170 | for( FieldMapping fieldMapping : Lists.newArrayList( classMapping.fields() ) ) | 218 | for( FieldMapping fieldMapping : Lists.newArrayList( classMapping.fields() ) ) |
| 171 | { | 219 | { |
| 172 | FieldEntry fieldEntry = new FieldEntry( classEntry, fieldMapping.getObfName() ); | 220 | FieldEntry fieldEntry = new FieldEntry( classEntry, fieldMapping.getObfName() ); |
| 173 | if( m_jarIndex.getAccess( fieldEntry ) == null ) | 221 | if( !m_jarIndex.containsObfField( fieldEntry ) ) |
| 174 | { | 222 | { |
| 175 | System.err.println( "WARNING: unable to find field " + fieldEntry + ". dropping mapping." ); | 223 | System.err.println( "WARNING: unable to find field " + fieldEntry + ". dropping mapping." ); |
| 176 | classMapping.removeFieldMapping( fieldMapping ); | 224 | classMapping.removeFieldMapping( fieldMapping ); |
| @@ -188,7 +236,7 @@ public class Deobfuscator | |||
| 188 | else if( methodMapping.getObfName().equals( "<init>" ) ) | 236 | else if( methodMapping.getObfName().equals( "<init>" ) ) |
| 189 | { | 237 | { |
| 190 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, methodMapping.getObfSignature() ); | 238 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, methodMapping.getObfSignature() ); |
| 191 | if( m_jarIndex.getAccess( constructorEntry ) == null ) | 239 | if( !m_jarIndex.containsObfBehavior( constructorEntry ) ) |
| 192 | { | 240 | { |
| 193 | System.err.println( "WARNING: unable to find constructor " + constructorEntry + ". dropping mapping." ); | 241 | System.err.println( "WARNING: unable to find constructor " + constructorEntry + ". dropping mapping." ); |
| 194 | classMapping.removeMethodMapping( methodMapping ); | 242 | classMapping.removeMethodMapping( methodMapping ); |
| @@ -201,7 +249,7 @@ public class Deobfuscator | |||
| 201 | methodMapping.getObfName(), | 249 | methodMapping.getObfName(), |
| 202 | methodMapping.getObfSignature() | 250 | methodMapping.getObfSignature() |
| 203 | ); | 251 | ); |
| 204 | if( m_jarIndex.getAccess( methodEntry ) == null ) | 252 | if( !m_jarIndex.containsObfBehavior( methodEntry ) ) |
| 205 | { | 253 | { |
| 206 | System.err.println( "WARNING: unable to find method " + methodEntry + ". dropping mapping." ); | 254 | System.err.println( "WARNING: unable to find method " + methodEntry + ". dropping mapping." ); |
| 207 | classMapping.removeMethodMapping( methodMapping ); | 255 | classMapping.removeMethodMapping( methodMapping ); |
| @@ -257,19 +305,20 @@ public class Deobfuscator | |||
| 257 | } | 305 | } |
| 258 | } | 306 | } |
| 259 | 307 | ||
| 260 | public CompilationUnit getSourceTree( String className ) | 308 | public CompilationUnit getSourceTree( String obfClassName ) |
| 261 | { | 309 | { |
| 262 | // is this class deobfuscated? | 310 | // is this class deobfuscated? |
| 263 | // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out | 311 | // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out |
| 264 | // the decompiler only sees the deobfuscated class, so we need to load it by the deobfuscated name | 312 | // the decompiler only sees the deobfuscated class, so we need to load it by the deobfuscated name |
| 265 | ClassMapping classMapping = m_mappings.getClassByObf( className ); | 313 | String lookupClassName = obfClassName; |
| 314 | ClassMapping classMapping = m_mappings.getClassByObf( obfClassName ); | ||
| 266 | if( classMapping != null && classMapping.getDeobfName() != null ) | 315 | if( classMapping != null && classMapping.getDeobfName() != null ) |
| 267 | { | 316 | { |
| 268 | className = classMapping.getDeobfName(); | 317 | lookupClassName = classMapping.getDeobfName(); |
| 269 | } | 318 | } |
| 270 | 319 | ||
| 271 | // is this class even in the jar? | 320 | // is this class even in the jar? |
| 272 | if( !m_jarIndex.containsObfClass( new ClassEntry( className ) ) ) | 321 | if( !m_jarIndex.containsObfClass( new ClassEntry( obfClassName ) ) ) |
| 273 | { | 322 | { |
| 274 | return null; | 323 | return null; |
| 275 | } | 324 | } |
| @@ -283,7 +332,7 @@ public class Deobfuscator | |||
| 283 | ) ); | 332 | ) ); |
| 284 | 333 | ||
| 285 | // decompile it! | 334 | // decompile it! |
| 286 | TypeDefinition resolvedType = new MetadataSystem( m_settings.getTypeLoader() ).lookupType( className ).resolve(); | 335 | TypeDefinition resolvedType = new MetadataSystem( m_settings.getTypeLoader() ).lookupType( lookupClassName ).resolve(); |
| 287 | DecompilerContext context = new DecompilerContext(); | 336 | DecompilerContext context = new DecompilerContext(); |
| 288 | context.setCurrentType( resolvedType ); | 337 | context.setCurrentType( resolvedType ); |
| 289 | context.setSettings( m_settings ); | 338 | context.setSettings( m_settings ); |
| @@ -302,13 +351,29 @@ public class Deobfuscator | |||
| 302 | // DEBUG | 351 | // DEBUG |
| 303 | //sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); | 352 | //sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); |
| 304 | 353 | ||
| 305 | /* DEBUG | 354 | // resolve all the classes in the source references |
| 306 | for( Token token : index.referenceTokens() ) | 355 | for( Token token : index.referenceTokens() ) |
| 307 | { | 356 | { |
| 308 | EntryReference<Entry,Entry> reference = index.getDeobfReference( token ); | 357 | EntryReference<Entry,Entry> deobfReference = index.getDeobfReference( token ); |
| 309 | System.out.println( token + " -> " + reference + " -> " + index.getReferenceToken( reference ) ); | 358 | |
| 359 | // get the obfuscated entry | ||
| 360 | Entry obfEntry = obfuscateEntry( deobfReference.entry ); | ||
| 361 | |||
| 362 | // try to resolve the class | ||
| 363 | ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( obfEntry ); | ||
| 364 | if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( obfEntry.getClassEntry() ) ) | ||
| 365 | { | ||
| 366 | // change the class of the entry | ||
| 367 | obfEntry = obfEntry.cloneToNewClass( resolvedObfClassEntry ); | ||
| 368 | |||
| 369 | // save the new deobfuscated reference | ||
| 370 | deobfReference.entry = deobfuscateEntry( obfEntry ); | ||
| 371 | index.replaceDeobfReference( token, deobfReference ); | ||
| 372 | } | ||
| 373 | |||
| 374 | // DEBUG | ||
| 375 | //System.out.println( token + " -> " + reference + " -> " + index.getReferenceToken( reference ) ); | ||
| 310 | } | 376 | } |
| 311 | */ | ||
| 312 | 377 | ||
| 313 | return index; | 378 | return index; |
| 314 | } | 379 | } |
| @@ -486,13 +551,6 @@ public class Deobfuscator | |||
| 486 | 551 | ||
| 487 | public boolean isObfuscatedIdentifier( Entry obfEntry ) | 552 | public boolean isObfuscatedIdentifier( Entry obfEntry ) |
| 488 | { | 553 | { |
| 489 | if( obfEntry instanceof ClassEntry ) | 554 | return m_jarIndex.containsObfEntry( obfEntry ); |
| 490 | { | ||
| 491 | return m_jarIndex.getObfClassEntries().contains( obfEntry ); | ||
| 492 | } | ||
| 493 | else | ||
| 494 | { | ||
| 495 | return isObfuscatedIdentifier( obfEntry.getClassEntry() ); | ||
| 496 | } | ||
| 497 | } | 555 | } |
| 498 | } | 556 | } |
diff --git a/src/cuchaz/enigma/analysis/EntryRenamer.java b/src/cuchaz/enigma/analysis/EntryRenamer.java index b82b2547..44e0220c 100644 --- a/src/cuchaz/enigma/analysis/EntryRenamer.java +++ b/src/cuchaz/enigma/analysis/EntryRenamer.java | |||
| @@ -117,7 +117,7 @@ public class EntryRenamer | |||
| 117 | { | 117 | { |
| 118 | ArgumentEntry argumentEntry = (ArgumentEntry)thing; | 118 | ArgumentEntry argumentEntry = (ArgumentEntry)thing; |
| 119 | return (T)new ArgumentEntry( | 119 | return (T)new ArgumentEntry( |
| 120 | renameMethodsInThing( renames, argumentEntry.getMethodEntry() ), | 120 | renameMethodsInThing( renames, argumentEntry.getBehaviorEntry() ), |
| 121 | argumentEntry.getIndex(), | 121 | argumentEntry.getIndex(), |
| 122 | argumentEntry.getName() | 122 | argumentEntry.getName() |
| 123 | ); | 123 | ); |
| @@ -177,7 +177,7 @@ public class EntryRenamer | |||
| 177 | { | 177 | { |
| 178 | ArgumentEntry argumentEntry = (ArgumentEntry)thing; | 178 | ArgumentEntry argumentEntry = (ArgumentEntry)thing; |
| 179 | return (T)new ArgumentEntry( | 179 | return (T)new ArgumentEntry( |
| 180 | renameClassesInThing( renames, argumentEntry.getMethodEntry() ), | 180 | renameClassesInThing( renames, argumentEntry.getBehaviorEntry() ), |
| 181 | argumentEntry.getIndex(), | 181 | argumentEntry.getIndex(), |
| 182 | argumentEntry.getName() | 182 | argumentEntry.getName() |
| 183 | ); | 183 | ); |
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index b51428a2..9f309cec 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -42,6 +42,7 @@ import com.google.common.collect.Sets; | |||
| 42 | 42 | ||
| 43 | import cuchaz.enigma.Constants; | 43 | 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.BehaviorEntry; | 46 | import cuchaz.enigma.mapping.BehaviorEntry; |
| 46 | import cuchaz.enigma.mapping.ClassEntry; | 47 | import cuchaz.enigma.mapping.ClassEntry; |
| 47 | import cuchaz.enigma.mapping.ConstructorEntry; | 48 | import cuchaz.enigma.mapping.ConstructorEntry; |
| @@ -264,7 +265,15 @@ public class JarIndex | |||
| 264 | call.getMethodName(), | 265 | call.getMethodName(), |
| 265 | call.getSignature() | 266 | call.getSignature() |
| 266 | ); | 267 | ); |
| 267 | calledMethodEntry = resolveMethodClass( calledMethodEntry ); | 268 | ClassEntry resolvedClassEntry = resolveEntryClass( calledMethodEntry ); |
| 269 | if( resolvedClassEntry != null && !resolvedClassEntry.equals( calledMethodEntry.getClassEntry() ) ) | ||
| 270 | { | ||
| 271 | calledMethodEntry = new MethodEntry( | ||
| 272 | resolvedClassEntry, | ||
| 273 | call.getMethodName(), | ||
| 274 | call.getSignature() | ||
| 275 | ); | ||
| 276 | } | ||
| 268 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( | 277 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( |
| 269 | calledMethodEntry, | 278 | calledMethodEntry, |
| 270 | behaviorEntry | 279 | behaviorEntry |
| @@ -280,6 +289,14 @@ public class JarIndex | |||
| 280 | new ClassEntry( className ), | 289 | new ClassEntry( className ), |
| 281 | call.getFieldName() | 290 | call.getFieldName() |
| 282 | ); | 291 | ); |
| 292 | ClassEntry resolvedClassEntry = resolveEntryClass( calledFieldEntry ); | ||
| 293 | if( resolvedClassEntry != null && !resolvedClassEntry.equals( calledFieldEntry.getClassEntry() ) ) | ||
| 294 | { | ||
| 295 | calledFieldEntry = new FieldEntry( | ||
| 296 | resolvedClassEntry, | ||
| 297 | call.getFieldName() | ||
| 298 | ); | ||
| 299 | } | ||
| 283 | EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>( | 300 | EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>( |
| 284 | calledFieldEntry, | 301 | calledFieldEntry, |
| 285 | behaviorEntry | 302 | behaviorEntry |
| @@ -355,30 +372,26 @@ public class JarIndex | |||
| 355 | throw new IllegalArgumentException( "behavior must be a method or a constructor!" ); | 372 | throw new IllegalArgumentException( "behavior must be a method or a constructor!" ); |
| 356 | } | 373 | } |
| 357 | } | 374 | } |
| 358 | 375 | ||
| 359 | private MethodEntry resolveMethodClass( MethodEntry methodEntry ) | 376 | public ClassEntry resolveEntryClass( Entry obfEntry ) |
| 360 | { | 377 | { |
| 361 | // this entry could refer to a method on a class where the method is not actually implemented | 378 | // this entry could refer to a method on a class where the method is not actually implemented |
| 362 | // travel up the inheritance tree to find the closest implementation | 379 | // travel up the inheritance tree to find the closest implementation |
| 363 | while( !isMethodImplemented( methodEntry ) ) | 380 | while( !containsObfEntry( obfEntry ) ) |
| 364 | { | 381 | { |
| 365 | // is there a parent class? | 382 | // is there a parent class? |
| 366 | String superclassName = m_translationIndex.getSuperclassName( methodEntry.getClassName() ); | 383 | String superclassName = m_translationIndex.getSuperclassName( obfEntry.getClassName() ); |
| 367 | if( superclassName == null ) | 384 | if( superclassName == null ) |
| 368 | { | 385 | { |
| 369 | // this is probably a method from a class in a library | 386 | // this is probably a method from a class in a library |
| 370 | // we can't trace the implementation up any higher unless we index the library | 387 | // we can't trace the implementation up any higher unless we index the library |
| 371 | return methodEntry; | 388 | return null; |
| 372 | } | 389 | } |
| 373 | 390 | ||
| 374 | // move up to the parent class | 391 | // move up to the parent class |
| 375 | methodEntry = new MethodEntry( | 392 | obfEntry = obfEntry.cloneToNewClass( new ClassEntry( superclassName ) ); |
| 376 | new ClassEntry( superclassName ), | ||
| 377 | methodEntry.getName(), | ||
| 378 | methodEntry.getSignature() | ||
| 379 | ); | ||
| 380 | } | 393 | } |
| 381 | return methodEntry; | 394 | return obfEntry.getClassEntry(); |
| 382 | } | 395 | } |
| 383 | 396 | ||
| 384 | private CtMethod getBridgedMethod( CtMethod method ) | 397 | private CtMethod getBridgedMethod( CtMethod method ) |
| @@ -704,16 +717,6 @@ public class JarIndex | |||
| 704 | return m_fieldClasses.get( fieldEntry ); | 717 | return m_fieldClasses.get( fieldEntry ); |
| 705 | } | 718 | } |
| 706 | 719 | ||
| 707 | public boolean isMethodImplemented( MethodEntry methodEntry ) | ||
| 708 | { | ||
| 709 | Collection<MethodEntry> implementations = m_methodImplementations.get( methodEntry.getClassName() ); | ||
| 710 | if( implementations == null ) | ||
| 711 | { | ||
| 712 | return false; | ||
| 713 | } | ||
| 714 | return implementations.contains( methodEntry ); | ||
| 715 | } | ||
| 716 | |||
| 717 | public ClassInheritanceTreeNode getClassInheritance( Translator deobfuscatingTranslator, ClassEntry obfClassEntry ) | 720 | public ClassInheritanceTreeNode getClassInheritance( Translator deobfuscatingTranslator, ClassEntry obfClassEntry ) |
| 718 | { | 721 | { |
| 719 | // get the root node | 722 | // get the root node |
| @@ -751,7 +754,7 @@ public class JarIndex | |||
| 751 | obfMethodEntry.getName(), | 754 | obfMethodEntry.getName(), |
| 752 | obfMethodEntry.getSignature() | 755 | obfMethodEntry.getSignature() |
| 753 | ); | 756 | ); |
| 754 | if( isMethodImplemented( ancestorMethodEntry ) ) | 757 | if( containsObfBehavior( ancestorMethodEntry ) ) |
| 755 | { | 758 | { |
| 756 | baseImplementationClassName = ancestorClassName; | 759 | baseImplementationClassName = ancestorClassName; |
| 757 | } | 760 | } |
| @@ -766,7 +769,7 @@ public class JarIndex | |||
| 766 | MethodInheritanceTreeNode rootNode = new MethodInheritanceTreeNode( | 769 | MethodInheritanceTreeNode rootNode = new MethodInheritanceTreeNode( |
| 767 | deobfuscatingTranslator, | 770 | deobfuscatingTranslator, |
| 768 | methodEntry, | 771 | methodEntry, |
| 769 | isMethodImplemented( methodEntry ) | 772 | containsObfBehavior( methodEntry ) |
| 770 | ); | 773 | ); |
| 771 | 774 | ||
| 772 | // expand the full tree | 775 | // expand the full tree |
| @@ -796,7 +799,7 @@ public class JarIndex | |||
| 796 | obfMethodEntry.getName(), | 799 | obfMethodEntry.getName(), |
| 797 | obfMethodEntry.getSignature() | 800 | obfMethodEntry.getSignature() |
| 798 | ); | 801 | ); |
| 799 | if( isMethodImplemented( methodInterface ) ) | 802 | if( containsObfBehavior( methodInterface ) ) |
| 800 | { | 803 | { |
| 801 | methodInterfaces.add( methodInterface ); | 804 | methodInterfaces.add( methodInterface ); |
| 802 | } | 805 | } |
| @@ -827,7 +830,7 @@ public class JarIndex | |||
| 827 | private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodInheritanceTreeNode node ) | 830 | private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodInheritanceTreeNode node ) |
| 828 | { | 831 | { |
| 829 | MethodEntry methodEntry = node.getMethodEntry(); | 832 | MethodEntry methodEntry = node.getMethodEntry(); |
| 830 | if( isMethodImplemented( methodEntry ) ) | 833 | if( containsObfBehavior( methodEntry ) ) |
| 831 | { | 834 | { |
| 832 | // collect the entry | 835 | // collect the entry |
| 833 | methodEntries.add( methodEntry ); | 836 | methodEntries.add( methodEntry ); |
| @@ -850,7 +853,7 @@ public class JarIndex | |||
| 850 | private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodImplementationsTreeNode node ) | 853 | private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodImplementationsTreeNode node ) |
| 851 | { | 854 | { |
| 852 | MethodEntry methodEntry = node.getMethodEntry(); | 855 | MethodEntry methodEntry = node.getMethodEntry(); |
| 853 | if( isMethodImplemented( methodEntry ) ) | 856 | if( containsObfBehavior( methodEntry ) ) |
| 854 | { | 857 | { |
| 855 | // collect the entry | 858 | // collect the entry |
| 856 | methodEntries.add( methodEntry ); | 859 | methodEntries.add( methodEntry ); |
| @@ -969,8 +972,49 @@ public class JarIndex | |||
| 969 | return m_access.containsKey( obfFieldEntry ); | 972 | return m_access.containsKey( obfFieldEntry ); |
| 970 | } | 973 | } |
| 971 | 974 | ||
| 972 | public boolean containsObfMethod( MethodEntry obfMethodEntry ) | 975 | public boolean containsObfBehavior( BehaviorEntry obfBehaviorEntry ) |
| 976 | { | ||
| 977 | return m_access.containsKey( obfBehaviorEntry ); | ||
| 978 | } | ||
| 979 | |||
| 980 | public boolean containsObfArgument( ArgumentEntry obfArgumentEntry ) | ||
| 981 | { | ||
| 982 | // check the behavior | ||
| 983 | if( !containsObfBehavior( obfArgumentEntry.getBehaviorEntry() ) ) | ||
| 984 | { | ||
| 985 | return false; | ||
| 986 | } | ||
| 987 | |||
| 988 | // check the argument | ||
| 989 | if( obfArgumentEntry.getIndex() >= Descriptor.numOfParameters( obfArgumentEntry.getBehaviorEntry().getSignature() ) ) | ||
| 990 | { | ||
| 991 | return false; | ||
| 992 | } | ||
| 993 | |||
| 994 | return true; | ||
| 995 | } | ||
| 996 | |||
| 997 | public boolean containsObfEntry( Entry obfEntry ) | ||
| 973 | { | 998 | { |
| 974 | return m_access.containsKey( obfMethodEntry ); | 999 | if( obfEntry instanceof ClassEntry ) |
| 1000 | { | ||
| 1001 | return containsObfClass( (ClassEntry)obfEntry ); | ||
| 1002 | } | ||
| 1003 | else if( obfEntry instanceof FieldEntry ) | ||
| 1004 | { | ||
| 1005 | return containsObfField( (FieldEntry)obfEntry ); | ||
| 1006 | } | ||
| 1007 | else if( obfEntry instanceof BehaviorEntry ) | ||
| 1008 | { | ||
| 1009 | return containsObfBehavior( (BehaviorEntry)obfEntry ); | ||
| 1010 | } | ||
| 1011 | else if( obfEntry instanceof ArgumentEntry ) | ||
| 1012 | { | ||
| 1013 | return containsObfArgument( (ArgumentEntry)obfEntry ); | ||
| 1014 | } | ||
| 1015 | else | ||
| 1016 | { | ||
| 1017 | throw new Error( "Entry type not supported: " + obfEntry.getClass().getName() ); | ||
| 1018 | } | ||
| 975 | } | 1019 | } |
| 976 | } | 1020 | } |
diff --git a/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java b/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java index 8b9dd2d8..a050282b 100644 --- a/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java +++ b/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java | |||
| @@ -81,7 +81,7 @@ public class MethodImplementationsTreeNode extends DefaultMutableTreeNode | |||
| 81 | m_entry.getName(), | 81 | m_entry.getName(), |
| 82 | m_entry.getSignature() | 82 | m_entry.getSignature() |
| 83 | ); | 83 | ); |
| 84 | if( index.isMethodImplemented( methodEntry ) ) | 84 | if( index.containsObfBehavior( methodEntry ) ) |
| 85 | { | 85 | { |
| 86 | nodes.add( new MethodImplementationsTreeNode( m_deobfuscatingTranslator, methodEntry ) ); | 86 | nodes.add( new MethodImplementationsTreeNode( m_deobfuscatingTranslator, methodEntry ) ); |
| 87 | } | 87 | } |
diff --git a/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java b/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java index d77fd858..bd919518 100644 --- a/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java +++ b/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java | |||
| @@ -93,7 +93,7 @@ public class MethodInheritanceTreeNode extends DefaultMutableTreeNode | |||
| 93 | nodes.add( new MethodInheritanceTreeNode( | 93 | nodes.add( new MethodInheritanceTreeNode( |
| 94 | m_deobfuscatingTranslator, | 94 | m_deobfuscatingTranslator, |
| 95 | methodEntry, | 95 | methodEntry, |
| 96 | index.isMethodImplemented( methodEntry ) | 96 | index.containsObfBehavior( methodEntry ) |
| 97 | ) ); | 97 | ) ); |
| 98 | } | 98 | } |
| 99 | 99 | ||
diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java index 49451b90..a5d1460f 100644 --- a/src/cuchaz/enigma/analysis/SourceIndex.java +++ b/src/cuchaz/enigma/analysis/SourceIndex.java | |||
| @@ -126,6 +126,15 @@ public class SourceIndex | |||
| 126 | return m_tokenToReference.get( token ); | 126 | return m_tokenToReference.get( token ); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | public void replaceDeobfReference( Token token, EntryReference<Entry,Entry> newDeobfReference ) | ||
| 130 | { | ||
| 131 | EntryReference<Entry,Entry> oldDeobfReference = m_tokenToReference.get( token ); | ||
| 132 | m_tokenToReference.put( token, newDeobfReference ); | ||
| 133 | Collection<Token> tokens = m_referenceToTokens.get( oldDeobfReference ); | ||
| 134 | m_referenceToTokens.removeAll( oldDeobfReference ); | ||
| 135 | m_referenceToTokens.putAll( newDeobfReference, tokens ); | ||
| 136 | } | ||
| 137 | |||
| 129 | public Iterable<Token> referenceTokens( ) | 138 | public Iterable<Token> referenceTokens( ) |
| 130 | { | 139 | { |
| 131 | return m_tokenToReference.keySet(); | 140 | return m_tokenToReference.keySet(); |
diff --git a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java index 6238b1e7..f307c11d 100644 --- a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java +++ b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java | |||
| @@ -116,6 +116,12 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor | |||
| 116 | MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE ); | 116 | MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE ); |
| 117 | if( ref != null ) | 117 | if( ref != null ) |
| 118 | { | 118 | { |
| 119 | // make sure this is actually a field | ||
| 120 | if( ref.getSignature().indexOf( '(' ) >= 0 ) | ||
| 121 | { | ||
| 122 | throw new Error( "Expected a field here! got " + ref ); | ||
| 123 | } | ||
| 124 | |||
| 119 | ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); | 125 | ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); |
| 120 | FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); | 126 | FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); |
| 121 | index.addReference( | 127 | index.addReference( |
| @@ -149,8 +155,16 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor | |||
| 149 | ParameterDefinition def = node.getUserData( Keys.PARAMETER_DEFINITION ); | 155 | ParameterDefinition def = node.getUserData( Keys.PARAMETER_DEFINITION ); |
| 150 | ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); | 156 | ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); |
| 151 | MethodDefinition methodDef = (MethodDefinition)def.getMethod(); | 157 | MethodDefinition methodDef = (MethodDefinition)def.getMethod(); |
| 152 | MethodEntry methodEntry = new MethodEntry( classEntry, methodDef.getName(), methodDef.getSignature() ); | 158 | BehaviorEntry behaviorEntry; |
| 153 | ArgumentEntry argumentEntry = new ArgumentEntry( methodEntry, def.getPosition(), def.getName() ); | 159 | if( methodDef.isConstructor() ) |
| 160 | { | ||
| 161 | behaviorEntry = new ConstructorEntry( classEntry, methodDef.getSignature() ); | ||
| 162 | } | ||
| 163 | else | ||
| 164 | { | ||
| 165 | behaviorEntry = new MethodEntry( classEntry, methodDef.getName(), methodDef.getSignature() ); | ||
| 166 | } | ||
| 167 | ArgumentEntry argumentEntry = new ArgumentEntry( behaviorEntry, def.getPosition(), def.getName() ); | ||
| 154 | index.addDeclaration( node.getNameToken(), argumentEntry ); | 168 | index.addDeclaration( node.getNameToken(), argumentEntry ); |
| 155 | 169 | ||
| 156 | return recurse( node, index ); | 170 | return recurse( node, index ); |
diff --git a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java index a8d3983f..adea7eae 100644 --- a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java +++ b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java | |||
| @@ -15,9 +15,13 @@ import java.util.List; | |||
| 15 | 15 | ||
| 16 | import javassist.CtBehavior; | 16 | import javassist.CtBehavior; |
| 17 | import javassist.CtClass; | 17 | import javassist.CtClass; |
| 18 | import javassist.CtConstructor; | ||
| 19 | import javassist.CtMethod; | ||
| 18 | import javassist.bytecode.Descriptor; | 20 | import javassist.bytecode.Descriptor; |
| 19 | import cuchaz.enigma.mapping.ArgumentEntry; | 21 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 22 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 20 | import cuchaz.enigma.mapping.ClassEntry; | 23 | import cuchaz.enigma.mapping.ClassEntry; |
| 24 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 21 | import cuchaz.enigma.mapping.MethodEntry; | 25 | import cuchaz.enigma.mapping.MethodEntry; |
| 22 | import cuchaz.enigma.mapping.Translator; | 26 | import cuchaz.enigma.mapping.Translator; |
| 23 | 27 | ||
| @@ -42,12 +46,26 @@ public class MethodParameterWriter | |||
| 42 | continue; | 46 | continue; |
| 43 | } | 47 | } |
| 44 | 48 | ||
| 49 | // get the behavior entry | ||
| 50 | BehaviorEntry behaviorEntry; | ||
| 51 | if( behavior instanceof CtMethod ) | ||
| 52 | { | ||
| 53 | behaviorEntry = new MethodEntry( classEntry, behavior.getMethodInfo().getName(), behavior.getSignature() ); | ||
| 54 | } | ||
| 55 | else if( behavior instanceof CtConstructor ) | ||
| 56 | { | ||
| 57 | behaviorEntry = new ConstructorEntry( classEntry, behavior.getSignature() ); | ||
| 58 | } | ||
| 59 | else | ||
| 60 | { | ||
| 61 | throw new Error( "Unsupported behavior type: " + behavior.getClass().getName() ); | ||
| 62 | } | ||
| 63 | |||
| 45 | // get the list of parameter names | 64 | // get the list of parameter names |
| 46 | MethodEntry methodEntry = new MethodEntry( classEntry, behavior.getMethodInfo().getName(), behavior.getSignature() ); | ||
| 47 | List<String> names = new ArrayList<String>( numParams ); | 65 | List<String> names = new ArrayList<String>( numParams ); |
| 48 | for( int i=0; i<numParams; i++ ) | 66 | for( int i=0; i<numParams; i++ ) |
| 49 | { | 67 | { |
| 50 | names.add( m_translator.translate( new ArgumentEntry( methodEntry, i, "" ) ) ); | 68 | names.add( m_translator.translate( new ArgumentEntry( behaviorEntry, i, "" ) ) ); |
| 51 | } | 69 | } |
| 52 | 70 | ||
| 53 | // save the mappings to the class | 71 | // save the mappings to the class |
diff --git a/src/cuchaz/enigma/convert/ClassMatcher.java b/src/cuchaz/enigma/convert/ClassMatcher.java index eb7a31df..290d90a7 100644 --- a/src/cuchaz/enigma/convert/ClassMatcher.java +++ b/src/cuchaz/enigma/convert/ClassMatcher.java | |||
| @@ -57,8 +57,8 @@ public class ClassMatcher | |||
| 57 | // TEMP | 57 | // TEMP |
| 58 | JarFile sourceJar = new JarFile( new File( "input/1.8-pre3.jar" ) ); | 58 | JarFile sourceJar = new JarFile( new File( "input/1.8-pre3.jar" ) ); |
| 59 | JarFile destJar = new JarFile( new File( "input/1.8.jar" ) ); | 59 | JarFile destJar = new JarFile( new File( "input/1.8.jar" ) ); |
| 60 | File inMappingsFile = new File( "../minecraft-mappings/1.8-pre3.mappings" ); | 60 | File inMappingsFile = new File( "../Enigma Mappings/1.8-pre3.mappings" ); |
| 61 | File outMappingsFile = new File( "../minecraft-mappings/1.8.mappings" ); | 61 | File outMappingsFile = new File( "../Enigma Mappings/1.8.mappings" ); |
| 62 | 62 | ||
| 63 | // define a matching to use when the automated system cannot find a match | 63 | // define a matching to use when the automated system cannot find a match |
| 64 | Map<String,String> fallbackMatching = Maps.newHashMap(); | 64 | Map<String,String> fallbackMatching = Maps.newHashMap(); |
| @@ -271,7 +271,7 @@ public class ClassMatcher | |||
| 271 | methodMapping.getObfName(), | 271 | methodMapping.getObfName(), |
| 272 | methodMapping.getObfSignature() | 272 | methodMapping.getObfSignature() |
| 273 | ); | 273 | ); |
| 274 | if( !destIndex.isMethodImplemented( methodEntry ) ) | 274 | if( !destIndex.containsObfBehavior( methodEntry ) ) |
| 275 | { | 275 | { |
| 276 | System.err.println( "WARNING: method doesn't match: " + methodEntry ); | 276 | System.err.println( "WARNING: method doesn't match: " + methodEntry ); |
| 277 | 277 | ||
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index 5eed728a..1f04aa35 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -229,27 +229,27 @@ public class Gui | |||
| 229 | switch( event.getKeyCode() ) | 229 | switch( event.getKeyCode() ) |
| 230 | { | 230 | { |
| 231 | case KeyEvent.VK_R: | 231 | case KeyEvent.VK_R: |
| 232 | startRename(); | 232 | m_renameMenu.doClick(); |
| 233 | break; | 233 | break; |
| 234 | 234 | ||
| 235 | case KeyEvent.VK_I: | 235 | case KeyEvent.VK_I: |
| 236 | showInheritance(); | 236 | m_showInheritanceMenu.doClick(); |
| 237 | break; | 237 | break; |
| 238 | 238 | ||
| 239 | case KeyEvent.VK_M: | 239 | case KeyEvent.VK_M: |
| 240 | showImplementations(); | 240 | m_showImplementationsMenu.doClick(); |
| 241 | break; | 241 | break; |
| 242 | 242 | ||
| 243 | case KeyEvent.VK_N: | 243 | case KeyEvent.VK_N: |
| 244 | navigateTo( m_reference.entry ); | 244 | m_openEntryMenu.doClick(); |
| 245 | break; | 245 | break; |
| 246 | 246 | ||
| 247 | case KeyEvent.VK_P: | 247 | case KeyEvent.VK_P: |
| 248 | m_controller.openPreviousReference(); | 248 | m_openPreviousMenu.doClick(); |
| 249 | break; | 249 | break; |
| 250 | 250 | ||
| 251 | case KeyEvent.VK_C: | 251 | case KeyEvent.VK_C: |
| 252 | showCalls(); | 252 | m_showCallsMenu.doClick(); |
| 253 | break; | 253 | break; |
| 254 | } | 254 | } |
| 255 | } | 255 | } |
| @@ -987,7 +987,7 @@ public class Gui | |||
| 987 | { | 987 | { |
| 988 | addNameValue( m_infoPanel, "Argument", entry.getName() ); | 988 | addNameValue( m_infoPanel, "Argument", entry.getName() ); |
| 989 | addNameValue( m_infoPanel, "Class", entry.getClassEntry().getName() ); | 989 | addNameValue( m_infoPanel, "Class", entry.getClassEntry().getName() ); |
| 990 | addNameValue( m_infoPanel, "Method", entry.getMethodEntry().getName() ); | 990 | addNameValue( m_infoPanel, "Method", entry.getBehaviorEntry().getName() ); |
| 991 | addNameValue( m_infoPanel, "Index", Integer.toString( entry.getIndex() ) ); | 991 | addNameValue( m_infoPanel, "Index", Integer.toString( entry.getIndex() ) ); |
| 992 | } | 992 | } |
| 993 | 993 | ||
| @@ -1014,7 +1014,7 @@ public class Gui | |||
| 1014 | boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; | 1014 | boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; |
| 1015 | boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; | 1015 | boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; |
| 1016 | boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; | 1016 | boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; |
| 1017 | boolean isInJar = isToken && m_controller.entryIsInJar( m_reference.entry.getClassEntry() ); | 1017 | boolean isInJar = isToken && m_controller.entryIsInJar( m_reference.entry ); |
| 1018 | 1018 | ||
| 1019 | if( isToken ) | 1019 | if( isToken ) |
| 1020 | { | 1020 | { |
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index bbefe606..098e065d 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -270,7 +270,7 @@ public class GuiController | |||
| 270 | ClassEntry obfClassEntry = obfReference.getClassEntry().getOuterClassEntry(); | 270 | ClassEntry obfClassEntry = obfReference.getClassEntry().getOuterClassEntry(); |
| 271 | if( !m_deobfuscator.isObfuscatedIdentifier( obfClassEntry ) ) | 271 | if( !m_deobfuscator.isObfuscatedIdentifier( obfClassEntry ) ) |
| 272 | { | 272 | { |
| 273 | throw new IllegalArgumentException( "Entry must be in the jar!" ); | 273 | throw new IllegalArgumentException( "Obfuscated class " + obfClassEntry + " was not found in the jar!" ); |
| 274 | } | 274 | } |
| 275 | if( m_currentObfClass == null || !m_currentObfClass.equals( obfClassEntry ) ) | 275 | if( m_currentObfClass == null || !m_currentObfClass.equals( obfClassEntry ) ) |
| 276 | { | 276 | { |
| @@ -354,6 +354,7 @@ public class GuiController | |||
| 354 | if( sourceTree == null ) | 354 | if( sourceTree == null ) |
| 355 | { | 355 | { |
| 356 | // decompilation of this class is not supported | 356 | // decompilation of this class is not supported |
| 357 | m_gui.setSource("Unable to find class: " + classEntry); | ||
| 357 | return; | 358 | return; |
| 358 | } | 359 | } |
| 359 | String source = m_deobfuscator.getSource( sourceTree ); | 360 | String source = m_deobfuscator.getSource( sourceTree ); |
diff --git a/src/cuchaz/enigma/mapping/ArgumentEntry.java b/src/cuchaz/enigma/mapping/ArgumentEntry.java index 27dcc41d..7ed3d328 100644 --- a/src/cuchaz/enigma/mapping/ArgumentEntry.java +++ b/src/cuchaz/enigma/mapping/ArgumentEntry.java | |||
| @@ -18,15 +18,15 @@ public class ArgumentEntry implements Entry, Serializable | |||
| 18 | { | 18 | { |
| 19 | private static final long serialVersionUID = 4472172468162696006L; | 19 | private static final long serialVersionUID = 4472172468162696006L; |
| 20 | 20 | ||
| 21 | private MethodEntry m_methodEntry; | 21 | private BehaviorEntry m_behaviorEntry; |
| 22 | private int m_index; | 22 | private int m_index; |
| 23 | private String m_name; | 23 | private String m_name; |
| 24 | 24 | ||
| 25 | public ArgumentEntry( MethodEntry methodEntry, int index, String name ) | 25 | public ArgumentEntry( BehaviorEntry behaviorEntry, int index, String name ) |
| 26 | { | 26 | { |
| 27 | if( methodEntry == null ) | 27 | if( behaviorEntry == null ) |
| 28 | { | 28 | { |
| 29 | throw new IllegalArgumentException( "Method cannot be null!" ); | 29 | throw new IllegalArgumentException( "Behavior cannot be null!" ); |
| 30 | } | 30 | } |
| 31 | if( index < 0 ) | 31 | if( index < 0 ) |
| 32 | { | 32 | { |
| @@ -37,21 +37,28 @@ public class ArgumentEntry implements Entry, Serializable | |||
| 37 | throw new IllegalArgumentException( "Argument name cannot be null!" ); | 37 | throw new IllegalArgumentException( "Argument name cannot be null!" ); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | m_methodEntry = methodEntry; | 40 | m_behaviorEntry = behaviorEntry; |
| 41 | m_index = index; | 41 | m_index = index; |
| 42 | m_name = name; | 42 | m_name = name; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | public ArgumentEntry( ArgumentEntry other ) | 45 | public ArgumentEntry( ArgumentEntry other ) |
| 46 | { | 46 | { |
| 47 | m_methodEntry = new MethodEntry( other.m_methodEntry ); | 47 | m_behaviorEntry = (BehaviorEntry)m_behaviorEntry.cloneToNewClass( getClassEntry() ); |
| 48 | m_index = other.m_index; | 48 | m_index = other.m_index; |
| 49 | m_name = other.m_name; | 49 | m_name = other.m_name; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | public MethodEntry getMethodEntry( ) | 52 | public ArgumentEntry( ArgumentEntry other, String newClassName ) |
| 53 | { | 53 | { |
| 54 | return m_methodEntry; | 54 | m_behaviorEntry = (BehaviorEntry)other.m_behaviorEntry.cloneToNewClass( new ClassEntry( newClassName ) ); |
| 55 | m_index = other.m_index; | ||
| 56 | m_name = other.m_name; | ||
| 57 | } | ||
| 58 | |||
| 59 | public BehaviorEntry getBehaviorEntry( ) | ||
| 60 | { | ||
| 61 | return m_behaviorEntry; | ||
| 55 | } | 62 | } |
| 56 | 63 | ||
| 57 | public int getIndex( ) | 64 | public int getIndex( ) |
| @@ -68,29 +75,35 @@ public class ArgumentEntry implements Entry, Serializable | |||
| 68 | @Override | 75 | @Override |
| 69 | public ClassEntry getClassEntry( ) | 76 | public ClassEntry getClassEntry( ) |
| 70 | { | 77 | { |
| 71 | return m_methodEntry.getClassEntry(); | 78 | return m_behaviorEntry.getClassEntry(); |
| 72 | } | 79 | } |
| 73 | 80 | ||
| 74 | @Override | 81 | @Override |
| 75 | public String getClassName( ) | 82 | public String getClassName( ) |
| 76 | { | 83 | { |
| 77 | return m_methodEntry.getClassName(); | 84 | return m_behaviorEntry.getClassName(); |
| 85 | } | ||
| 86 | |||
| 87 | @Override | ||
| 88 | public ArgumentEntry cloneToNewClass( ClassEntry classEntry ) | ||
| 89 | { | ||
| 90 | return new ArgumentEntry( this, classEntry.getName() ); | ||
| 78 | } | 91 | } |
| 79 | 92 | ||
| 80 | public String getMethodName( ) | 93 | public String getMethodName( ) |
| 81 | { | 94 | { |
| 82 | return m_methodEntry.getName(); | 95 | return m_behaviorEntry.getName(); |
| 83 | } | 96 | } |
| 84 | 97 | ||
| 85 | public String getMethodSignature( ) | 98 | public String getMethodSignature( ) |
| 86 | { | 99 | { |
| 87 | return m_methodEntry.getSignature(); | 100 | return m_behaviorEntry.getSignature(); |
| 88 | } | 101 | } |
| 89 | 102 | ||
| 90 | @Override | 103 | @Override |
| 91 | public int hashCode( ) | 104 | public int hashCode( ) |
| 92 | { | 105 | { |
| 93 | return Util.combineHashesOrdered( m_methodEntry, Integer.valueOf( m_index ).hashCode(), m_name.hashCode() ); | 106 | return Util.combineHashesOrdered( m_behaviorEntry, Integer.valueOf( m_index ).hashCode(), m_name.hashCode() ); |
| 94 | } | 107 | } |
| 95 | 108 | ||
| 96 | @Override | 109 | @Override |
| @@ -105,7 +118,7 @@ public class ArgumentEntry implements Entry, Serializable | |||
| 105 | 118 | ||
| 106 | public boolean equals( ArgumentEntry other ) | 119 | public boolean equals( ArgumentEntry other ) |
| 107 | { | 120 | { |
| 108 | return m_methodEntry.equals( other.m_methodEntry ) | 121 | return m_behaviorEntry.equals( other.m_behaviorEntry ) |
| 109 | && m_index == other.m_index | 122 | && m_index == other.m_index |
| 110 | && m_name.equals( other.m_name ); | 123 | && m_name.equals( other.m_name ); |
| 111 | } | 124 | } |
| @@ -113,6 +126,6 @@ public class ArgumentEntry implements Entry, Serializable | |||
| 113 | @Override | 126 | @Override |
| 114 | public String toString( ) | 127 | public String toString( ) |
| 115 | { | 128 | { |
| 116 | return m_methodEntry.toString() + "(" + m_index + ":" + m_name + ")"; | 129 | return m_behaviorEntry.toString() + "(" + m_index + ":" + m_name + ")"; |
| 117 | } | 130 | } |
| 118 | } | 131 | } |
diff --git a/src/cuchaz/enigma/mapping/ClassEntry.java b/src/cuchaz/enigma/mapping/ClassEntry.java index c6faa506..2c708f2a 100644 --- a/src/cuchaz/enigma/mapping/ClassEntry.java +++ b/src/cuchaz/enigma/mapping/ClassEntry.java | |||
| @@ -44,12 +44,6 @@ public class ClassEntry implements Entry, Serializable | |||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | @Override | 46 | @Override |
| 47 | public ClassEntry getClassEntry( ) | ||
| 48 | { | ||
| 49 | return this; | ||
| 50 | } | ||
| 51 | |||
| 52 | @Override | ||
| 53 | public String getName( ) | 47 | public String getName( ) |
| 54 | { | 48 | { |
| 55 | return m_name; | 49 | return m_name; |
| @@ -62,6 +56,18 @@ public class ClassEntry implements Entry, Serializable | |||
| 62 | } | 56 | } |
| 63 | 57 | ||
| 64 | @Override | 58 | @Override |
| 59 | public ClassEntry getClassEntry( ) | ||
| 60 | { | ||
| 61 | return this; | ||
| 62 | } | ||
| 63 | |||
| 64 | @Override | ||
| 65 | public ClassEntry cloneToNewClass( ClassEntry classEntry ) | ||
| 66 | { | ||
| 67 | return classEntry; | ||
| 68 | } | ||
| 69 | |||
| 70 | @Override | ||
| 65 | public int hashCode( ) | 71 | public int hashCode( ) |
| 66 | { | 72 | { |
| 67 | return m_name.hashCode(); | 73 | return m_name.hashCode(); |
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java index 88006cff..b551d71c 100644 --- a/src/cuchaz/enigma/mapping/ClassMapping.java +++ b/src/cuchaz/enigma/mapping/ClassMapping.java | |||
| @@ -139,6 +139,16 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> | |||
| 139 | return m_fieldsByObf.values(); | 139 | return m_fieldsByObf.values(); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | public boolean containsObfField( String obfName ) | ||
| 143 | { | ||
| 144 | return m_fieldsByObf.containsKey( obfName ); | ||
| 145 | } | ||
| 146 | |||
| 147 | public boolean containsDeobfField( String deobfName ) | ||
| 148 | { | ||
| 149 | return m_fieldsByDeobf.containsKey( deobfName ); | ||
| 150 | } | ||
| 151 | |||
| 142 | public void addFieldMapping( FieldMapping fieldMapping ) | 152 | public void addFieldMapping( FieldMapping fieldMapping ) |
| 143 | { | 153 | { |
| 144 | if( m_fieldsByObf.containsKey( fieldMapping.getObfName() ) ) | 154 | if( m_fieldsByObf.containsKey( fieldMapping.getObfName() ) ) |
| @@ -214,6 +224,16 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> | |||
| 214 | return m_methodsByObf.values(); | 224 | return m_methodsByObf.values(); |
| 215 | } | 225 | } |
| 216 | 226 | ||
| 227 | public boolean containsObfMethod( String obfName, String obfSignature ) | ||
| 228 | { | ||
| 229 | return m_methodsByObf.containsKey( getMethodKey( obfName, obfSignature ) ); | ||
| 230 | } | ||
| 231 | |||
| 232 | public boolean containsDeobfMethod( String deobfName, String deobfSignature ) | ||
| 233 | { | ||
| 234 | return m_methodsByDeobf.containsKey( getMethodKey( deobfName, deobfSignature ) ); | ||
| 235 | } | ||
| 236 | |||
| 217 | public void addMethodMapping( MethodMapping methodMapping ) | 237 | public void addMethodMapping( MethodMapping methodMapping ) |
| 218 | { | 238 | { |
| 219 | String obfKey = getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ); | 239 | String obfKey = getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ); |
| @@ -375,19 +395,9 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> | |||
| 375 | return false; | 395 | return false; |
| 376 | } | 396 | } |
| 377 | 397 | ||
| 378 | public boolean containsDeobfField( String name ) | 398 | public boolean containsArgument( BehaviorEntry obfBehaviorEntry, String name ) |
| 379 | { | ||
| 380 | return m_fieldsByDeobf.containsKey( name ); | ||
| 381 | } | ||
| 382 | |||
| 383 | public boolean containsDeobfMethod( String name, String signature ) | ||
| 384 | { | ||
| 385 | return m_methodsByDeobf.containsKey( getMethodKey( name, signature ) ); | ||
| 386 | } | ||
| 387 | |||
| 388 | public boolean containsArgument( MethodEntry obfMethodEntry, String name ) | ||
| 389 | { | 399 | { |
| 390 | MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfMethodEntry.getName(), obfMethodEntry.getSignature() ) ); | 400 | MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfBehaviorEntry.getName(), obfBehaviorEntry.getSignature() ) ); |
| 391 | if( methodMapping != null ) | 401 | if( methodMapping != null ) |
| 392 | { | 402 | { |
| 393 | return methodMapping.containsArgument( name ); | 403 | return methodMapping.containsArgument( name ); |
diff --git a/src/cuchaz/enigma/mapping/ConstructorEntry.java b/src/cuchaz/enigma/mapping/ConstructorEntry.java index ad029e1c..d99d1c35 100644 --- a/src/cuchaz/enigma/mapping/ConstructorEntry.java +++ b/src/cuchaz/enigma/mapping/ConstructorEntry.java | |||
| @@ -43,6 +43,12 @@ public class ConstructorEntry implements BehaviorEntry, Serializable | |||
| 43 | m_signature = other.m_signature; | 43 | m_signature = other.m_signature; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | public ConstructorEntry( ConstructorEntry other, String newClassName ) | ||
| 47 | { | ||
| 48 | m_classEntry = new ClassEntry( newClassName ); | ||
| 49 | m_signature = other.m_signature; | ||
| 50 | } | ||
| 51 | |||
| 46 | @Override | 52 | @Override |
| 47 | public ClassEntry getClassEntry( ) | 53 | public ClassEntry getClassEntry( ) |
| 48 | { | 54 | { |
| @@ -77,6 +83,12 @@ public class ConstructorEntry implements BehaviorEntry, Serializable | |||
| 77 | } | 83 | } |
| 78 | 84 | ||
| 79 | @Override | 85 | @Override |
| 86 | public ConstructorEntry cloneToNewClass( ClassEntry classEntry ) | ||
| 87 | { | ||
| 88 | return new ConstructorEntry( this, classEntry.getName() ); | ||
| 89 | } | ||
| 90 | |||
| 91 | @Override | ||
| 80 | public int hashCode( ) | 92 | public int hashCode( ) |
| 81 | { | 93 | { |
| 82 | if( isStatic() ) | 94 | if( isStatic() ) |
diff --git a/src/cuchaz/enigma/mapping/Entry.java b/src/cuchaz/enigma/mapping/Entry.java index e1591f02..8524834c 100644 --- a/src/cuchaz/enigma/mapping/Entry.java +++ b/src/cuchaz/enigma/mapping/Entry.java | |||
| @@ -15,4 +15,5 @@ public interface Entry | |||
| 15 | String getName( ); | 15 | String getName( ); |
| 16 | String getClassName( ); | 16 | String getClassName( ); |
| 17 | ClassEntry getClassEntry( ); | 17 | ClassEntry getClassEntry( ); |
| 18 | Entry cloneToNewClass( ClassEntry classEntry ); | ||
| 18 | } | 19 | } |
diff --git a/src/cuchaz/enigma/mapping/FieldEntry.java b/src/cuchaz/enigma/mapping/FieldEntry.java index 435490bd..626af576 100644 --- a/src/cuchaz/enigma/mapping/FieldEntry.java +++ b/src/cuchaz/enigma/mapping/FieldEntry.java | |||
| @@ -68,6 +68,12 @@ public class FieldEntry implements Entry, Serializable | |||
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | @Override | 70 | @Override |
| 71 | public FieldEntry cloneToNewClass( ClassEntry classEntry ) | ||
| 72 | { | ||
| 73 | return new FieldEntry( this, classEntry.getName() ); | ||
| 74 | } | ||
| 75 | |||
| 76 | @Override | ||
| 71 | public int hashCode( ) | 77 | public int hashCode( ) |
| 72 | { | 78 | { |
| 73 | return Util.combineHashesOrdered( m_classEntry, m_name ); | 79 | return Util.combineHashesOrdered( m_classEntry, m_name ); |
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index f855f580..0b4e7f3c 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java | |||
| @@ -253,12 +253,12 @@ public class Mappings implements Serializable | |||
| 253 | return false; | 253 | return false; |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | public boolean containsArgument( MethodEntry obfMethodEntry, String name ) | 256 | public boolean containsArgument( BehaviorEntry obfBehaviorEntry, String name ) |
| 257 | { | 257 | { |
| 258 | ClassMapping classMapping = m_classesByObf.get( obfMethodEntry.getClassName() ); | 258 | ClassMapping classMapping = m_classesByObf.get( obfBehaviorEntry.getClassName() ); |
| 259 | if( classMapping != null ) | 259 | if( classMapping != null ) |
| 260 | { | 260 | { |
| 261 | return classMapping.containsArgument( obfMethodEntry, name ); | 261 | return classMapping.containsArgument( obfBehaviorEntry, name ); |
| 262 | } | 262 | } |
| 263 | return false; | 263 | return false; |
| 264 | } | 264 | } |
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java index 49e7b5fd..dcceefbd 100644 --- a/src/cuchaz/enigma/mapping/MappingsRenamer.java +++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java | |||
| @@ -79,7 +79,7 @@ public class MappingsRenamer | |||
| 79 | { | 79 | { |
| 80 | String deobfSignature = getTranslator( TranslationDirection.Deobfuscating ).translateSignature( obf.getSignature() ); | 80 | String deobfSignature = getTranslator( TranslationDirection.Deobfuscating ).translateSignature( obf.getSignature() ); |
| 81 | MethodEntry targetEntry = new MethodEntry( entry.getClassEntry(), deobfName, deobfSignature ); | 81 | MethodEntry targetEntry = new MethodEntry( entry.getClassEntry(), deobfName, deobfSignature ); |
| 82 | if( m_mappings.containsDeobfMethod( entry.getClassEntry(), deobfName, entry.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) | 82 | if( m_mappings.containsDeobfMethod( entry.getClassEntry(), deobfName, entry.getSignature() ) || m_index.containsObfBehavior( targetEntry ) ) |
| 83 | { | 83 | { |
| 84 | String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( entry.getClassName() ); | 84 | String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( entry.getClassName() ); |
| 85 | throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); | 85 | throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); |
| @@ -96,7 +96,7 @@ public class MappingsRenamer | |||
| 96 | { | 96 | { |
| 97 | deobfName = NameValidator.validateMethodName( deobfName ); | 97 | deobfName = NameValidator.validateMethodName( deobfName ); |
| 98 | MethodEntry targetEntry = new MethodEntry( obf.getClassEntry(), deobfName, obf.getSignature() ); | 98 | MethodEntry targetEntry = new MethodEntry( obf.getClassEntry(), deobfName, obf.getSignature() ); |
| 99 | if( m_mappings.containsDeobfMethod( obf.getClassEntry(), deobfName, obf.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) | 99 | if( m_mappings.containsDeobfMethod( obf.getClassEntry(), deobfName, obf.getSignature() ) || m_index.containsObfBehavior( targetEntry ) ) |
| 100 | { | 100 | { |
| 101 | String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( obf.getClassName() ); | 101 | String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( obf.getClassName() ); |
| 102 | throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); | 102 | throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); |
| @@ -110,7 +110,7 @@ public class MappingsRenamer | |||
| 110 | { | 110 | { |
| 111 | deobfName = NameValidator.validateArgumentName( deobfName ); | 111 | deobfName = NameValidator.validateArgumentName( deobfName ); |
| 112 | // NOTE: don't need to check arguments for name collisions with names determined by Procyon | 112 | // NOTE: don't need to check arguments for name collisions with names determined by Procyon |
| 113 | if( m_mappings.containsArgument( obf.getMethodEntry(), deobfName ) ) | 113 | if( m_mappings.containsArgument( obf.getBehaviorEntry(), deobfName ) ) |
| 114 | { | 114 | { |
| 115 | throw new IllegalNameException( deobfName, "There is already an argument with that name" ); | 115 | throw new IllegalNameException( deobfName, "There is already an argument with that name" ); |
| 116 | } | 116 | } |
| @@ -119,6 +119,32 @@ public class MappingsRenamer | |||
| 119 | classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName ); | 119 | classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName ); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | public boolean moveFieldToObfClass( ClassMapping classMapping, FieldMapping fieldMapping, ClassEntry obfClass ) | ||
| 123 | { | ||
| 124 | classMapping.removeFieldMapping( fieldMapping ); | ||
| 125 | ClassMapping targetClassMapping = getOrCreateClassMapping( obfClass ); | ||
| 126 | if( !targetClassMapping.containsObfField( fieldMapping.getObfName() ) | ||
| 127 | && !targetClassMapping.containsDeobfField( fieldMapping.getDeobfName() ) ) | ||
| 128 | { | ||
| 129 | targetClassMapping.addFieldMapping( fieldMapping ); | ||
| 130 | return true; | ||
| 131 | } | ||
| 132 | return false; | ||
| 133 | } | ||
| 134 | |||
| 135 | public boolean moveMethodToObfClass( ClassMapping classMapping, MethodMapping methodMapping, ClassEntry obfClass ) | ||
| 136 | { | ||
| 137 | classMapping.removeMethodMapping( methodMapping ); | ||
| 138 | ClassMapping targetClassMapping = getOrCreateClassMapping( obfClass ); | ||
| 139 | if( !targetClassMapping.containsObfMethod( methodMapping.getObfName(), methodMapping.getObfSignature() ) | ||
| 140 | && !targetClassMapping.containsDeobfMethod( methodMapping.getDeobfName(), methodMapping.getObfSignature() ) ) | ||
| 141 | { | ||
| 142 | targetClassMapping.addMethodMapping( methodMapping ); | ||
| 143 | return true; | ||
| 144 | } | ||
| 145 | return false; | ||
| 146 | } | ||
| 147 | |||
| 122 | public void write( OutputStream out ) | 148 | public void write( OutputStream out ) |
| 123 | throws IOException | 149 | throws IOException |
| 124 | { | 150 | { |
diff --git a/src/cuchaz/enigma/mapping/MethodEntry.java b/src/cuchaz/enigma/mapping/MethodEntry.java index a311e636..8adbfe9c 100644 --- a/src/cuchaz/enigma/mapping/MethodEntry.java +++ b/src/cuchaz/enigma/mapping/MethodEntry.java | |||
| @@ -81,6 +81,12 @@ public class MethodEntry implements BehaviorEntry, Serializable | |||
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | @Override | 83 | @Override |
| 84 | public MethodEntry cloneToNewClass( ClassEntry classEntry ) | ||
| 85 | { | ||
| 86 | return new MethodEntry( this, classEntry.getName() ); | ||
| 87 | } | ||
| 88 | |||
| 89 | @Override | ||
| 84 | public int hashCode( ) | 90 | public int hashCode( ) |
| 85 | { | 91 | { |
| 86 | return Util.combineHashesOrdered( m_classEntry, m_name, m_signature ); | 92 | return Util.combineHashesOrdered( m_classEntry, m_name, m_signature ); |
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java index b438e08d..7904ef53 100644 --- a/src/cuchaz/enigma/mapping/Translator.java +++ b/src/cuchaz/enigma/mapping/Translator.java | |||
| @@ -271,7 +271,7 @@ public class Translator | |||
| 271 | name = in.getName(); | 271 | name = in.getName(); |
| 272 | } | 272 | } |
| 273 | return new ArgumentEntry( | 273 | return new ArgumentEntry( |
| 274 | translateEntry( in.getMethodEntry() ), | 274 | translateEntry( in.getBehaviorEntry() ), |
| 275 | in.getIndex(), | 275 | in.getIndex(), |
| 276 | name | 276 | name |
| 277 | ); | 277 | ); |