diff options
| author | 2014-08-13 00:22:12 -0400 | |
|---|---|---|
| committer | 2014-08-13 00:22:12 -0400 | |
| commit | cc74d0e62cfdcf14c5918234f69d587d264807ed (patch) | |
| tree | 7a11bd6af9b7cd2f28c3dbd43a281b4036464f77 | |
| parent | got simple method call graph working! (diff) | |
| download | enigma-fork-cc74d0e62cfdcf14c5918234f69d587d264807ed.tar.gz enigma-fork-cc74d0e62cfdcf14c5918234f69d587d264807ed.tar.xz enigma-fork-cc74d0e62cfdcf14c5918234f69d587d264807ed.zip | |
added support for field access searches
added proper detection/handling for constructors
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 30 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/FieldCallsTreeNode.java | 82 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 107 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/MethodCallsTreeNode.java | 114 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/SourceIndexVisitor.java | 5 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 60 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiController.java | 38 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/ConstructorEntry.java | 94 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Translator.java | 8 |
9 files changed, 460 insertions, 78 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 33eef08..770172e 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -34,6 +34,7 @@ import cuchaz.enigma.analysis.SourceIndexVisitor; | |||
| 34 | import cuchaz.enigma.mapping.ArgumentEntry; | 34 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 35 | import cuchaz.enigma.mapping.ClassEntry; | 35 | import cuchaz.enigma.mapping.ClassEntry; |
| 36 | import cuchaz.enigma.mapping.ClassMapping; | 36 | import cuchaz.enigma.mapping.ClassMapping; |
| 37 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 37 | import cuchaz.enigma.mapping.Entry; | 38 | import cuchaz.enigma.mapping.Entry; |
| 38 | import cuchaz.enigma.mapping.FieldEntry; | 39 | import cuchaz.enigma.mapping.FieldEntry; |
| 39 | import cuchaz.enigma.mapping.Mappings; | 40 | import cuchaz.enigma.mapping.Mappings; |
| @@ -185,6 +186,10 @@ public class Deobfuscator | |||
| 185 | { | 186 | { |
| 186 | m_renamer.setMethodTreeName( (MethodEntry)obfEntry, newName ); | 187 | m_renamer.setMethodTreeName( (MethodEntry)obfEntry, newName ); |
| 187 | } | 188 | } |
| 189 | else if( obfEntry instanceof ConstructorEntry ) | ||
| 190 | { | ||
| 191 | m_renamer.setClassName( obfEntry.getClassEntry(), newName ); | ||
| 192 | } | ||
| 188 | else if( obfEntry instanceof ArgumentEntry ) | 193 | else if( obfEntry instanceof ArgumentEntry ) |
| 189 | { | 194 | { |
| 190 | m_renamer.setArgumentName( (ArgumentEntry)obfEntry, newName ); | 195 | m_renamer.setArgumentName( (ArgumentEntry)obfEntry, newName ); |
| @@ -210,6 +215,10 @@ public class Deobfuscator | |||
| 210 | { | 215 | { |
| 211 | return translator.translateEntry( (MethodEntry)deobfEntry ); | 216 | return translator.translateEntry( (MethodEntry)deobfEntry ); |
| 212 | } | 217 | } |
| 218 | else if( deobfEntry instanceof ConstructorEntry ) | ||
| 219 | { | ||
| 220 | return translator.translateEntry( (ConstructorEntry)deobfEntry ); | ||
| 221 | } | ||
| 213 | else if( deobfEntry instanceof ArgumentEntry ) | 222 | else if( deobfEntry instanceof ArgumentEntry ) |
| 214 | { | 223 | { |
| 215 | return translator.translateEntry( (ArgumentEntry)deobfEntry ); | 224 | return translator.translateEntry( (ArgumentEntry)deobfEntry ); |
| @@ -235,6 +244,10 @@ public class Deobfuscator | |||
| 235 | { | 244 | { |
| 236 | return translator.translateEntry( (MethodEntry)obfEntry ); | 245 | return translator.translateEntry( (MethodEntry)obfEntry ); |
| 237 | } | 246 | } |
| 247 | else if( obfEntry instanceof ConstructorEntry ) | ||
| 248 | { | ||
| 249 | return translator.translateEntry( (ConstructorEntry)obfEntry ); | ||
| 250 | } | ||
| 238 | else if( obfEntry instanceof ArgumentEntry ) | 251 | else if( obfEntry instanceof ArgumentEntry ) |
| 239 | { | 252 | { |
| 240 | return translator.translateEntry( (ArgumentEntry)obfEntry ); | 253 | return translator.translateEntry( (ArgumentEntry)obfEntry ); |
| @@ -263,6 +276,11 @@ public class Deobfuscator | |||
| 263 | String deobfName = translator.translate( (MethodEntry)obfEntry ); | 276 | String deobfName = translator.translate( (MethodEntry)obfEntry ); |
| 264 | return deobfName != null && !deobfName.equals( obfEntry.getName() ); | 277 | return deobfName != null && !deobfName.equals( obfEntry.getName() ); |
| 265 | } | 278 | } |
| 279 | else if( obfEntry instanceof ConstructorEntry ) | ||
| 280 | { | ||
| 281 | String deobfName = translator.translate( obfEntry.getClassEntry() ); | ||
| 282 | return deobfName != null && !deobfName.equals( obfEntry.getClassName() ); | ||
| 283 | } | ||
| 266 | else if( obfEntry instanceof ArgumentEntry ) | 284 | else if( obfEntry instanceof ArgumentEntry ) |
| 267 | { | 285 | { |
| 268 | return translator.translate( (ArgumentEntry)obfEntry ) != null; | 286 | return translator.translate( (ArgumentEntry)obfEntry ) != null; |
| @@ -282,16 +300,20 @@ public class Deobfuscator | |||
| 282 | } | 300 | } |
| 283 | else if( obfEntry instanceof FieldEntry ) | 301 | else if( obfEntry instanceof FieldEntry ) |
| 284 | { | 302 | { |
| 285 | return m_jarIndex.getObfClassNames().contains( ((FieldEntry)obfEntry).getClassName() ); | 303 | return m_jarIndex.getObfClassNames().contains( obfEntry.getClassName() ); |
| 286 | } | 304 | } |
| 287 | else if( obfEntry instanceof MethodEntry ) | 305 | else if( obfEntry instanceof MethodEntry ) |
| 288 | { | 306 | { |
| 289 | return m_jarIndex.getObfClassNames().contains( ((MethodEntry)obfEntry).getClassName() ); | 307 | return m_jarIndex.getObfClassNames().contains( obfEntry.getClassName() ); |
| 308 | } | ||
| 309 | else if( obfEntry instanceof ConstructorEntry ) | ||
| 310 | { | ||
| 311 | return m_jarIndex.getObfClassNames().contains( obfEntry.getClassName() ); | ||
| 290 | } | 312 | } |
| 291 | else if( obfEntry instanceof ArgumentEntry ) | 313 | else if( obfEntry instanceof ArgumentEntry ) |
| 292 | { | 314 | { |
| 293 | // arguments only appear in method delcarations | 315 | // arguments only appear in method declarations |
| 294 | // since we only show declrations for obf classes, these are always obfuscated | 316 | // since we only show declarations for obf classes, these are always obfuscated |
| 295 | return true; | 317 | return true; |
| 296 | } | 318 | } |
| 297 | 319 | ||
diff --git a/src/cuchaz/enigma/analysis/FieldCallsTreeNode.java b/src/cuchaz/enigma/analysis/FieldCallsTreeNode.java new file mode 100644 index 0000000..0427b3b --- /dev/null +++ b/src/cuchaz/enigma/analysis/FieldCallsTreeNode.java | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.analysis; | ||
| 12 | |||
| 13 | import javax.swing.tree.DefaultMutableTreeNode; | ||
| 14 | |||
| 15 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 16 | import cuchaz.enigma.mapping.Entry; | ||
| 17 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 18 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 19 | import cuchaz.enigma.mapping.Translator; | ||
| 20 | |||
| 21 | public class FieldCallsTreeNode extends DefaultMutableTreeNode | ||
| 22 | { | ||
| 23 | private static final long serialVersionUID = -7934108091928699835L; | ||
| 24 | |||
| 25 | private Translator m_deobfuscatingTranslator; | ||
| 26 | private FieldEntry m_entry; | ||
| 27 | |||
| 28 | public FieldCallsTreeNode( Translator deobfuscatingTranslator, FieldEntry fieldEntry ) | ||
| 29 | { | ||
| 30 | m_deobfuscatingTranslator = deobfuscatingTranslator; | ||
| 31 | m_entry = fieldEntry; | ||
| 32 | } | ||
| 33 | |||
| 34 | public FieldEntry getFieldEntry( ) | ||
| 35 | { | ||
| 36 | return m_entry; | ||
| 37 | } | ||
| 38 | |||
| 39 | @Override | ||
| 40 | public String toString( ) | ||
| 41 | { | ||
| 42 | String className = m_deobfuscatingTranslator.translateClass( m_entry.getClassName() ); | ||
| 43 | if( className == null ) | ||
| 44 | { | ||
| 45 | className = m_entry.getClassName(); | ||
| 46 | } | ||
| 47 | |||
| 48 | String targetName = m_deobfuscatingTranslator.translate( m_entry ); | ||
| 49 | if( targetName == null ) | ||
| 50 | { | ||
| 51 | targetName = m_entry.getName(); | ||
| 52 | } | ||
| 53 | return className + "." + targetName; | ||
| 54 | } | ||
| 55 | |||
| 56 | public void load( JarIndex index, boolean recurse ) | ||
| 57 | { | ||
| 58 | // get all the child nodes | ||
| 59 | for( Entry entry : index.getFieldCallers( m_entry ) ) | ||
| 60 | { | ||
| 61 | if( entry instanceof MethodEntry ) | ||
| 62 | { | ||
| 63 | add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (MethodEntry)entry ) ); | ||
| 64 | } | ||
| 65 | else if( entry instanceof ConstructorEntry ) | ||
| 66 | { | ||
| 67 | add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (ConstructorEntry)entry ) ); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | if( recurse && children != null ) | ||
| 72 | { | ||
| 73 | for( Object node : children ) | ||
| 74 | { | ||
| 75 | if( node instanceof MethodCallsTreeNode ) | ||
| 76 | { | ||
| 77 | ((MethodCallsTreeNode)node).load( index, true ); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
| 81 | } | ||
| 82 | } | ||
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 06b0173..96bddc1 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -27,17 +27,26 @@ import javassist.CannotCompileException; | |||
| 27 | import javassist.ClassPool; | 27 | import javassist.ClassPool; |
| 28 | import javassist.CtBehavior; | 28 | import javassist.CtBehavior; |
| 29 | import javassist.CtClass; | 29 | import javassist.CtClass; |
| 30 | import javassist.CtConstructor; | ||
| 31 | import javassist.CtMethod; | ||
| 30 | import javassist.NotFoundException; | 32 | import javassist.NotFoundException; |
| 31 | import javassist.bytecode.Descriptor; | 33 | import javassist.bytecode.Descriptor; |
| 34 | import javassist.expr.ConstructorCall; | ||
| 32 | import javassist.expr.ExprEditor; | 35 | import javassist.expr.ExprEditor; |
| 36 | import javassist.expr.FieldAccess; | ||
| 33 | import javassist.expr.MethodCall; | 37 | import javassist.expr.MethodCall; |
| 38 | import javassist.expr.NewExpr; | ||
| 34 | 39 | ||
| 35 | import com.google.common.collect.HashMultimap; | 40 | import com.google.common.collect.HashMultimap; |
| 41 | import com.google.common.collect.Lists; | ||
| 36 | import com.google.common.collect.Multimap; | 42 | import com.google.common.collect.Multimap; |
| 37 | import com.google.common.collect.Sets; | 43 | import com.google.common.collect.Sets; |
| 38 | 44 | ||
| 39 | import cuchaz.enigma.Constants; | 45 | import cuchaz.enigma.Constants; |
| 40 | import cuchaz.enigma.mapping.ClassEntry; | 46 | import cuchaz.enigma.mapping.ClassEntry; |
| 47 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 48 | import cuchaz.enigma.mapping.Entry; | ||
| 49 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 41 | import cuchaz.enigma.mapping.MethodEntry; | 50 | import cuchaz.enigma.mapping.MethodEntry; |
| 42 | import cuchaz.enigma.mapping.Translator; | 51 | import cuchaz.enigma.mapping.Translator; |
| 43 | 52 | ||
| @@ -46,7 +55,8 @@ public class JarIndex | |||
| 46 | private Set<String> m_obfClassNames; | 55 | private Set<String> m_obfClassNames; |
| 47 | private Ancestries m_ancestries; | 56 | private Ancestries m_ancestries; |
| 48 | private Multimap<String,MethodEntry> m_methodImplementations; | 57 | private Multimap<String,MethodEntry> m_methodImplementations; |
| 49 | private Multimap<MethodEntry,MethodEntry> m_methodCalls; | 58 | private Multimap<Entry,Entry> m_methodCalls; |
| 59 | private Multimap<FieldEntry,Entry> m_fieldCalls; | ||
| 50 | 60 | ||
| 51 | public JarIndex( JarFile jar ) | 61 | public JarIndex( JarFile jar ) |
| 52 | { | 62 | { |
| @@ -54,6 +64,7 @@ public class JarIndex | |||
| 54 | m_ancestries = new Ancestries(); | 64 | m_ancestries = new Ancestries(); |
| 55 | m_methodImplementations = HashMultimap.create(); | 65 | m_methodImplementations = HashMultimap.create(); |
| 56 | m_methodCalls = HashMultimap.create(); | 66 | m_methodCalls = HashMultimap.create(); |
| 67 | m_fieldCalls = HashMultimap.create(); | ||
| 57 | 68 | ||
| 58 | // read the class names | 69 | // read the class names |
| 59 | Enumeration<JarEntry> enumeration = jar.entries(); | 70 | Enumeration<JarEntry> enumeration = jar.entries(); |
| @@ -133,14 +144,30 @@ public class JarIndex | |||
| 133 | { | 144 | { |
| 134 | // get the method entry | 145 | // get the method entry |
| 135 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); | 146 | String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); |
| 136 | final MethodEntry methodEntry = new MethodEntry( | 147 | final Entry thisEntry; |
| 137 | new ClassEntry( className ), | 148 | if( behavior instanceof CtMethod ) |
| 138 | behavior.getName(), | 149 | { |
| 139 | behavior.getSignature() | 150 | MethodEntry methodEntry = new MethodEntry( |
| 140 | ); | 151 | new ClassEntry( className ), |
| 141 | 152 | behavior.getName(), | |
| 142 | // index implementation | 153 | behavior.getSignature() |
| 143 | m_methodImplementations.put( className, methodEntry ); | 154 | ); |
| 155 | thisEntry = methodEntry; | ||
| 156 | |||
| 157 | // index implementation | ||
| 158 | m_methodImplementations.put( className, methodEntry ); | ||
| 159 | } | ||
| 160 | else if( behavior instanceof CtConstructor ) | ||
| 161 | { | ||
| 162 | thisEntry = new ConstructorEntry( | ||
| 163 | new ClassEntry( className ), | ||
| 164 | behavior.getSignature() | ||
| 165 | ); | ||
| 166 | } | ||
| 167 | else | ||
| 168 | { | ||
| 169 | throw new IllegalArgumentException( "behavior must be a method or a constructor!" ); | ||
| 170 | } | ||
| 144 | 171 | ||
| 145 | // index method calls | 172 | // index method calls |
| 146 | try | 173 | try |
| @@ -150,20 +177,53 @@ public class JarIndex | |||
| 150 | @Override | 177 | @Override |
| 151 | public void edit( MethodCall call ) | 178 | public void edit( MethodCall call ) |
| 152 | { | 179 | { |
| 153 | // is this a jar class? | ||
| 154 | String className = Descriptor.toJvmName( call.getClassName() ); | 180 | 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( | 181 | MethodEntry calledMethodEntry = new MethodEntry( |
| 162 | new ClassEntry( className ), | 182 | new ClassEntry( className ), |
| 163 | call.getMethodName(), | 183 | call.getMethodName(), |
| 164 | call.getSignature() | 184 | call.getSignature() |
| 165 | ); | 185 | ); |
| 166 | m_methodCalls.put( calledMethodEntry, methodEntry ); | 186 | m_methodCalls.put( calledMethodEntry, thisEntry ); |
| 187 | } | ||
| 188 | |||
| 189 | @Override | ||
| 190 | public void edit( FieldAccess call ) | ||
| 191 | { | ||
| 192 | String className = Descriptor.toJvmName( call.getClassName() ); | ||
| 193 | FieldEntry calledFieldEntry = new FieldEntry( | ||
| 194 | new ClassEntry( className ), | ||
| 195 | call.getFieldName() | ||
| 196 | ); | ||
| 197 | m_fieldCalls.put( calledFieldEntry, thisEntry ); | ||
| 198 | } | ||
| 199 | |||
| 200 | @Override | ||
| 201 | public void edit( ConstructorCall call ) | ||
| 202 | { | ||
| 203 | String className = Descriptor.toJvmName( call.getClassName() ); | ||
| 204 | ConstructorEntry calledConstructorEntry = new ConstructorEntry( | ||
| 205 | new ClassEntry( className ), | ||
| 206 | call.getSignature() | ||
| 207 | ); | ||
| 208 | m_methodCalls.put( calledConstructorEntry, thisEntry ); | ||
| 209 | } | ||
| 210 | |||
| 211 | @Override | ||
| 212 | public void edit( NewExpr call ) | ||
| 213 | { | ||
| 214 | String className = Descriptor.toJvmName( call.getClassName() ); | ||
| 215 | ConstructorEntry calledConstructorEntry = new ConstructorEntry( | ||
| 216 | new ClassEntry( className ), | ||
| 217 | call.getSignature() | ||
| 218 | ); | ||
| 219 | |||
| 220 | // TEMP | ||
| 221 | if( className.equals( "bgw" ) ) | ||
| 222 | { | ||
| 223 | System.out.println( calledConstructorEntry + " called by " + thisEntry ); | ||
| 224 | } | ||
| 225 | |||
| 226 | m_methodCalls.put( calledConstructorEntry, thisEntry ); | ||
| 167 | } | 227 | } |
| 168 | } ); | 228 | } ); |
| 169 | } | 229 | } |
| @@ -202,7 +262,9 @@ public class JarIndex | |||
| 202 | public ClassInheritanceTreeNode getClassInheritance( Translator deobfuscatingTranslator, ClassEntry obfClassEntry ) | 262 | public ClassInheritanceTreeNode getClassInheritance( Translator deobfuscatingTranslator, ClassEntry obfClassEntry ) |
| 203 | { | 263 | { |
| 204 | // get the root node | 264 | // get the root node |
| 205 | List<String> ancestry = m_ancestries.getAncestry( obfClassEntry.getName() ); | 265 | List<String> ancestry = Lists.newArrayList(); |
| 266 | ancestry.add( obfClassEntry.getName() ); | ||
| 267 | ancestry.addAll( m_ancestries.getAncestry( obfClassEntry.getName() ) ); | ||
| 206 | ClassInheritanceTreeNode rootNode = new ClassInheritanceTreeNode( deobfuscatingTranslator, ancestry.get( ancestry.size() - 1 ) ); | 268 | ClassInheritanceTreeNode rootNode = new ClassInheritanceTreeNode( deobfuscatingTranslator, ancestry.get( ancestry.size() - 1 ) ); |
| 207 | 269 | ||
| 208 | // expand all children recursively | 270 | // expand all children recursively |
| @@ -241,9 +303,14 @@ public class JarIndex | |||
| 241 | return rootNode; | 303 | return rootNode; |
| 242 | } | 304 | } |
| 243 | 305 | ||
| 244 | public Collection<MethodEntry> getMethodCallers( MethodEntry methodEntry ) | 306 | public Collection<Entry> getFieldCallers( FieldEntry fieldEntry ) |
| 307 | { | ||
| 308 | return m_fieldCalls.get( fieldEntry ); | ||
| 309 | } | ||
| 310 | |||
| 311 | public Collection<Entry> getMethodCallers( Entry entry ) | ||
| 245 | { | 312 | { |
| 246 | return m_methodCalls.get( methodEntry ); | 313 | return m_methodCalls.get( entry ); |
| 247 | } | 314 | } |
| 248 | 315 | ||
| 249 | private String getMethodKey( String name, String signature ) | 316 | private String getMethodKey( String name, String signature ) |
diff --git a/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java b/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java index dedfb2e..b5cf4c3 100644 --- a/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java +++ b/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java | |||
| @@ -10,12 +10,15 @@ | |||
| 10 | ******************************************************************************/ | 10 | ******************************************************************************/ |
| 11 | package cuchaz.enigma.analysis; | 11 | package cuchaz.enigma.analysis; |
| 12 | 12 | ||
| 13 | import java.util.List; | 13 | import java.util.Set; |
| 14 | 14 | ||
| 15 | import javax.swing.tree.DefaultMutableTreeNode; | 15 | import javax.swing.tree.DefaultMutableTreeNode; |
| 16 | import javax.swing.tree.TreeNode; | ||
| 16 | 17 | ||
| 17 | import com.google.common.collect.Lists; | 18 | import com.google.common.collect.Sets; |
| 18 | 19 | ||
| 20 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 21 | import cuchaz.enigma.mapping.Entry; | ||
| 19 | import cuchaz.enigma.mapping.MethodEntry; | 22 | import cuchaz.enigma.mapping.MethodEntry; |
| 20 | import cuchaz.enigma.mapping.Translator; | 23 | import cuchaz.enigma.mapping.Translator; |
| 21 | 24 | ||
| @@ -24,72 +27,117 @@ public class MethodCallsTreeNode extends DefaultMutableTreeNode | |||
| 24 | private static final long serialVersionUID = -3658163700783307520L; | 27 | private static final long serialVersionUID = -3658163700783307520L; |
| 25 | 28 | ||
| 26 | private Translator m_deobfuscatingTranslator; | 29 | private Translator m_deobfuscatingTranslator; |
| 27 | private MethodEntry m_entry; | 30 | private MethodEntry m_methodEntry; |
| 31 | private ConstructorEntry m_constructorEntry; | ||
| 28 | 32 | ||
| 29 | public MethodCallsTreeNode( Translator deobfuscatingTranslator, MethodEntry entry ) | 33 | public MethodCallsTreeNode( Translator deobfuscatingTranslator, MethodEntry entry ) |
| 30 | { | 34 | { |
| 31 | m_deobfuscatingTranslator = deobfuscatingTranslator; | 35 | m_deobfuscatingTranslator = deobfuscatingTranslator; |
| 32 | m_entry = entry; | 36 | m_methodEntry = entry; |
| 37 | m_constructorEntry = null; | ||
| 38 | } | ||
| 39 | |||
| 40 | public MethodCallsTreeNode( Translator deobfuscatingTranslator, ConstructorEntry entry ) | ||
| 41 | { | ||
| 42 | m_deobfuscatingTranslator = deobfuscatingTranslator; | ||
| 43 | m_methodEntry = null; | ||
| 44 | m_constructorEntry = entry; | ||
| 33 | } | 45 | } |
| 34 | 46 | ||
| 35 | public MethodEntry getMethodEntry( ) | 47 | public MethodEntry getMethodEntry( ) |
| 36 | { | 48 | { |
| 37 | return m_entry; | 49 | return m_methodEntry; |
| 38 | } | 50 | } |
| 39 | 51 | ||
| 40 | public String getDeobfClassName( ) | 52 | public ConstructorEntry getConstructorEntry( ) |
| 41 | { | 53 | { |
| 42 | return m_deobfuscatingTranslator.translateClass( m_entry.getClassName() ); | 54 | return m_constructorEntry; |
| 43 | } | 55 | } |
| 44 | 56 | ||
| 45 | public String getDeobfMethodName( ) | 57 | public Entry getEntry( ) |
| 46 | { | 58 | { |
| 47 | return m_deobfuscatingTranslator.translate( m_entry ); | 59 | if( m_methodEntry != null ) |
| 60 | { | ||
| 61 | return m_methodEntry; | ||
| 62 | } | ||
| 63 | else if( m_constructorEntry != null ) | ||
| 64 | { | ||
| 65 | return m_constructorEntry; | ||
| 66 | } | ||
| 67 | throw new Error( "Illegal state!" ); | ||
| 48 | } | 68 | } |
| 49 | 69 | ||
| 50 | @Override | 70 | @Override |
| 51 | public String toString( ) | 71 | public String toString( ) |
| 52 | { | 72 | { |
| 53 | String className = getDeobfClassName(); | 73 | if( m_methodEntry != null ) |
| 54 | if( className == null ) | ||
| 55 | { | 74 | { |
| 56 | className = m_entry.getClassName(); | 75 | String className = m_deobfuscatingTranslator.translateClass( m_methodEntry.getClassName() ); |
| 76 | if( className == null ) | ||
| 77 | { | ||
| 78 | className = m_methodEntry.getClassName(); | ||
| 79 | } | ||
| 80 | |||
| 81 | String methodName = m_deobfuscatingTranslator.translate( m_methodEntry ); | ||
| 82 | if( methodName == null ) | ||
| 83 | { | ||
| 84 | methodName = m_methodEntry.getName(); | ||
| 85 | } | ||
| 86 | return className + "." + methodName + "()"; | ||
| 57 | } | 87 | } |
| 58 | 88 | else if( m_constructorEntry != null ) | |
| 59 | String methodName = getDeobfMethodName(); | ||
| 60 | if( methodName == null ) | ||
| 61 | { | 89 | { |
| 62 | methodName = m_entry.getName(); | 90 | String className = m_deobfuscatingTranslator.translateClass( m_constructorEntry.getClassName() ); |
| 91 | if( className == null ) | ||
| 92 | { | ||
| 93 | className = m_constructorEntry.getClassName(); | ||
| 94 | } | ||
| 95 | return className + "()"; | ||
| 63 | } | 96 | } |
| 64 | return className + "." + methodName + "()"; | 97 | throw new Error( "Illegal state!" ); |
| 65 | } | 98 | } |
| 66 | 99 | ||
| 67 | public void load( JarIndex index, boolean recurse ) | 100 | public void load( JarIndex index, boolean recurse ) |
| 68 | { | 101 | { |
| 69 | // get all the child nodes | 102 | // get all the child nodes |
| 70 | List<MethodCallsTreeNode> nodes = Lists.newArrayList(); | 103 | for( Entry entry : index.getMethodCallers( getEntry() ) ) |
| 71 | for( MethodEntry entry : index.getMethodCallers( m_entry ) ) | ||
| 72 | { | 104 | { |
| 73 | nodes.add( new MethodCallsTreeNode( m_deobfuscatingTranslator, entry ) ); | 105 | if( entry instanceof MethodEntry ) |
| 74 | } | 106 | { |
| 75 | 107 | add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (MethodEntry)entry ) ); | |
| 76 | // add them to this node | 108 | } |
| 77 | for( MethodCallsTreeNode node : nodes ) | 109 | else if( entry instanceof ConstructorEntry ) |
| 78 | { | 110 | { |
| 79 | this.add( node ); | 111 | add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (ConstructorEntry)entry ) ); |
| 112 | } | ||
| 80 | } | 113 | } |
| 81 | 114 | ||
| 82 | if( recurse ) | 115 | if( recurse && children != null ) |
| 83 | { | 116 | { |
| 84 | for( MethodCallsTreeNode node : nodes ) | 117 | for( Object child : children ) |
| 85 | { | 118 | { |
| 86 | // don't recurse into self | 119 | if( child instanceof MethodCallsTreeNode ) |
| 87 | if( node.getMethodEntry().equals( m_entry ) ) | ||
| 88 | { | 120 | { |
| 89 | continue; | 121 | MethodCallsTreeNode node = (MethodCallsTreeNode)child; |
| 122 | |||
| 123 | // don't recurse into ancestor | ||
| 124 | Set<Entry> ancestors = Sets.newHashSet(); | ||
| 125 | TreeNode n = (TreeNode)node; | ||
| 126 | while( n.getParent() != null ) | ||
| 127 | { | ||
| 128 | n = n.getParent(); | ||
| 129 | if( n instanceof MethodCallsTreeNode ) | ||
| 130 | { | ||
| 131 | ancestors.add( ((MethodCallsTreeNode)n).getEntry() ); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | if( ancestors.contains( node.getEntry() ) ) | ||
| 135 | { | ||
| 136 | continue; | ||
| 137 | } | ||
| 138 | |||
| 139 | node.load( index, true ); | ||
| 90 | } | 140 | } |
| 91 | |||
| 92 | node.load( index, true ); | ||
| 93 | } | 141 | } |
| 94 | } | 142 | } |
| 95 | } | 143 | } |
diff --git a/src/cuchaz/enigma/analysis/SourceIndexVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexVisitor.java index 0ba5996..6c14ee9 100644 --- a/src/cuchaz/enigma/analysis/SourceIndexVisitor.java +++ b/src/cuchaz/enigma/analysis/SourceIndexVisitor.java | |||
| @@ -93,6 +93,7 @@ import com.strobel.decompiler.patterns.Pattern; | |||
| 93 | 93 | ||
| 94 | import cuchaz.enigma.mapping.ArgumentEntry; | 94 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 95 | import cuchaz.enigma.mapping.ClassEntry; | 95 | import cuchaz.enigma.mapping.ClassEntry; |
| 96 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 96 | import cuchaz.enigma.mapping.FieldEntry; | 97 | import cuchaz.enigma.mapping.FieldEntry; |
| 97 | import cuchaz.enigma.mapping.MethodEntry; | 98 | import cuchaz.enigma.mapping.MethodEntry; |
| 98 | 99 | ||
| @@ -158,7 +159,9 @@ public class SourceIndexVisitor implements IAstVisitor<SourceIndex, Void> | |||
| 158 | public Void visitConstructorDeclaration( ConstructorDeclaration node, SourceIndex index ) | 159 | public Void visitConstructorDeclaration( ConstructorDeclaration node, SourceIndex index ) |
| 159 | { | 160 | { |
| 160 | MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); | 161 | MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); |
| 161 | index.add( node.getNameToken(), new ClassEntry( def.getDeclaringType().getInternalName() ) ); | 162 | ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); |
| 163 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, def.getSignature() ); | ||
| 164 | index.addDeclaration( node.getNameToken(), constructorEntry ); | ||
| 162 | 165 | ||
| 163 | return recurse( node, index ); | 166 | return recurse( node, index ); |
| 164 | } | 167 | } |
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index 072fb3a..1d2d3ab 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -67,11 +67,13 @@ import com.google.common.collect.Lists; | |||
| 67 | 67 | ||
| 68 | import cuchaz.enigma.Constants; | 68 | import cuchaz.enigma.Constants; |
| 69 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; | 69 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; |
| 70 | import cuchaz.enigma.analysis.FieldCallsTreeNode; | ||
| 70 | import cuchaz.enigma.analysis.MethodCallsTreeNode; | 71 | import cuchaz.enigma.analysis.MethodCallsTreeNode; |
| 71 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; | 72 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; |
| 72 | import cuchaz.enigma.analysis.Token; | 73 | import cuchaz.enigma.analysis.Token; |
| 73 | import cuchaz.enigma.mapping.ArgumentEntry; | 74 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 74 | import cuchaz.enigma.mapping.ClassEntry; | 75 | import cuchaz.enigma.mapping.ClassEntry; |
| 76 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 75 | import cuchaz.enigma.mapping.Entry; | 77 | import cuchaz.enigma.mapping.Entry; |
| 76 | import cuchaz.enigma.mapping.EntryPair; | 78 | import cuchaz.enigma.mapping.EntryPair; |
| 77 | import cuchaz.enigma.mapping.FieldEntry; | 79 | import cuchaz.enigma.mapping.FieldEntry; |
| @@ -419,7 +421,7 @@ public class Gui | |||
| 419 | Object node = path.getLastPathComponent(); | 421 | Object node = path.getLastPathComponent(); |
| 420 | if( node instanceof MethodCallsTreeNode ) | 422 | if( node instanceof MethodCallsTreeNode ) |
| 421 | { | 423 | { |
| 422 | m_controller.openEntry( ((MethodCallsTreeNode)node).getMethodEntry() ); | 424 | m_controller.openEntry( ((MethodCallsTreeNode)node).getEntry() ); |
| 423 | } | 425 | } |
| 424 | } | 426 | } |
| 425 | } | 427 | } |
| @@ -438,7 +440,7 @@ public class Gui | |||
| 438 | m_tabs = new JTabbedPane(); | 440 | m_tabs = new JTabbedPane(); |
| 439 | m_tabs.setPreferredSize( new Dimension( 250, 0 ) ); | 441 | m_tabs.setPreferredSize( new Dimension( 250, 0 ) ); |
| 440 | m_tabs.addTab( "Inheritance", inheritancePanel ); | 442 | m_tabs.addTab( "Inheritance", inheritancePanel ); |
| 441 | m_tabs.addTab( "Method Calls", callPanel ); | 443 | m_tabs.addTab( "Call Graph", callPanel ); |
| 442 | JSplitPane splitRight = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs ); | 444 | JSplitPane splitRight = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs ); |
| 443 | splitRight.setResizeWeight( 1 ); // let the left side take all the slack | 445 | splitRight.setResizeWeight( 1 ); // let the left side take all the slack |
| 444 | splitRight.resetToPreferredSizes(); | 446 | splitRight.resetToPreferredSizes(); |
| @@ -770,6 +772,10 @@ public class Gui | |||
| 770 | { | 772 | { |
| 771 | showMethodEntryPair( (EntryPair<? extends MethodEntry>)pair ); | 773 | showMethodEntryPair( (EntryPair<? extends MethodEntry>)pair ); |
| 772 | } | 774 | } |
| 775 | else if( pair.deobf instanceof ConstructorEntry ) | ||
| 776 | { | ||
| 777 | showConstructorEntryPair( (EntryPair<? extends ConstructorEntry>)pair ); | ||
| 778 | } | ||
| 773 | else if( pair.deobf instanceof ArgumentEntry ) | 779 | else if( pair.deobf instanceof ArgumentEntry ) |
| 774 | { | 780 | { |
| 775 | showArgumentEntryPair( (EntryPair<? extends ArgumentEntry>)pair ); | 781 | showArgumentEntryPair( (EntryPair<? extends ArgumentEntry>)pair ); |
| @@ -800,6 +806,12 @@ public class Gui | |||
| 800 | addNameValue( m_infoPanel, "Signature", pair.deobf.getSignature() ); | 806 | addNameValue( m_infoPanel, "Signature", pair.deobf.getSignature() ); |
| 801 | } | 807 | } |
| 802 | 808 | ||
| 809 | private void showConstructorEntryPair( EntryPair<? extends ConstructorEntry> pair ) | ||
| 810 | { | ||
| 811 | addNameValue( m_infoPanel, "Constructor", pair.deobf.getClassEntry().getName() ); | ||
| 812 | addNameValue( m_infoPanel, "Signature", pair.deobf.getSignature() ); | ||
| 813 | } | ||
| 814 | |||
| 803 | private void showArgumentEntryPair( EntryPair<? extends ArgumentEntry> pair ) | 815 | private void showArgumentEntryPair( EntryPair<? extends ArgumentEntry> pair ) |
| 804 | { | 816 | { |
| 805 | addNameValue( m_infoPanel, "Argument", pair.deobf.getName() ); | 817 | addNameValue( m_infoPanel, "Argument", pair.deobf.getName() ); |
| @@ -815,7 +827,7 @@ public class Gui | |||
| 815 | container.add( panel ); | 827 | container.add( panel ); |
| 816 | 828 | ||
| 817 | JLabel label = new JLabel( name + ":", JLabel.RIGHT ); | 829 | JLabel label = new JLabel( name + ":", JLabel.RIGHT ); |
| 818 | label.setPreferredSize( new Dimension( 80, label.getPreferredSize().height ) ); | 830 | label.setPreferredSize( new Dimension( 100, label.getPreferredSize().height ) ); |
| 819 | panel.add( label ); | 831 | panel.add( label ); |
| 820 | 832 | ||
| 821 | panel.add( unboldLabel( new JLabel( value, JLabel.LEFT ) ) ); | 833 | panel.add( unboldLabel( new JLabel( value, JLabel.LEFT ) ) ); |
| @@ -824,23 +836,27 @@ public class Gui | |||
| 824 | private void onCaretMove( int pos ) | 836 | private void onCaretMove( int pos ) |
| 825 | { | 837 | { |
| 826 | Token token = m_controller.getToken( pos ); | 838 | Token token = m_controller.getToken( pos ); |
| 827 | m_renameMenu.setEnabled( token != null ); | 839 | boolean isToken = token != null; |
| 828 | if( token == null ) | ||
| 829 | { | ||
| 830 | clearEntryPair(); | ||
| 831 | return; | ||
| 832 | } | ||
| 833 | 840 | ||
| 834 | m_selectedEntryPair = m_controller.getEntryPair( token ); | 841 | m_selectedEntryPair = m_controller.getEntryPair( token ); |
| 835 | boolean isClassEntry = m_selectedEntryPair.obf instanceof ClassEntry; | 842 | boolean isClassEntry = isToken && m_selectedEntryPair.obf instanceof ClassEntry; |
| 836 | boolean isFieldEntry = m_selectedEntryPair.obf instanceof FieldEntry; | 843 | boolean isFieldEntry = isToken && m_selectedEntryPair.obf instanceof FieldEntry; |
| 837 | boolean isMethodEntry = m_selectedEntryPair.obf instanceof MethodEntry; | 844 | boolean isMethodEntry = isToken && m_selectedEntryPair.obf instanceof MethodEntry; |
| 845 | boolean isConstructorEntry = isToken && m_selectedEntryPair.obf instanceof ConstructorEntry; | ||
| 838 | 846 | ||
| 839 | showEntryPair( m_selectedEntryPair ); | 847 | if( isToken ) |
| 848 | { | ||
| 849 | showEntryPair( m_selectedEntryPair ); | ||
| 850 | } | ||
| 851 | else | ||
| 852 | { | ||
| 853 | clearEntryPair(); | ||
| 854 | } | ||
| 840 | 855 | ||
| 841 | m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry ); | 856 | m_renameMenu.setEnabled( isToken ); |
| 842 | m_showCallsMenu.setEnabled( isMethodEntry ); | 857 | m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry ); |
| 843 | m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry ); | 858 | m_showCallsMenu.setEnabled( isFieldEntry || isMethodEntry || isConstructorEntry ); |
| 859 | m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); | ||
| 844 | m_openPreviousMenu.setEnabled( m_controller.hasPreviousEntry() ); | 860 | m_openPreviousMenu.setEnabled( m_controller.hasPreviousEntry() ); |
| 845 | } | 861 | } |
| 846 | 862 | ||
| @@ -945,11 +961,21 @@ public class Gui | |||
| 945 | return; | 961 | return; |
| 946 | } | 962 | } |
| 947 | 963 | ||
| 948 | if( m_selectedEntryPair.obf instanceof MethodEntry ) | 964 | if( m_selectedEntryPair.obf instanceof FieldEntry ) |
| 965 | { | ||
| 966 | FieldCallsTreeNode node = m_controller.getFieldCalls( (FieldEntry)m_selectedEntryPair.obf ); | ||
| 967 | m_callsTree.setModel( new DefaultTreeModel( node ) ); | ||
| 968 | } | ||
| 969 | else if( m_selectedEntryPair.obf instanceof MethodEntry ) | ||
| 949 | { | 970 | { |
| 950 | MethodCallsTreeNode node = m_controller.getMethodCalls( (MethodEntry)m_selectedEntryPair.obf ); | 971 | MethodCallsTreeNode node = m_controller.getMethodCalls( (MethodEntry)m_selectedEntryPair.obf ); |
| 951 | m_callsTree.setModel( new DefaultTreeModel( node ) ); | 972 | m_callsTree.setModel( new DefaultTreeModel( node ) ); |
| 952 | } | 973 | } |
| 974 | else if( m_selectedEntryPair.obf instanceof ConstructorEntry ) | ||
| 975 | { | ||
| 976 | MethodCallsTreeNode node = m_controller.getMethodCalls( (ConstructorEntry)m_selectedEntryPair.obf ); | ||
| 977 | m_callsTree.setModel( new DefaultTreeModel( node ) ); | ||
| 978 | } | ||
| 953 | 979 | ||
| 954 | m_tabs.setSelectedIndex( 1 ); | 980 | m_tabs.setSelectedIndex( 1 ); |
| 955 | redraw(); | 981 | redraw(); |
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index b54aeba..534b0cc 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -21,13 +21,16 @@ import com.google.common.collect.Lists; | |||
| 21 | 21 | ||
| 22 | import cuchaz.enigma.Deobfuscator; | 22 | import cuchaz.enigma.Deobfuscator; |
| 23 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; | 23 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; |
| 24 | import cuchaz.enigma.analysis.FieldCallsTreeNode; | ||
| 24 | import cuchaz.enigma.analysis.MethodCallsTreeNode; | 25 | import cuchaz.enigma.analysis.MethodCallsTreeNode; |
| 25 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; | 26 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; |
| 26 | import cuchaz.enigma.analysis.SourceIndex; | 27 | import cuchaz.enigma.analysis.SourceIndex; |
| 27 | import cuchaz.enigma.analysis.Token; | 28 | import cuchaz.enigma.analysis.Token; |
| 28 | import cuchaz.enigma.mapping.ClassEntry; | 29 | import cuchaz.enigma.mapping.ClassEntry; |
| 30 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 29 | import cuchaz.enigma.mapping.Entry; | 31 | import cuchaz.enigma.mapping.Entry; |
| 30 | import cuchaz.enigma.mapping.EntryPair; | 32 | import cuchaz.enigma.mapping.EntryPair; |
| 33 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 31 | import cuchaz.enigma.mapping.MappingsReader; | 34 | import cuchaz.enigma.mapping.MappingsReader; |
| 32 | import cuchaz.enigma.mapping.MappingsWriter; | 35 | import cuchaz.enigma.mapping.MappingsWriter; |
| 33 | import cuchaz.enigma.mapping.MethodEntry; | 36 | import cuchaz.enigma.mapping.MethodEntry; |
| @@ -118,6 +121,10 @@ public class GuiController | |||
| 118 | } | 121 | } |
| 119 | 122 | ||
| 120 | Entry deobfEntry = m_index.getEntry( token ); | 123 | Entry deobfEntry = m_index.getEntry( token ); |
| 124 | if( deobfEntry == null ) | ||
| 125 | { | ||
| 126 | return null; | ||
| 127 | } | ||
| 121 | return new EntryPair<Entry>( m_deobfuscator.obfuscateEntry( deobfEntry ), deobfEntry ); | 128 | return new EntryPair<Entry>( m_deobfuscator.obfuscateEntry( deobfEntry ), deobfEntry ); |
| 122 | } | 129 | } |
| 123 | 130 | ||
| @@ -149,16 +156,41 @@ public class GuiController | |||
| 149 | return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); | 156 | return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); |
| 150 | } | 157 | } |
| 151 | 158 | ||
| 152 | public MethodCallsTreeNode getMethodCalls( MethodEntry obfMethodEntry ) | 159 | public FieldCallsTreeNode getFieldCalls( FieldEntry obfFieldEntry ) |
| 153 | { | 160 | { |
| 154 | MethodCallsTreeNode rootNode = new MethodCallsTreeNode( | 161 | FieldCallsTreeNode rootNode = new FieldCallsTreeNode( |
| 155 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | 162 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), |
| 156 | obfMethodEntry | 163 | obfFieldEntry |
| 157 | ); | 164 | ); |
| 158 | rootNode.load( m_deobfuscator.getJarIndex(), true ); | 165 | rootNode.load( m_deobfuscator.getJarIndex(), true ); |
| 159 | return rootNode; | 166 | return rootNode; |
| 160 | } | 167 | } |
| 161 | 168 | ||
| 169 | public MethodCallsTreeNode getMethodCalls( Entry obfEntry ) | ||
| 170 | { | ||
| 171 | MethodCallsTreeNode rootNode; | ||
| 172 | if( obfEntry instanceof MethodEntry ) | ||
| 173 | { | ||
| 174 | rootNode = new MethodCallsTreeNode( | ||
| 175 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | ||
| 176 | (MethodEntry)obfEntry | ||
| 177 | ); | ||
| 178 | } | ||
| 179 | else if( obfEntry instanceof ConstructorEntry ) | ||
| 180 | { | ||
| 181 | rootNode = new MethodCallsTreeNode( | ||
| 182 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | ||
| 183 | (ConstructorEntry)obfEntry | ||
| 184 | ); | ||
| 185 | } | ||
| 186 | else | ||
| 187 | { | ||
| 188 | throw new IllegalArgumentException( "entry must be a MethodEntry or a ConstructorEntry!" ); | ||
| 189 | } | ||
| 190 | rootNode.load( m_deobfuscator.getJarIndex(), true ); | ||
| 191 | return rootNode; | ||
| 192 | } | ||
| 193 | |||
| 162 | public void rename( Entry obfEntry, String newName ) | 194 | public void rename( Entry obfEntry, String newName ) |
| 163 | { | 195 | { |
| 164 | m_deobfuscator.rename( obfEntry, newName ); | 196 | m_deobfuscator.rename( obfEntry, newName ); |
diff --git a/src/cuchaz/enigma/mapping/ConstructorEntry.java b/src/cuchaz/enigma/mapping/ConstructorEntry.java new file mode 100644 index 0000000..e0fa7cf --- /dev/null +++ b/src/cuchaz/enigma/mapping/ConstructorEntry.java | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.mapping; | ||
| 12 | |||
| 13 | import java.io.Serializable; | ||
| 14 | |||
| 15 | import cuchaz.enigma.Util; | ||
| 16 | |||
| 17 | public class ConstructorEntry implements Entry, Serializable | ||
| 18 | { | ||
| 19 | private static final long serialVersionUID = -868346075317366758L; | ||
| 20 | |||
| 21 | private ClassEntry m_classEntry; | ||
| 22 | private String m_signature; | ||
| 23 | |||
| 24 | public ConstructorEntry( ClassEntry classEntry, String signature ) | ||
| 25 | { | ||
| 26 | if( classEntry == null ) | ||
| 27 | { | ||
| 28 | throw new IllegalArgumentException( "Class cannot be null!" ); | ||
| 29 | } | ||
| 30 | if( signature == null ) | ||
| 31 | { | ||
| 32 | throw new IllegalArgumentException( "Method signature cannot be null!" ); | ||
| 33 | } | ||
| 34 | |||
| 35 | m_classEntry = classEntry; | ||
| 36 | m_signature = signature; | ||
| 37 | } | ||
| 38 | |||
| 39 | public ConstructorEntry( ConstructorEntry other ) | ||
| 40 | { | ||
| 41 | m_classEntry = new ClassEntry( other.m_classEntry ); | ||
| 42 | m_signature = other.m_signature; | ||
| 43 | } | ||
| 44 | |||
| 45 | @Override | ||
| 46 | public ClassEntry getClassEntry( ) | ||
| 47 | { | ||
| 48 | return m_classEntry; | ||
| 49 | } | ||
| 50 | |||
| 51 | @Override | ||
| 52 | public String getName( ) | ||
| 53 | { | ||
| 54 | return m_classEntry.getName(); | ||
| 55 | } | ||
| 56 | |||
| 57 | public String getSignature( ) | ||
| 58 | { | ||
| 59 | return m_signature; | ||
| 60 | } | ||
| 61 | |||
| 62 | @Override | ||
| 63 | public String getClassName( ) | ||
| 64 | { | ||
| 65 | return m_classEntry.getName(); | ||
| 66 | } | ||
| 67 | |||
| 68 | @Override | ||
| 69 | public int hashCode( ) | ||
| 70 | { | ||
| 71 | return Util.combineHashesOrdered( m_classEntry, m_signature ); | ||
| 72 | } | ||
| 73 | |||
| 74 | @Override | ||
| 75 | public boolean equals( Object other ) | ||
| 76 | { | ||
| 77 | if( other instanceof ConstructorEntry ) | ||
| 78 | { | ||
| 79 | return equals( (ConstructorEntry)other ); | ||
| 80 | } | ||
| 81 | return false; | ||
| 82 | } | ||
| 83 | |||
| 84 | public boolean equals( ConstructorEntry other ) | ||
| 85 | { | ||
| 86 | return m_classEntry.equals( other.m_classEntry ) && m_signature.equals( other.m_signature ); | ||
| 87 | } | ||
| 88 | |||
| 89 | @Override | ||
| 90 | public String toString( ) | ||
| 91 | { | ||
| 92 | return m_classEntry.getName() + m_signature; | ||
| 93 | } | ||
| 94 | } | ||
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java index 02565c9..5043321 100644 --- a/src/cuchaz/enigma/mapping/Translator.java +++ b/src/cuchaz/enigma/mapping/Translator.java | |||
| @@ -135,6 +135,14 @@ public class Translator | |||
| 135 | ); | 135 | ); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | public ConstructorEntry translateEntry( ConstructorEntry in ) | ||
| 139 | { | ||
| 140 | return new ConstructorEntry( | ||
| 141 | translateEntry( in.getClassEntry() ), | ||
| 142 | translateSignature( in.getSignature() ) | ||
| 143 | ); | ||
| 144 | } | ||
| 145 | |||
| 138 | public String translate( ArgumentEntry in ) | 146 | public String translate( ArgumentEntry in ) |
| 139 | { | 147 | { |
| 140 | for( String className : getSelfAndAncestors( in.getClassName() ) ) | 148 | for( String className : getSelfAndAncestors( in.getClassName() ) ) |