summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/JarIndex.java
diff options
context:
space:
mode:
authorGravatar jeff2014-08-12 00:24:11 -0400
committerGravatar jeff2014-08-12 00:24:11 -0400
commit52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e (patch)
tree52a89485240cb15318adb29a340ed5dc9056bc8c /src/cuchaz/enigma/analysis/JarIndex.java
parentfix keyboard shortcuts (diff)
downloadenigma-fork-52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e.tar.gz
enigma-fork-52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e.tar.xz
enigma-fork-52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e.zip
got simple method call graph working!
Diffstat (limited to 'src/cuchaz/enigma/analysis/JarIndex.java')
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java101
1 files changed, 89 insertions, 12 deletions
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index 8a8384c..06b0173 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -14,19 +14,28 @@ import java.io.ByteArrayOutputStream;
14import java.io.IOException; 14import java.io.IOException;
15import java.io.InputStream; 15import java.io.InputStream;
16import java.util.Collection; 16import java.util.Collection;
17import java.util.Enumeration;
17import java.util.List; 18import java.util.List;
19import java.util.Set;
20import java.util.jar.JarEntry;
21import java.util.jar.JarFile;
18import java.util.zip.ZipEntry; 22import java.util.zip.ZipEntry;
19import java.util.zip.ZipInputStream; 23import java.util.zip.ZipInputStream;
20 24
21import com.google.common.collect.HashMultimap;
22import com.google.common.collect.Multimap;
23
24import javassist.ByteArrayClassPath; 25import javassist.ByteArrayClassPath;
26import javassist.CannotCompileException;
25import javassist.ClassPool; 27import javassist.ClassPool;
28import javassist.CtBehavior;
26import javassist.CtClass; 29import javassist.CtClass;
27import javassist.NotFoundException; 30import javassist.NotFoundException;
28import javassist.bytecode.Descriptor; 31import javassist.bytecode.Descriptor;
29import javassist.bytecode.MethodInfo; 32import javassist.expr.ExprEditor;
33import javassist.expr.MethodCall;
34
35import com.google.common.collect.HashMultimap;
36import com.google.common.collect.Multimap;
37import com.google.common.collect.Sets;
38
30import cuchaz.enigma.Constants; 39import cuchaz.enigma.Constants;
31import cuchaz.enigma.mapping.ClassEntry; 40import cuchaz.enigma.mapping.ClassEntry;
32import cuchaz.enigma.mapping.MethodEntry; 41import cuchaz.enigma.mapping.MethodEntry;
@@ -34,16 +43,35 @@ import cuchaz.enigma.mapping.Translator;
34 43
35public class JarIndex 44public class JarIndex
36{ 45{
46 private Set<String> m_obfClassNames;
37 private Ancestries m_ancestries; 47 private Ancestries m_ancestries;
38 private Multimap<String,String> m_methodImplementations; 48 private Multimap<String,MethodEntry> m_methodImplementations;
49 private Multimap<MethodEntry,MethodEntry> m_methodCalls;
39 50
40 public JarIndex( ) 51 public JarIndex( JarFile jar )
41 { 52 {
53 m_obfClassNames = Sets.newHashSet();
42 m_ancestries = new Ancestries(); 54 m_ancestries = new Ancestries();
43 m_methodImplementations = HashMultimap.create(); 55 m_methodImplementations = HashMultimap.create();
56 m_methodCalls = HashMultimap.create();
57
58 // read the class names
59 Enumeration<JarEntry> enumeration = jar.entries();
60 while( enumeration.hasMoreElements() )
61 {
62 JarEntry entry = enumeration.nextElement();
63
64 // filter out non-classes
65 if( entry.isDirectory() || !entry.getName().endsWith( ".class" ) )
66 {
67 continue;
68 }
69
70 String className = entry.getName().substring( 0, entry.getName().length() - 6 );
71 m_obfClassNames.add( Descriptor.toJvmName( className ) );
72 }
44 } 73 }
45 74
46 @SuppressWarnings( "unchecked" )
47 public void indexJar( InputStream in ) 75 public void indexJar( InputStream in )
48 throws IOException 76 throws IOException
49 { 77 {
@@ -89,7 +117,10 @@ public class JarIndex
89 { 117 {
90 CtClass c = classPool.get( className ); 118 CtClass c = classPool.get( className );
91 m_ancestries.addSuperclass( c.getName(), c.getClassFile().getSuperclass() ); 119 m_ancestries.addSuperclass( c.getName(), c.getClassFile().getSuperclass() );
92 addMethodImplementations( c.getName(), (List<MethodInfo>)c.getClassFile().getMethods() ); 120 for( CtBehavior behavior : c.getDeclaredBehaviors() )
121 {
122 indexBehavior( behavior );
123 }
93 } 124 }
94 catch( NotFoundException ex ) 125 catch( NotFoundException ex )
95 { 126 {
@@ -98,14 +129,55 @@ public class JarIndex
98 } 129 }
99 } 130 }
100 131
101 private void addMethodImplementations( String name, List<MethodInfo> methods ) 132 private void indexBehavior( CtBehavior behavior )
102 { 133 {
103 for( MethodInfo method : methods ) 134 // get the method entry
135 String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() );
136 final MethodEntry methodEntry = new MethodEntry(
137 new ClassEntry( className ),
138 behavior.getName(),
139 behavior.getSignature()
140 );
141
142 // index implementation
143 m_methodImplementations.put( className, methodEntry );
144
145 // index method calls
146 try
147 {
148 behavior.instrument( new ExprEditor( )
149 {
150 @Override
151 public void edit( MethodCall call )
152 {
153 // is this a jar class?
154 String className = Descriptor.toJvmName( call.getClassName() );
155 if( !m_obfClassNames.contains( className ) )
156 {
157 return;
158 }
159
160 // make entry for the called method
161 MethodEntry calledMethodEntry = new MethodEntry(
162 new ClassEntry( className ),
163 call.getMethodName(),
164 call.getSignature()
165 );
166 m_methodCalls.put( calledMethodEntry, methodEntry );
167 }
168 } );
169 }
170 catch( CannotCompileException ex )
104 { 171 {
105 m_methodImplementations.put( name, getMethodKey( method.getName(), method.getDescriptor() ) ); 172 throw new Error( ex );
106 } 173 }
107 } 174 }
108 175
176 public Set<String> getObfClassNames( )
177 {
178 return m_obfClassNames;
179 }
180
109 public Ancestries getAncestries( ) 181 public Ancestries getAncestries( )
110 { 182 {
111 return m_ancestries; 183 return m_ancestries;
@@ -118,7 +190,7 @@ public class JarIndex
118 190
119 public boolean isMethodImplemented( String className, String methodName, String methodSignature ) 191 public boolean isMethodImplemented( String className, String methodName, String methodSignature )
120 { 192 {
121 Collection<String> implementations = m_methodImplementations.get( className ); 193 Collection<MethodEntry> implementations = m_methodImplementations.get( className );
122 if( implementations == null ) 194 if( implementations == null )
123 { 195 {
124 return false; 196 return false;
@@ -169,6 +241,11 @@ public class JarIndex
169 return rootNode; 241 return rootNode;
170 } 242 }
171 243
244 public Collection<MethodEntry> getMethodCallers( MethodEntry methodEntry )
245 {
246 return m_methodCalls.get( methodEntry );
247 }
248
172 private String getMethodKey( String name, String signature ) 249 private String getMethodKey( String name, String signature )
173 { 250 {
174 return name + signature; 251 return name + signature;