summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/JarIndex.java
diff options
context:
space:
mode:
authorGravatar jeff2014-09-14 19:06:55 -0400
committerGravatar jeff2014-09-14 19:06:55 -0400
commitaa68099bb252dd1a1c275459f8babe537868bcaf (patch)
tree88e600c5d3aec3e0d06558a8b7615a17cb80b34f /src/cuchaz/enigma/analysis/JarIndex.java
parentadded some tests for a small inheritance hierarchy (diff)
downloadenigma-fork-aa68099bb252dd1a1c275459f8babe537868bcaf.tar.gz
enigma-fork-aa68099bb252dd1a1c275459f8babe537868bcaf.tar.xz
enigma-fork-aa68099bb252dd1a1c275459f8babe537868bcaf.zip
fixed bug with method references pointing to wrong class
Diffstat (limited to 'src/cuchaz/enigma/analysis/JarIndex.java')
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java120
1 files changed, 81 insertions, 39 deletions
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index b4096e9..f484316 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 {