diff options
| author | 2014-09-14 19:06:55 -0400 | |
|---|---|---|
| committer | 2014-09-14 19:06:55 -0400 | |
| commit | aa68099bb252dd1a1c275459f8babe537868bcaf (patch) | |
| tree | 88e600c5d3aec3e0d06558a8b7615a17cb80b34f /src/cuchaz | |
| parent | added some tests for a small inheritance hierarchy (diff) | |
| download | enigma-aa68099bb252dd1a1c275459f8babe537868bcaf.tar.gz enigma-aa68099bb252dd1a1c275459f8babe537868bcaf.tar.xz enigma-aa68099bb252dd1a1c275459f8babe537868bcaf.zip | |
fixed bug with method references pointing to wrong class
Diffstat (limited to 'src/cuchaz')
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 120 |
1 files changed, 81 insertions, 39 deletions
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index b4096e9d..f4843164 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -127,7 +127,7 @@ public class JarIndex | |||
| 127 | } | 127 | } |
| 128 | for( CtField field : c.getDeclaredFields() ) | 128 | for( CtField field : c.getDeclaredFields() ) |
| 129 | { | 129 | { |
| 130 | indexField( field ); | 130 | m_translationIndex.addField( className, field.getName() ); |
| 131 | } | 131 | } |
| 132 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) | 132 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) |
| 133 | { | 133 | { |
| @@ -135,9 +135,19 @@ public class JarIndex | |||
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | // step 4: index field, method, constructor references | ||
| 139 | for( CtClass c : JarClassIterator.classes( jar ) ) | ||
| 140 | { | ||
| 141 | ClassRenamer.moveAllClassesOutOfDefaultPackage( c, Constants.NonePackage ); | ||
| 142 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) | ||
| 143 | { | ||
| 144 | indexBehaviorReferences( behavior ); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 138 | if( buildInnerClasses ) | 148 | if( buildInnerClasses ) |
| 139 | { | 149 | { |
| 140 | // step 4: index inner classes and anonymous classes | 150 | // step 5: index inner classes and anonymous classes |
| 141 | for( CtClass c : JarClassIterator.classes( jar ) ) | 151 | for( CtClass c : JarClassIterator.classes( jar ) ) |
| 142 | { | 152 | { |
| 143 | ClassRenamer.moveAllClassesOutOfDefaultPackage( c, Constants.NonePackage ); | 153 | ClassRenamer.moveAllClassesOutOfDefaultPackage( c, Constants.NonePackage ); |
| @@ -163,7 +173,7 @@ public class JarIndex | |||
| 163 | } | 173 | } |
| 164 | } | 174 | } |
| 165 | 175 | ||
| 166 | // step 5: update other indices with inner class info | 176 | // step 6: update other indices with inner class info |
| 167 | Map<String,String> renames = Maps.newHashMap(); | 177 | Map<String,String> renames = Maps.newHashMap(); |
| 168 | for( Map.Entry<String,String> entry : m_outerClasses.entrySet() ) | 178 | for( Map.Entry<String,String> entry : m_outerClasses.entrySet() ) |
| 169 | { | 179 | { |
| @@ -183,25 +193,14 @@ public class JarIndex | |||
| 183 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_fieldReferences ); | 193 | EntryRenamer.renameMethodsInMultimap( m_bridgeMethods, m_fieldReferences ); |
| 184 | } | 194 | } |
| 185 | 195 | ||
| 186 | private void indexField( CtField field ) | ||
| 187 | { | ||
| 188 | String className = Descriptor.toJvmName( field.getDeclaringClass().getName() ); | ||
| 189 | m_translationIndex.addField( className, field.getName() ); | ||
| 190 | } | ||
| 191 | |||
| 192 | private void indexBehavior( CtBehavior behavior ) | 196 | private void indexBehavior( CtBehavior behavior ) |
| 193 | { | 197 | { |
| 194 | // get the method entry | 198 | // get the behavior entry |
| 195 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); | 199 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); |
| 196 | final BehaviorEntry thisEntry; | 200 | final BehaviorEntry behaviorEntry = getBehaviorEntry( behavior ); |
| 197 | if( behavior instanceof CtMethod ) | 201 | if( behaviorEntry instanceof MethodEntry ) |
| 198 | { | 202 | { |
| 199 | MethodEntry methodEntry = new MethodEntry( | 203 | MethodEntry methodEntry = (MethodEntry)behaviorEntry; |
| 200 | new ClassEntry( className ), | ||
| 201 | behavior.getName(), | ||
| 202 | behavior.getSignature() | ||
| 203 | ); | ||
| 204 | thisEntry = methodEntry; | ||
| 205 | 204 | ||
| 206 | // index implementation | 205 | // index implementation |
| 207 | m_methodImplementations.put( className, methodEntry ); | 206 | m_methodImplementations.put( className, methodEntry ); |
| @@ -218,24 +217,13 @@ public class JarIndex | |||
| 218 | m_bridgeMethods.put( bridgedMethodEntry, methodEntry ); | 217 | m_bridgeMethods.put( bridgedMethodEntry, methodEntry ); |
| 219 | } | 218 | } |
| 220 | } | 219 | } |
| 221 | else if( behavior instanceof CtConstructor ) | 220 | // looks like we don't care about constructors here |
| 222 | { | 221 | } |
| 223 | boolean isStatic = behavior.getName().equals( "<clinit>" ); | 222 | |
| 224 | if( isStatic ) | 223 | private void indexBehaviorReferences( CtBehavior behavior ) |
| 225 | { | 224 | { |
| 226 | thisEntry = new ConstructorEntry( new ClassEntry( className ) ); | ||
| 227 | } | ||
| 228 | else | ||
| 229 | { | ||
| 230 | thisEntry = new ConstructorEntry( new ClassEntry( className ), behavior.getSignature() ); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | else | ||
| 234 | { | ||
| 235 | throw new IllegalArgumentException( "behavior must be a method or a constructor!" ); | ||
| 236 | } | ||
| 237 | |||
| 238 | // index method calls | 225 | // index method calls |
| 226 | final BehaviorEntry behaviorEntry = getBehaviorEntry( behavior ); | ||
| 239 | try | 227 | try |
| 240 | { | 228 | { |
| 241 | behavior.instrument( new ExprEditor( ) | 229 | behavior.instrument( new ExprEditor( ) |
| @@ -249,9 +237,10 @@ public class JarIndex | |||
| 249 | call.getMethodName(), | 237 | call.getMethodName(), |
| 250 | call.getSignature() | 238 | call.getSignature() |
| 251 | ); | 239 | ); |
| 240 | calledMethodEntry = resolveMethodClass( calledMethodEntry ); | ||
| 252 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( | 241 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( |
| 253 | calledMethodEntry, | 242 | calledMethodEntry, |
| 254 | thisEntry | 243 | behaviorEntry |
| 255 | ); | 244 | ); |
| 256 | m_behaviorReferences.put( calledMethodEntry, reference ); | 245 | m_behaviorReferences.put( calledMethodEntry, reference ); |
| 257 | } | 246 | } |
| @@ -266,7 +255,7 @@ public class JarIndex | |||
| 266 | ); | 255 | ); |
| 267 | EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>( | 256 | EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>( |
| 268 | calledFieldEntry, | 257 | calledFieldEntry, |
| 269 | thisEntry | 258 | behaviorEntry |
| 270 | ); | 259 | ); |
| 271 | m_fieldReferences.put( calledFieldEntry, reference ); | 260 | m_fieldReferences.put( calledFieldEntry, reference ); |
| 272 | } | 261 | } |
| @@ -284,7 +273,7 @@ public class JarIndex | |||
| 284 | ); | 273 | ); |
| 285 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( | 274 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( |
| 286 | calledConstructorEntry, | 275 | calledConstructorEntry, |
| 287 | thisEntry | 276 | behaviorEntry |
| 288 | ); | 277 | ); |
| 289 | m_behaviorReferences.put( calledConstructorEntry, reference ); | 278 | m_behaviorReferences.put( calledConstructorEntry, reference ); |
| 290 | } | 279 | } |
| @@ -299,7 +288,7 @@ public class JarIndex | |||
| 299 | ); | 288 | ); |
| 300 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( | 289 | EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( |
| 301 | calledConstructorEntry, | 290 | calledConstructorEntry, |
| 302 | thisEntry | 291 | behaviorEntry |
| 303 | ); | 292 | ); |
| 304 | m_behaviorReferences.put( calledConstructorEntry, reference ); | 293 | m_behaviorReferences.put( calledConstructorEntry, reference ); |
| 305 | } | 294 | } |
| @@ -311,6 +300,59 @@ public class JarIndex | |||
| 311 | } | 300 | } |
| 312 | } | 301 | } |
| 313 | 302 | ||
| 303 | private BehaviorEntry getBehaviorEntry( CtBehavior behavior ) | ||
| 304 | { | ||
| 305 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); | ||
| 306 | if( behavior instanceof CtMethod ) | ||
| 307 | { | ||
| 308 | return new MethodEntry( | ||
| 309 | new ClassEntry( className ), | ||
| 310 | behavior.getName(), | ||
| 311 | behavior.getSignature() | ||
| 312 | ); | ||
| 313 | } | ||
| 314 | else if( behavior instanceof CtConstructor ) | ||
| 315 | { | ||
| 316 | boolean isStatic = behavior.getName().equals( "<clinit>" ); | ||
| 317 | if( isStatic ) | ||
| 318 | { | ||
| 319 | return new ConstructorEntry( new ClassEntry( className ) ); | ||
| 320 | } | ||
| 321 | else | ||
| 322 | { | ||
| 323 | return new ConstructorEntry( new ClassEntry( className ), behavior.getSignature() ); | ||
| 324 | } | ||
| 325 | } | ||
| 326 | else | ||
| 327 | { | ||
| 328 | throw new IllegalArgumentException( "behavior must be a method or a constructor!" ); | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | private MethodEntry resolveMethodClass( MethodEntry methodEntry ) | ||
| 333 | { | ||
| 334 | // this entry could refer to a method on a class where the method is not actually implemented | ||
| 335 | // travel up the inheritance tree to find the closest implementation | ||
| 336 | while( !isMethodImplemented( methodEntry ) ) | ||
| 337 | { | ||
| 338 | // is there a parent class? | ||
| 339 | String superclassName = m_translationIndex.getSuperclassName( methodEntry.getClassName() ); | ||
| 340 | if( superclassName == null ) | ||
| 341 | { | ||
| 342 | // this is probably a method from a class in a library | ||
| 343 | // we can't trace the implementation up any higher unless we index the library | ||
| 344 | return methodEntry; | ||
| 345 | } | ||
| 346 | |||
| 347 | // move up to the parent class | ||
| 348 | methodEntry = new MethodEntry( | ||
| 349 | new ClassEntry( superclassName ), | ||
| 350 | methodEntry.getName(), | ||
| 351 | methodEntry.getSignature() | ||
| 352 | ); | ||
| 353 | } | ||
| 354 | return methodEntry; | ||
| 355 | } | ||
| 314 | 356 | ||
| 315 | private CtMethod getBridgedMethod( CtMethod method ) | 357 | private CtMethod getBridgedMethod( CtMethod method ) |
| 316 | { | 358 | { |