diff options
| author | 2014-08-12 00:24:11 -0400 | |
|---|---|---|
| committer | 2014-08-12 00:24:11 -0400 | |
| commit | 52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e (patch) | |
| tree | 52a89485240cb15318adb29a340ed5dc9056bc8c /src/cuchaz/enigma/analysis/JarIndex.java | |
| parent | fix keyboard shortcuts (diff) | |
| download | enigma-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.java | 101 |
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; | |||
| 14 | import java.io.IOException; | 14 | import java.io.IOException; |
| 15 | import java.io.InputStream; | 15 | import java.io.InputStream; |
| 16 | import java.util.Collection; | 16 | import java.util.Collection; |
| 17 | import java.util.Enumeration; | ||
| 17 | import java.util.List; | 18 | import java.util.List; |
| 19 | import java.util.Set; | ||
| 20 | import java.util.jar.JarEntry; | ||
| 21 | import java.util.jar.JarFile; | ||
| 18 | import java.util.zip.ZipEntry; | 22 | import java.util.zip.ZipEntry; |
| 19 | import java.util.zip.ZipInputStream; | 23 | import java.util.zip.ZipInputStream; |
| 20 | 24 | ||
| 21 | import com.google.common.collect.HashMultimap; | ||
| 22 | import com.google.common.collect.Multimap; | ||
| 23 | |||
| 24 | import javassist.ByteArrayClassPath; | 25 | import javassist.ByteArrayClassPath; |
| 26 | import javassist.CannotCompileException; | ||
| 25 | import javassist.ClassPool; | 27 | import javassist.ClassPool; |
| 28 | import javassist.CtBehavior; | ||
| 26 | import javassist.CtClass; | 29 | import javassist.CtClass; |
| 27 | import javassist.NotFoundException; | 30 | import javassist.NotFoundException; |
| 28 | import javassist.bytecode.Descriptor; | 31 | import javassist.bytecode.Descriptor; |
| 29 | import javassist.bytecode.MethodInfo; | 32 | import javassist.expr.ExprEditor; |
| 33 | import javassist.expr.MethodCall; | ||
| 34 | |||
| 35 | import com.google.common.collect.HashMultimap; | ||
| 36 | import com.google.common.collect.Multimap; | ||
| 37 | import com.google.common.collect.Sets; | ||
| 38 | |||
| 30 | import cuchaz.enigma.Constants; | 39 | import cuchaz.enigma.Constants; |
| 31 | import cuchaz.enigma.mapping.ClassEntry; | 40 | import cuchaz.enigma.mapping.ClassEntry; |
| 32 | import cuchaz.enigma.mapping.MethodEntry; | 41 | import cuchaz.enigma.mapping.MethodEntry; |
| @@ -34,16 +43,35 @@ import cuchaz.enigma.mapping.Translator; | |||
| 34 | 43 | ||
| 35 | public class JarIndex | 44 | public 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; |