From 237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375 Mon Sep 17 00:00:00 2001 From: jeff Date: Thu, 21 Aug 2014 01:10:37 -0400 Subject: fixed call graph searching added system to navigate multiple tokens for the same entry in a behavior --- src/cuchaz/enigma/Deobfuscator.java | 18 +++--- src/cuchaz/enigma/analysis/EntryReference.java | 13 ++-- src/cuchaz/enigma/analysis/JarIndex.java | 30 ++++----- src/cuchaz/enigma/analysis/SourceIndex.java | 37 +++++++++-- .../analysis/SourceIndexBehaviorVisitor.java | 16 ++--- .../enigma/analysis/SourceIndexClassVisitor.java | 23 ++++--- src/cuchaz/enigma/gui/Gui.java | 53 +++++++++++---- src/cuchaz/enigma/gui/GuiController.java | 75 ++++++++++++++-------- src/cuchaz/enigma/gui/ReadableToken.java | 38 +++++++++++ src/cuchaz/enigma/gui/TokenListCellRenderer.java | 40 ++++++++++++ src/cuchaz/enigma/mapping/ConstructorEntry.java | 54 +++++++++++++--- src/cuchaz/enigma/mapping/Translator.java | 28 +++++--- 12 files changed, 302 insertions(+), 123 deletions(-) create mode 100644 src/cuchaz/enigma/gui/ReadableToken.java create mode 100644 src/cuchaz/enigma/gui/TokenListCellRenderer.java diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 34e6033..a5feaa9 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java @@ -181,7 +181,7 @@ public class Deobfuscator return index; } - public Entry obfuscateEntry( Entry deobfEntry ) + public T obfuscateEntry( T deobfEntry ) { if( deobfEntry == null ) { @@ -190,7 +190,7 @@ public class Deobfuscator return getTranslator( TranslationDirection.Obfuscating ).translateEntry( deobfEntry ); } - public Entry deobfuscateEntry( Entry obfEntry ) + public T deobfuscateEntry( T obfEntry ) { if( obfEntry == null ) { @@ -199,29 +199,27 @@ public class Deobfuscator return getTranslator( TranslationDirection.Deobfuscating ).translateEntry( obfEntry ); } - public EntryReference obfuscateReference( EntryReference deobfReference ) + public EntryReference obfuscateReference( EntryReference deobfReference ) { if( deobfReference == null ) { return null; } - return new EntryReference( + return new EntryReference( obfuscateEntry( deobfReference.entry ), - obfuscateEntry( deobfReference.context ), - deobfReference.pos + obfuscateEntry( deobfReference.context ) ); } - public EntryReference deobfuscateReference( EntryReference obfReference ) + public EntryReference deobfuscateReference( EntryReference obfReference ) { if( obfReference == null ) { return null; } - return new EntryReference( + return new EntryReference( deobfuscateEntry( obfReference.entry ), - deobfuscateEntry( obfReference.context ), - obfReference.pos + deobfuscateEntry( obfReference.context ) ); } diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java index 869e08c..768c113 100644 --- a/src/cuchaz/enigma/analysis/EntryReference.java +++ b/src/cuchaz/enigma/analysis/EntryReference.java @@ -18,14 +18,13 @@ public class EntryReference { public E entry; public C context; - public int pos; public EntryReference( E entry ) { - this( entry, null, -1 ); + this( entry, null ); } - public EntryReference( E entry, C context, int pos ) + public EntryReference( E entry, C context ) { if( entry == null ) { @@ -34,7 +33,6 @@ public class EntryReference this.entry = entry; this.context = context; - this.pos = pos; } public ClassEntry getClassEntry( ) @@ -51,7 +49,7 @@ public class EntryReference { if( context != null ) { - return Util.combineHashesOrdered( entry.hashCode(), context.hashCode(), Integer.valueOf( pos ).hashCode() ); + return Util.combineHashesOrdered( entry.hashCode(), context.hashCode() ); } return entry.hashCode(); } @@ -82,7 +80,7 @@ public class EntryReference } else if( context != null && other.context != null ) { - return context.equals( other.context ) && pos == other.pos; + return context.equals( other.context ); } return false; } @@ -96,9 +94,6 @@ public class EntryReference { buf.append( " called from " ); buf.append( context ); - buf.append( " (" ); - buf.append( pos ); - buf.append( ")" ); } return buf.toString(); } diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index f408d93..315a286 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java @@ -146,10 +146,15 @@ public class JarIndex } else if( behavior instanceof CtConstructor ) { - thisEntry = new ConstructorEntry( - new ClassEntry( className ), - behavior.getSignature() - ); + boolean isStatic = behavior.getName().equals( "" ); + if( isStatic ) + { + thisEntry = new ConstructorEntry( new ClassEntry( className ) ); + } + else + { + thisEntry = new ConstructorEntry( new ClassEntry( className ), behavior.getSignature() ); + } } else { @@ -159,7 +164,6 @@ public class JarIndex // index method calls try { - final Multiset callNumbers = HashMultiset.create(); behavior.instrument( new ExprEditor( ) { @Override @@ -171,11 +175,9 @@ public class JarIndex call.getMethodName(), call.getSignature() ); - callNumbers.add( calledMethodEntry ); EntryReference reference = new EntryReference( calledMethodEntry, - thisEntry, - callNumbers.count( calledMethodEntry ) - 1 + thisEntry ); m_behaviorReferences.put( calledMethodEntry, reference ); } @@ -188,11 +190,9 @@ public class JarIndex new ClassEntry( className ), call.getFieldName() ); - callNumbers.add( calledFieldEntry ); EntryReference reference = new EntryReference( calledFieldEntry, - thisEntry, - callNumbers.count( calledFieldEntry ) - 1 + thisEntry ); m_fieldReferences.put( calledFieldEntry, reference ); } @@ -208,11 +208,9 @@ public class JarIndex new ClassEntry( className ), call.getSignature() ); - callNumbers.add( calledConstructorEntry ); EntryReference reference = new EntryReference( calledConstructorEntry, - thisEntry, - callNumbers.count( calledConstructorEntry ) - 1 + thisEntry ); m_behaviorReferences.put( calledConstructorEntry, reference ); } @@ -225,11 +223,9 @@ public class JarIndex new ClassEntry( className ), call.getSignature() ); - callNumbers.add( calledConstructorEntry ); EntryReference reference = new EntryReference( calledConstructorEntry, - thisEntry, - callNumbers.count( calledConstructorEntry ) - 1 + thisEntry ); m_behaviorReferences.put( calledConstructorEntry, reference ); } diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java index bf890e3..960ec36 100644 --- a/src/cuchaz/enigma/analysis/SourceIndex.java +++ b/src/cuchaz/enigma/analysis/SourceIndex.java @@ -10,13 +10,15 @@ ******************************************************************************/ package cuchaz.enigma.analysis; -import java.util.HashMap; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.TreeMap; +import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.strobel.decompiler.languages.Region; import com.strobel.decompiler.languages.java.ast.Identifier; @@ -26,7 +28,7 @@ public class SourceIndex { private String m_source; private TreeMap> m_tokenToReference; - private HashMap,Token> m_referenceToToken; + private Multimap,Token> m_referenceToTokens; private Map m_declarationToToken; private List m_lineOffsets; @@ -34,7 +36,7 @@ public class SourceIndex { m_source = source; m_tokenToReference = Maps.newTreeMap(); - m_referenceToToken = Maps.newHashMap(); + m_referenceToTokens = HashMultimap.create(); m_declarationToToken = Maps.newHashMap(); m_lineOffsets = Lists.newArrayList(); @@ -96,7 +98,7 @@ public class SourceIndex if( token != null ) { m_tokenToReference.put( token, deobfReference ); - m_referenceToToken.put( deobfReference, token ); + m_referenceToTokens.put( deobfReference, token ); } } @@ -107,7 +109,7 @@ public class SourceIndex { EntryReference reference = new EntryReference( deobfEntry ); m_tokenToReference.put( token, reference ); - m_referenceToToken.put( reference, token ); + m_referenceToTokens.put( reference, token ); m_declarationToToken.put( deobfEntry, token ); } } @@ -122,9 +124,9 @@ public class SourceIndex return null; } - public Token getReferenceToken( EntryReference deobfReference ) + public Collection getReferenceTokens( EntryReference deobfReference ) { - return m_referenceToToken.get( deobfReference ); + return m_referenceToTokens.get( deobfReference ); } public EntryReference getDeobfReference( Token token ) @@ -151,6 +153,27 @@ public class SourceIndex return m_declarationToToken.get( deobfEntry ); } + public int getLineNumber( int pos ) + { + // line number is 1-based + int line = 0; + for( Integer offset : m_lineOffsets ) + { + if( offset > pos ) + { + break; + } + line++; + } + return line; + } + + public int getColumnNumber( int pos ) + { + // column number is 1-based + return pos - m_lineOffsets.get( getLineNumber( pos ) - 1 ) + 1; + } + private int toPos( int line, int col ) { // line and col are 1-based diff --git a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java index d3386c5..a943858 100644 --- a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java +++ b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java @@ -10,8 +10,6 @@ ******************************************************************************/ package cuchaz.enigma.analysis; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.Multiset; import com.strobel.assembler.metadata.MemberReference; import com.strobel.assembler.metadata.MethodDefinition; import com.strobel.assembler.metadata.ParameterDefinition; @@ -36,12 +34,10 @@ import cuchaz.enigma.mapping.MethodEntry; public class SourceIndexBehaviorVisitor extends SourceIndexVisitor { private BehaviorEntry m_behaviorEntry; - private Multiset m_indices; public SourceIndexBehaviorVisitor( BehaviorEntry behaviorEntry ) { m_behaviorEntry = behaviorEntry; - m_indices = HashMultiset.create(); } @Override @@ -64,10 +60,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor MethodEntry methodEntry = new MethodEntry( classEntry, ref.getName(), ref.getSignature() ); if( node.getTarget() instanceof MemberReferenceExpression ) { - m_indices.add( methodEntry ); index.addReference( ((MemberReferenceExpression)node.getTarget()).getMemberNameToken(), - new EntryReference( methodEntry, m_behaviorEntry, m_indices.count( methodEntry ) ) + new EntryReference( methodEntry, m_behaviorEntry ) ); } @@ -82,10 +77,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor { ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); - m_indices.add( fieldEntry ); index.addReference( node.getMemberNameToken(), - new EntryReference( fieldEntry, m_behaviorEntry, m_indices.count( fieldEntry ) ) + new EntryReference( fieldEntry, m_behaviorEntry ) ); } @@ -99,10 +93,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY ) { ClassEntry classEntry = new ClassEntry( ref.getInternalName() ); - m_indices.add( classEntry ); index.addReference( node.getIdentifierToken(), - new EntryReference( classEntry, m_behaviorEntry, m_indices.count( classEntry ) ) + new EntryReference( classEntry, m_behaviorEntry ) ); } @@ -130,10 +123,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor { ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); - m_indices.add( fieldEntry ); index.addReference( node.getIdentifierToken(), - new EntryReference( fieldEntry, m_behaviorEntry, m_indices.count( fieldEntry ) ) + new EntryReference( fieldEntry, m_behaviorEntry ) ); } diff --git a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java index 5257088..a1c8271 100644 --- a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java +++ b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java @@ -10,8 +10,6 @@ ******************************************************************************/ package cuchaz.enigma.analysis; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.Multiset; import com.strobel.assembler.metadata.FieldDefinition; import com.strobel.assembler.metadata.MethodDefinition; import com.strobel.assembler.metadata.TypeDefinition; @@ -26,6 +24,7 @@ import com.strobel.decompiler.languages.java.ast.SimpleType; import com.strobel.decompiler.languages.java.ast.TypeDeclaration; import com.strobel.decompiler.languages.java.ast.VariableInitializer; +import cuchaz.enigma.mapping.BehaviorEntry; import cuchaz.enigma.mapping.ClassEntry; import cuchaz.enigma.mapping.ConstructorEntry; import cuchaz.enigma.mapping.Entry; @@ -35,12 +34,10 @@ import cuchaz.enigma.mapping.MethodEntry; public class SourceIndexClassVisitor extends SourceIndexVisitor { private ClassEntry m_classEntry; - private Multiset m_indices; public SourceIndexClassVisitor( ClassEntry classEntry ) { m_classEntry = classEntry; - m_indices = HashMultiset.create(); } @Override @@ -68,7 +65,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor ClassEntry classEntry = new ClassEntry( ref.getInternalName() ); index.addReference( node.getIdentifierToken(), - new EntryReference( classEntry, m_classEntry, m_indices.count( classEntry ) ) + new EntryReference( classEntry, m_classEntry ) ); } @@ -80,11 +77,17 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor { MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); - MethodEntry methodEntry = new MethodEntry( classEntry, def.getName(), def.getSignature() ); - index.addDeclaration( node.getNameToken(), methodEntry ); - //if( !def.getName().equals( "" ) ) - - return node.acceptVisitor( new SourceIndexBehaviorVisitor( methodEntry ), index ); + BehaviorEntry behaviorEntry; + if( def.getName().equals( "" ) ) + { + behaviorEntry = new ConstructorEntry( classEntry ); + } + else + { + behaviorEntry = new MethodEntry( classEntry, def.getName(), def.getSignature() ); + } + index.addDeclaration( node.getNameToken(), behaviorEntry ); + return node.acceptVisitor( new SourceIndexBehaviorVisitor( behaviorEntry ), index ); } @Override diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index 341c149..a5471a7 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java @@ -28,6 +28,7 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -145,6 +146,7 @@ public class Gui private BoxHighlightPainter m_deobfuscatedHighlightPainter; private JTree m_inheritanceTree; private JTree m_callsTree; + private JList m_tokens; private JTabbedPane m_tabs; // dynamic menu items @@ -457,9 +459,29 @@ public class Gui } } } ); - JPanel callPanel = new JPanel(); - callPanel.setLayout( new BorderLayout() ); - callPanel.add( new JScrollPane( m_callsTree ) ); + m_tokens = new JList(); + m_tokens.setCellRenderer( new TokenListCellRenderer( m_controller ) ); + m_tokens.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); + m_tokens.setLayoutOrientation( JList.VERTICAL ); + m_tokens.addMouseListener( new MouseAdapter() + { + @Override + public void mouseClicked( MouseEvent event ) + { + if( event.getClickCount() == 2 ) + { + Token selected = m_tokens.getSelectedValue(); + if( selected != null ) + { + showToken( selected ); + } + } + } + } ); + m_tokens.setPreferredSize( new Dimension( 0, 200 ) ); + JSplitPane callPanel = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, new JScrollPane( m_callsTree ), new JScrollPane( m_tokens ) ); + callPanel.setResizeWeight( 1 ); // let the top side take all the slack + callPanel.resetToPreferredSizes(); // layout controls JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel ); @@ -743,6 +765,21 @@ public class Gui m_editor.grabFocus(); } + public void showTokens( Collection tokens ) + { + Vector sortedTokens = new Vector( tokens ); + Collections.sort( sortedTokens ); + if( sortedTokens.size() > 1 ) + { + // sort the tokens and update the tokens panel + m_tokens.setListData( sortedTokens ); + m_tokens.setSelectedIndex( 0 ); + } + + // show the first token + showToken( sortedTokens.get( 0 ) ); + } + public void setHighlightedTokens( Iterable obfuscatedTokens, Iterable deobfuscatedTokens ) { // remove any old highlighters @@ -900,17 +937,9 @@ public class Gui private void startRename( ) { - // get the class name - ClassEntry classEntry = m_reference.entry.getClassEntry(); - String className = classEntry.getName(); - if( classEntry.isInnerClass() ) - { - className = classEntry.getInnerClassName(); - } - // init the text box final JTextField text = new JTextField(); - text.setText( className ); + text.setText( m_reference.entry.getName() ); text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) ); text.addKeyListener( new KeyAdapter( ) { diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index dfa2557..a35db05 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.util.Collection; import java.util.Deque; import java.util.List; @@ -45,7 +46,7 @@ public class GuiController private SourceIndex m_index; private ClassEntry m_currentObfClass; private boolean m_isDirty; - private Deque> m_referenceStack; // TODO: make a location class, can be either Entry or EntryReference + private Deque> m_referenceStack; public GuiController( Gui gui ) { @@ -111,7 +112,6 @@ public class GuiController { return null; } - return m_index.getReferenceToken( pos ); } @@ -124,6 +124,19 @@ public class GuiController return m_index.getDeobfReference( token ); } + public ReadableToken getReadableToken( Token token ) + { + if( m_index == null ) + { + return null; + } + return new ReadableToken( + m_index.getLineNumber( token.start ), + m_index.getColumnNumber( token.start ), + m_index.getColumnNumber( token.end ) + ); + } + public boolean entryHasMapping( Entry deobfEntry ) { return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); @@ -134,8 +147,9 @@ public class GuiController return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); } - public ClassInheritanceTreeNode getClassInheritance( ClassEntry obfClassEntry ) + public ClassInheritanceTreeNode getClassInheritance( ClassEntry deobfClassEntry ) { + ClassEntry obfClassEntry = m_deobfuscator.obfuscateEntry( deobfClassEntry ); ClassInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getClassInheritance( m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), obfClassEntry @@ -143,8 +157,9 @@ public class GuiController return ClassInheritanceTreeNode.findNode( rootNode, obfClassEntry ); } - public MethodInheritanceTreeNode getMethodInheritance( MethodEntry obfMethodEntry ) + public MethodInheritanceTreeNode getMethodInheritance( MethodEntry deobfMethodEntry ) { + MethodEntry obfMethodEntry = m_deobfuscator.obfuscateEntry( deobfMethodEntry ); MethodInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getMethodInheritance( m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), obfMethodEntry @@ -152,8 +167,9 @@ public class GuiController return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); } - public FieldReferenceTreeNode getFieldReferences( FieldEntry obfFieldEntry ) + public FieldReferenceTreeNode getFieldReferences( FieldEntry deobfFieldEntry ) { + FieldEntry obfFieldEntry = m_deobfuscator.obfuscateEntry( deobfFieldEntry ); FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode( m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), obfFieldEntry @@ -162,11 +178,12 @@ public class GuiController return rootNode; } - public BehaviorReferenceTreeNode getMethodReferences( BehaviorEntry obfEntry ) + public BehaviorReferenceTreeNode getMethodReferences( BehaviorEntry deobfBehaviorEntry ) { + BehaviorEntry obfBehaviorEntry = m_deobfuscator.obfuscateEntry( deobfBehaviorEntry ); BehaviorReferenceTreeNode rootNode = new BehaviorReferenceTreeNode( m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), - obfEntry + obfBehaviorEntry ); rootNode.load( m_deobfuscator.getJarIndex(), true ); return rootNode; @@ -181,13 +198,13 @@ public class GuiController refreshCurrentClass( obfReference ); } - public void openDeclaration( Entry entry ) + public void openDeclaration( Entry deobfEntry ) { - if( entry == null ) + if( deobfEntry == null ) { throw new IllegalArgumentException( "Entry cannot be null!" ); } - openReference( new EntryReference( entry ) ); + openReference( new EntryReference( deobfEntry ) ); } public void openReference( EntryReference deobfReference ) @@ -208,8 +225,22 @@ public class GuiController } else { - // the class file is already open, just navigate to the reference - m_gui.showToken( m_index.getReferenceToken( deobfReference ) ); + showReference( obfReference ); + } + } + + private void showReference( EntryReference obfReference ) + { + EntryReference deobfReference = m_deobfuscator.deobfuscateReference( obfReference ); + Collection tokens = m_index.getReferenceTokens( deobfReference ); + if( tokens.isEmpty() ) + { + // DEBUG + System.err.println( String.format( "WARNING: no tokens found for %s in %s", deobfReference, m_currentObfClass ) ); + } + else + { + m_gui.showTokens( tokens ); } } @@ -245,15 +276,15 @@ public class GuiController refreshCurrentClass( null ); } - private void refreshCurrentClass( EntryReference obfReferenceToShow ) + private void refreshCurrentClass( EntryReference obfReference ) { if( m_currentObfClass != null ) { - deobfuscate( m_currentObfClass, obfReferenceToShow ); + deobfuscate( m_currentObfClass, obfReference ); } } - private void deobfuscate( final ClassEntry classEntry, final EntryReference obfReferenceToShow ) + private void deobfuscate( final ClassEntry classEntry, final EntryReference obfReference ) { m_gui.setSource( "(deobfuscating...)" ); @@ -266,19 +297,9 @@ public class GuiController // decompile,deobfuscate the bytecode m_index = m_deobfuscator.getSource( classEntry.getClassName() ); m_gui.setSource( m_index.getSource() ); - if( obfReferenceToShow != null ) + if( obfReference != null ) { - EntryReference deobfReferenceToShow = m_deobfuscator.deobfuscateReference( obfReferenceToShow ); - Token token = m_index.getReferenceToken( deobfReferenceToShow ); - if( token == null ) - { - // DEBUG - System.out.println( "WARNING: can't find token for " + obfReferenceToShow + " -> " + deobfReferenceToShow ); - } - else - { - m_gui.showToken( token ); - } + showReference( obfReference ); } // set the highlighted tokens diff --git a/src/cuchaz/enigma/gui/ReadableToken.java b/src/cuchaz/enigma/gui/ReadableToken.java new file mode 100644 index 0000000..3f43045 --- /dev/null +++ b/src/cuchaz/enigma/gui/ReadableToken.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.gui; + +public class ReadableToken +{ + public int line; + public int startColumn; + public int endColumn; + + public ReadableToken( int line, int startColumn, int endColumn ) + { + this.line = line; + this.startColumn = startColumn; + this.endColumn = endColumn; + } + + @Override + public String toString( ) + { + StringBuilder buf = new StringBuilder(); + buf.append( "line " ); + buf.append( line ); + buf.append( " columns " ); + buf.append( startColumn ); + buf.append( "-" ); + buf.append( endColumn ); + return buf.toString(); + } +} diff --git a/src/cuchaz/enigma/gui/TokenListCellRenderer.java b/src/cuchaz/enigma/gui/TokenListCellRenderer.java new file mode 100644 index 0000000..9247c06 --- /dev/null +++ b/src/cuchaz/enigma/gui/TokenListCellRenderer.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.gui; + +import java.awt.Component; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; + +import cuchaz.enigma.analysis.Token; + +public class TokenListCellRenderer implements ListCellRenderer +{ + private GuiController m_controller; + private DefaultListCellRenderer m_defaultRenderer; + + public TokenListCellRenderer( GuiController controller ) + { + m_controller = controller; + m_defaultRenderer = new DefaultListCellRenderer(); + } + + @Override + public Component getListCellRendererComponent( JList list, Token token, int index, boolean isSelected, boolean hasFocus ) + { + JLabel label = (JLabel)m_defaultRenderer.getListCellRendererComponent( list, token, index, isSelected, hasFocus ); + label.setText( m_controller.getReadableToken( token ).toString() ); + return label; + } +} diff --git a/src/cuchaz/enigma/mapping/ConstructorEntry.java b/src/cuchaz/enigma/mapping/ConstructorEntry.java index 0f7dab6..ad029e1 100644 --- a/src/cuchaz/enigma/mapping/ConstructorEntry.java +++ b/src/cuchaz/enigma/mapping/ConstructorEntry.java @@ -21,16 +21,17 @@ public class ConstructorEntry implements BehaviorEntry, Serializable private ClassEntry m_classEntry; private String m_signature; + public ConstructorEntry( ClassEntry classEntry ) + { + this( classEntry, null ); + } + public ConstructorEntry( ClassEntry classEntry, String signature ) { if( classEntry == null ) { throw new IllegalArgumentException( "Class cannot be null!" ); } - if( signature == null ) - { - throw new IllegalArgumentException( "Method signature cannot be null!" ); - } m_classEntry = classEntry; m_signature = signature; @@ -47,11 +48,20 @@ public class ConstructorEntry implements BehaviorEntry, Serializable { return m_classEntry; } - + @Override public String getName( ) { - return m_classEntry.getName(); + if( isStatic() ) + { + return ""; + } + return ""; + } + + public boolean isStatic( ) + { + return m_signature == null; } @Override @@ -69,7 +79,14 @@ public class ConstructorEntry implements BehaviorEntry, Serializable @Override public int hashCode( ) { - return Util.combineHashesOrdered( m_classEntry, m_signature ); + if( isStatic() ) + { + return Util.combineHashesOrdered( m_classEntry ); + } + else + { + return Util.combineHashesOrdered( m_classEntry, m_signature ); + } } @Override @@ -84,12 +101,31 @@ public class ConstructorEntry implements BehaviorEntry, Serializable public boolean equals( ConstructorEntry other ) { - return m_classEntry.equals( other.m_classEntry ) && m_signature.equals( other.m_signature ); + if( isStatic() != other.isStatic() ) + { + return false; + } + + if( isStatic() ) + { + return m_classEntry.equals( other.m_classEntry ); + } + else + { + return m_classEntry.equals( other.m_classEntry ) && m_signature.equals( other.m_signature ); + } } @Override public String toString( ) { - return m_classEntry.getName() + m_signature; + if( isStatic() ) + { + return m_classEntry.getName() + "." + getName(); + } + else + { + return m_classEntry.getName() + "." + getName() + m_signature; + } } } diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java index e34c31b..a671c27 100644 --- a/src/cuchaz/enigma/mapping/Translator.java +++ b/src/cuchaz/enigma/mapping/Translator.java @@ -30,27 +30,28 @@ public class Translator m_ancestries = ancestries; } - public Entry translateEntry( Entry entry ) + @SuppressWarnings( "unchecked" ) + public T translateEntry( T entry ) { if( entry instanceof ClassEntry ) { - return translateEntry( (ClassEntry)entry ); + return (T)translateEntry( (ClassEntry)entry ); } else if( entry instanceof FieldEntry ) { - return translateEntry( (FieldEntry)entry ); + return (T)translateEntry( (FieldEntry)entry ); } else if( entry instanceof MethodEntry ) { - return translateEntry( (MethodEntry)entry ); + return (T)translateEntry( (MethodEntry)entry ); } else if( entry instanceof ConstructorEntry ) { - return translateEntry( (ConstructorEntry)entry ); + return (T)translateEntry( (ConstructorEntry)entry ); } else if( entry instanceof ArgumentEntry ) { - return translateEntry( (ArgumentEntry)entry ); + return (T)translateEntry( (ArgumentEntry)entry ); } else { @@ -194,10 +195,17 @@ public class Translator public ConstructorEntry translateEntry( ConstructorEntry in ) { - return new ConstructorEntry( - translateEntry( in.getClassEntry() ), - translateSignature( in.getSignature() ) - ); + if( in.isStatic() ) + { + return new ConstructorEntry( translateEntry( in.getClassEntry() ) ); + } + else + { + return new ConstructorEntry( + translateEntry( in.getClassEntry() ), + translateSignature( in.getSignature() ) + ); + } } public BehaviorEntry translateEntry( BehaviorEntry in ) -- cgit v1.2.3