From c133e05b786ff5357931842581571c046f958c74 Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 16 Mar 2015 12:29:17 -0400 Subject: fix a zillion issues with inner classes --- src/cuchaz/enigma/Deobfuscator.java | 8 +- src/cuchaz/enigma/TranslatingTypeLoader.java | 2 +- src/cuchaz/enigma/analysis/EntryReference.java | 2 +- src/cuchaz/enigma/analysis/JarIndex.java | 2 +- src/cuchaz/enigma/bytecode/ClassRenamer.java | 2 +- src/cuchaz/enigma/bytecode/ClassTranslator.java | 17 +-- src/cuchaz/enigma/bytecode/InnerClassWriter.java | 4 +- src/cuchaz/enigma/convert/ClassIdentity.java | 2 +- src/cuchaz/enigma/convert/MappingsConverter.java | 2 +- src/cuchaz/enigma/gui/CodeReader.java | 2 +- src/cuchaz/enigma/gui/GuiController.java | 2 +- src/cuchaz/enigma/mapping/ClassEntry.java | 31 ++++-- src/cuchaz/enigma/mapping/ClassMapping.java | 79 +++++++------- src/cuchaz/enigma/mapping/Mappings.java | 28 +++++ src/cuchaz/enigma/mapping/MappingsRenamer.java | 128 +++++++++++------------ src/cuchaz/enigma/mapping/Translator.java | 73 ++++--------- 16 files changed, 198 insertions(+), 186 deletions(-) (limited to 'src') diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index f5012bde..5a23ce5b 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java @@ -438,7 +438,13 @@ public class Deobfuscator { public boolean hasDeobfuscatedName(Entry obfEntry) { Translator translator = getTranslator(TranslationDirection.Deobfuscating); if (obfEntry instanceof ClassEntry) { - return translator.translate((ClassEntry)obfEntry) != null; + ClassEntry obfClass = (ClassEntry)obfEntry; + ClassEntry translated = translator.translateEntry(obfClass); + if (obfClass.isInnerClass()) { + return !obfClass.getInnermostClassName().equals(translated.getInnermostClassName()); + } else { + return !obfClass.equals(translated); + } } else if (obfEntry instanceof FieldEntry) { return translator.translate((FieldEntry)obfEntry) != null; } else if (obfEntry instanceof MethodEntry) { diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java index 7b57cfa7..ecd7d642 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java @@ -205,7 +205,7 @@ public class TranslatingTypeLoader implements ITypeLoader { } if (obfClassEntry.isInnerClass()) { // try just the inner class name - classNamesToTry.add(obfClassEntry.getInnerClassName()); + classNamesToTry.add(obfClassEntry.getInnermostClassName()); } return classNamesToTry; } diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java index bb611df5..d0a5c6af 100644 --- a/src/cuchaz/enigma/analysis/EntryReference.java +++ b/src/cuchaz/enigma/analysis/EntryReference.java @@ -74,7 +74,7 @@ public class EntryReference { ClassEntry classEntry = (ClassEntry)getNameableEntry(); if (classEntry.isInnerClass()) { // make sure we only rename the inner class name - return classEntry.getInnerClassName(); + return classEntry.getInnermostClassName(); } } diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 7ebbd974..a4a3abb8 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java @@ -312,7 +312,7 @@ public class JarIndex { // does this class already have an outer class? if (classEntry.isInnerClass()) { - return classEntry.getOuterClassEntry(); + return classEntry.getOutermostClassEntry(); } InnerClassesAttribute innerClassesAttribute = (InnerClassesAttribute)c.getClassFile().getAttribute(InnerClassesAttribute.tag); if (innerClassesAttribute != null) { diff --git a/src/cuchaz/enigma/bytecode/ClassRenamer.java b/src/cuchaz/enigma/bytecode/ClassRenamer.java index a5fea926..e9cdea3c 100644 --- a/src/cuchaz/enigma/bytecode/ClassRenamer.java +++ b/src/cuchaz/enigma/bytecode/ClassRenamer.java @@ -43,7 +43,7 @@ public class ClassRenamer { for (int i = 0; i < attr.tableLength(); i++) { ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i))); if (attr.innerNameIndex(i) != 0) { - attr.setInnerNameIndex(i, constants.addUtf8Info(classEntry.getInnerClassName())); + attr.setInnerNameIndex(i, constants.addUtf8Info(classEntry.getInnermostClassName())); } /* DEBUG diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java index 4167731a..94ab2c4b 100644 --- a/src/cuchaz/enigma/bytecode/ClassTranslator.java +++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java @@ -26,7 +26,6 @@ import cuchaz.enigma.mapping.BehaviorEntry; import cuchaz.enigma.mapping.ClassEntry; import cuchaz.enigma.mapping.EntryFactory; import cuchaz.enigma.mapping.FieldEntry; -import cuchaz.enigma.mapping.MethodEntry; import cuchaz.enigma.mapping.Signature; import cuchaz.enigma.mapping.Translator; import cuchaz.enigma.mapping.Type; @@ -101,26 +100,30 @@ public class ClassTranslator { } // translate the type - Type translatedType = m_translator.translateType(new Type(field.getFieldInfo().getDescriptor())); + Type translatedType = m_translator.translateType(entry.getType()); field.getFieldInfo().setDescriptor(translatedType.toString()); } // translate all the methods and constructors for (CtBehavior behavior : c.getDeclaredBehaviors()) { + + BehaviorEntry entry = EntryFactory.getBehaviorEntry(behavior); + if (behavior instanceof CtMethod) { CtMethod method = (CtMethod)behavior; // translate the name - MethodEntry entry = EntryFactory.getMethodEntry(method); String translatedName = m_translator.translate(entry); if (translatedName != null) { method.setName(translatedName); } } - // translate the type - Signature translatedSignature = m_translator.translateSignature(new Signature(behavior.getMethodInfo().getDescriptor())); - behavior.getMethodInfo().setDescriptor(translatedSignature.toString()); + if (entry.getSignature() != null) { + // translate the type + Signature translatedSignature = m_translator.translateSignature(entry.getSignature()); + behavior.getMethodInfo().setDescriptor(translatedSignature.toString()); + } } // translate all the class names referenced in the code @@ -137,7 +140,7 @@ public class ClassTranslator { // translate the source file attribute too ClassEntry deobfClassEntry = map.get(classEntry); if (deobfClassEntry != null) { - String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOuterClassName()) + ".java"; + String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOutermostClassName()) + ".java"; c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile)); } } diff --git a/src/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/cuchaz/enigma/bytecode/InnerClassWriter.java index dd21a780..976028d2 100644 --- a/src/cuchaz/enigma/bytecode/InnerClassWriter.java +++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java @@ -93,7 +93,7 @@ public class InnerClassWriter { // get the new inner class name ClassEntry obfInnerClassEntry = obfClassEntry.buildClassEntry(obfClassChain); - ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOuterClassEntry(); + ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOutermostClassEntry(); // here's what the JVM spec says about the InnerClasses attribute // append(inner, parent, 0 if anonymous else simple name, flags); @@ -105,7 +105,7 @@ public class InnerClassWriter { int innerClassNameIndex = 0; int accessFlags = 0; if (!m_index.isAnonymousClass(obfClassEntry)) { - innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnerClassName()); + innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnermostClassName()); } attr.append(innerClassIndex, parentClassIndex, innerClassNameIndex, accessFlags); diff --git a/src/cuchaz/enigma/convert/ClassIdentity.java b/src/cuchaz/enigma/convert/ClassIdentity.java index 35667b05..d76cd63e 100644 --- a/src/cuchaz/enigma/convert/ClassIdentity.java +++ b/src/cuchaz/enigma/convert/ClassIdentity.java @@ -180,7 +180,7 @@ public class ClassIdentity { } } - m_outer = EntryFactory.getClassEntry(c).getOuterClassName(); + m_outer = EntryFactory.getClassEntry(c).getOutermostClassName(); } private void addReference(EntryReference reference) { diff --git a/src/cuchaz/enigma/convert/MappingsConverter.java b/src/cuchaz/enigma/convert/MappingsConverter.java index ddd3a53c..2afa1208 100644 --- a/src/cuchaz/enigma/convert/MappingsConverter.java +++ b/src/cuchaz/enigma/convert/MappingsConverter.java @@ -169,7 +169,7 @@ public class MappingsConverter { newMappings.addClassMapping(destMapping); } } else { - destMapping = destMapping.getInnerClassByObf(destChainClassEntry.getInnerClassName()); + destMapping = destMapping.getInnerClassByObfSimple(destChainClassEntry.getInnermostClassName()); if (destMapping == null) { destMapping = new ClassMapping(destChainClassEntry.getName()); destMapping.addInnerClassMapping(destMapping); diff --git a/src/cuchaz/enigma/gui/CodeReader.java b/src/cuchaz/enigma/gui/CodeReader.java index 743ef2e4..fb8e0825 100644 --- a/src/cuchaz/enigma/gui/CodeReader.java +++ b/src/cuchaz/enigma/gui/CodeReader.java @@ -106,7 +106,7 @@ public class CodeReader extends JEditorPane { // get the outermost class ClassEntry outermostClassEntry = classEntry; while (outermostClassEntry.isInnerClass()) { - outermostClassEntry = outermostClassEntry.getOuterClassEntry(); + outermostClassEntry = outermostClassEntry.getOutermostClassEntry(); } // decompile it diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index 9fa633eb..552ee47c 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java @@ -257,7 +257,7 @@ public class GuiController { // get the reference target class EntryReference obfReference = m_deobfuscator.obfuscateReference(deobfReference); - ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOuterClassEntry(); + ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOutermostClassEntry(); if (!m_deobfuscator.isObfuscatedIdentifier(obfClassEntry)) { throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!"); } diff --git a/src/cuchaz/enigma/mapping/ClassEntry.java b/src/cuchaz/enigma/mapping/ClassEntry.java index 69e66bc0..5f3b5e23 100644 --- a/src/cuchaz/enigma/mapping/ClassEntry.java +++ b/src/cuchaz/enigma/mapping/ClassEntry.java @@ -13,6 +13,8 @@ package cuchaz.enigma.mapping; import java.io.Serializable; import java.util.List; +import com.beust.jcommander.internal.Lists; + public class ClassEntry implements Entry, Serializable { private static final long serialVersionUID = 4235460580973955811L; @@ -29,7 +31,7 @@ public class ClassEntry implements Entry, Serializable { m_name = className; - if (isInnerClass() && getInnerClassName().indexOf('/') >= 0) { + if (isInnerClass() && getInnermostClassName().indexOf('/') >= 0) { throw new IllegalArgumentException("Inner class must not have a package: " + className); } } @@ -84,22 +86,39 @@ public class ClassEntry implements Entry, Serializable { return m_name.lastIndexOf('$') >= 0; } - public String getOuterClassName() { + public List getClassChainNames() { + return Lists.newArrayList(m_name.split("\\$")); + } + + public List getClassChain() { + List entries = Lists.newArrayList(); + StringBuilder buf = new StringBuilder(); + for (String name : getClassChainNames()) { + if (buf.length() > 0) { + buf.append("$"); + } + buf.append(name); + entries.add(new ClassEntry(buf.toString())); + } + return entries; + } + + public String getOutermostClassName() { if (isInnerClass()) { return m_name.substring(0, m_name.lastIndexOf('$')); } return m_name; } - public String getInnerClassName() { + public String getInnermostClassName() { if (!isInnerClass()) { throw new Error("This is not an inner class!"); } return m_name.substring(m_name.lastIndexOf('$') + 1); } - public ClassEntry getOuterClassEntry() { - return new ClassEntry(getOuterClassName()); + public ClassEntry getOutermostClassEntry() { + return new ClassEntry(getOutermostClassName()); } public boolean isInDefaultPackage() { @@ -130,7 +149,7 @@ public class ClassEntry implements Entry, Serializable { buf.append(chainEntry.getName()); } else { buf.append("$"); - buf.append(chainEntry.isInnerClass() ? chainEntry.getInnerClassName() : chainEntry.getSimpleName()); + buf.append(chainEntry.isInnerClass() ? chainEntry.getInnermostClassName() : chainEntry.getSimpleName()); } if (chainEntry == this) { diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java index 38cd3d6d..6e7fd17b 100644 --- a/src/cuchaz/enigma/mapping/ClassMapping.java +++ b/src/cuchaz/enigma/mapping/ClassMapping.java @@ -23,22 +23,23 @@ public class ClassMapping implements Serializable, Comparable { private String m_obfFullName; private String m_obfSimpleName; private String m_deobfName; - private Map m_innerClassesByObf; + private Map m_innerClassesByObfSimple; private Map m_innerClassesByDeobf; private Map m_fieldsByObf; private Map m_fieldsByDeobf; private Map m_methodsByObf; private Map m_methodsByDeobf; - public ClassMapping(String obfName) { - this(obfName, null); + public ClassMapping(String obfFullName) { + this(obfFullName, null); } - public ClassMapping(String obfName, String deobfName) { - m_obfFullName = obfName; - m_obfSimpleName = new ClassEntry(obfName).getSimpleName(); + public ClassMapping(String obfFullName, String deobfName) { + m_obfFullName = obfFullName; + ClassEntry classEntry = new ClassEntry(obfFullName); + m_obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName(); m_deobfName = NameValidator.validateClassName(deobfName, false); - m_innerClassesByObf = Maps.newHashMap(); + m_innerClassesByObfSimple = Maps.newHashMap(); m_innerClassesByDeobf = Maps.newHashMap(); m_fieldsByObf = Maps.newHashMap(); m_fieldsByDeobf = Maps.newHashMap(); @@ -65,12 +66,12 @@ public class ClassMapping implements Serializable, Comparable { //// INNER CLASSES //////// public Iterable innerClasses() { - assert (m_innerClassesByObf.size() >= m_innerClassesByDeobf.size()); - return m_innerClassesByObf.values(); + assert (m_innerClassesByObfSimple.size() >= m_innerClassesByDeobf.size()); + return m_innerClassesByObfSimple.values(); } public void addInnerClassMapping(ClassMapping classMapping) { - boolean obfWasAdded = m_innerClassesByObf.put(classMapping.getObfSimpleName(), classMapping) == null; + boolean obfWasAdded = m_innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null; assert (obfWasAdded); if (classMapping.getDeobfName() != null) { assert (isSimpleClassName(classMapping.getDeobfName())); @@ -80,7 +81,7 @@ public class ClassMapping implements Serializable, Comparable { } public void removeInnerClassMapping(ClassMapping classMapping) { - boolean obfWasRemoved = m_innerClassesByObf.remove(classMapping.getObfSimpleName()) != null; + boolean obfWasRemoved = m_innerClassesByObfSimple.remove(classMapping.getObfSimpleName()) != null; assert (obfWasRemoved); if (classMapping.getDeobfName() != null) { boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; @@ -88,20 +89,19 @@ public class ClassMapping implements Serializable, Comparable { } } - public ClassMapping getOrCreateInnerClass(String obfName) { - assert (isSimpleClassName(obfName)); - ClassMapping classMapping = m_innerClassesByObf.get(obfName); + public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) { + ClassMapping classMapping = m_innerClassesByObfSimple.get(obfInnerClass.getInnermostClassName()); if (classMapping == null) { - classMapping = new ClassMapping(obfName); - boolean wasAdded = m_innerClassesByObf.put(obfName, classMapping) == null; + classMapping = new ClassMapping(obfInnerClass.getName()); + boolean wasAdded = m_innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null; assert (wasAdded); } return classMapping; } - public ClassMapping getInnerClassByObf(String obfName) { - assert (isSimpleClassName(obfName)); - return m_innerClassesByObf.get(obfName); + public ClassMapping getInnerClassByObfSimple(String obfSimpleName) { + assert (isSimpleClassName(obfSimpleName)); + return m_innerClassesByObfSimple.get(obfSimpleName); } public ClassMapping getInnerClassByDeobf(String deobfName) { @@ -109,35 +109,25 @@ public class ClassMapping implements Serializable, Comparable { return m_innerClassesByDeobf.get(deobfName); } - public ClassMapping getInnerClassByDeobfThenObf(String name) { + public ClassMapping getInnerClassByDeobfThenObfSimple(String name) { ClassMapping classMapping = getInnerClassByDeobf(name); if (classMapping == null) { - classMapping = getInnerClassByObf(name); + classMapping = getInnerClassByObfSimple(name); } return classMapping; } - public String getObfInnerClassSimpleName(String deobfName) { - assert (isSimpleClassName(deobfName)); - ClassMapping classMapping = m_innerClassesByDeobf.get(deobfName); - if (classMapping != null) { - return classMapping.getObfSimpleName(); - } - return null; - } - - public String getDeobfInnerClassName(String obfName) { - assert (isSimpleClassName(obfName)); - ClassMapping classMapping = m_innerClassesByObf.get(obfName); + public String getDeobfInnerClassName(String obfSimpleName) { + assert (isSimpleClassName(obfSimpleName)); + ClassMapping classMapping = m_innerClassesByObfSimple.get(obfSimpleName); if (classMapping != null) { return classMapping.getDeobfName(); } return null; } - public void setInnerClassName(String obfName, String deobfName) { - assert (isSimpleClassName(obfName)); - ClassMapping classMapping = getOrCreateInnerClass(obfName); + public void setInnerClassName(ClassEntry obfInnerClass, String deobfName) { + ClassMapping classMapping = getOrCreateInnerClass(obfInnerClass); if (classMapping.getDeobfName() != null) { boolean wasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; assert (wasRemoved); @@ -150,6 +140,15 @@ public class ClassMapping implements Serializable, Comparable { } } + public boolean hasInnerClassByObfSimple(String obfSimpleName) { + return m_innerClassesByObfSimple.containsKey(obfSimpleName); + } + + public boolean hasInnerClassByDeobf(String deobfName) { + return m_innerClassesByDeobf.containsKey(deobfName); + } + + //// FIELDS //////// public Iterable fields() { @@ -382,7 +381,7 @@ public class ClassMapping implements Serializable, Comparable { buf.append("\n"); } buf.append("Inner Classes:\n"); - for (ClassMapping classMapping : m_innerClassesByObf.values()) { + for (ClassMapping classMapping : m_innerClassesByObfSimple.values()) { buf.append("\t"); buf.append(classMapping.getObfSimpleName()); buf.append(" <-> "); @@ -404,11 +403,11 @@ public class ClassMapping implements Serializable, Comparable { public boolean renameObfClass(String oldObfClassName, String newObfClassName) { // rename inner classes - for (ClassMapping innerClassMapping : new ArrayList(m_innerClassesByObf.values())) { + for (ClassMapping innerClassMapping : new ArrayList(m_innerClassesByObfSimple.values())) { if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) { - boolean wasRemoved = m_innerClassesByObf.remove(oldObfClassName) != null; + boolean wasRemoved = m_innerClassesByObfSimple.remove(oldObfClassName) != null; assert (wasRemoved); - boolean wasAdded = m_innerClassesByObf.put(newObfClassName, innerClassMapping) == null; + boolean wasAdded = m_innerClassesByObfSimple.put(newObfClassName, innerClassMapping) == null; assert (wasAdded); } } diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index a85bcbf6..659d23ac 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java @@ -13,9 +13,11 @@ package cuchaz.enigma.mapping; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; +import com.beust.jcommander.internal.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -89,6 +91,18 @@ public class Mappings implements Serializable { return m_classesByDeobf.get(deobfName); } + public void setClassDeobfName(ClassMapping classMapping, String deobfName) { + if (classMapping.getDeobfName() != null) { + boolean wasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null; + assert (wasRemoved); + } + classMapping.setDeobfName(deobfName); + if (deobfName != null) { + boolean wasAdded = m_classesByDeobf.put(deobfName, classMapping) == null; + assert (wasAdded); + } + } + public Translator getTranslator(TranslationDirection direction, TranslationIndex index) { switch (direction) { case Deobfuscating: @@ -185,4 +199,18 @@ public class Mappings implements Serializable { } return false; } + + public List getClassMappingChain(ClassEntry obfClass) { + List mappingChain = Lists.newArrayList(); + ClassMapping classMapping = null; + for (ClassEntry obfClassEntry : obfClass.getClassChain()) { + if (mappingChain.isEmpty()) { + classMapping = m_classesByObf.get(obfClassEntry.getName()); + } else if (classMapping != null) { + classMapping = classMapping.getInnerClassByObfSimple(obfClassEntry.getInnermostClassName()); + } + mappingChain.add(classMapping); + } + return mappingChain; + } } diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java index 16f700d2..d7766dc8 100644 --- a/src/cuchaz/enigma/mapping/MappingsRenamer.java +++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java @@ -13,10 +13,10 @@ package cuchaz.enigma.mapping; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.OutputStream; +import java.util.List; import java.util.Set; import java.util.zip.GZIPOutputStream; -import cuchaz.enigma.Constants; import cuchaz.enigma.analysis.JarIndex; public class MappingsRenamer { @@ -30,48 +30,43 @@ public class MappingsRenamer { } public void setClassName(ClassEntry obf, String deobfName) { - deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass()); - ClassEntry targetEntry = new ClassEntry(deobfName); - if (m_mappings.containsDeobfClass(deobfName) || m_index.containsObfClass(targetEntry)) { - throw new IllegalNameException(deobfName, "There is already a class with that name"); - } - ClassMapping classMapping = getOrCreateClassMapping(obf); + deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass()); - if (obf.isInnerClass()) { - classMapping.setInnerClassName(obf.getInnerClassName(), deobfName); + List mappingChain = getOrCreateClassMappingChain(obf); + if (mappingChain.size() == 1) { + + if (deobfName != null) { + // make sure we don't rename to an existing obf or deobf class + if (m_mappings.containsDeobfClass(deobfName) || m_index.containsObfClass(new ClassEntry(deobfName))) { + throw new IllegalNameException(deobfName, "There is already a class with that name"); + } + } + + ClassMapping classMapping = mappingChain.get(0); + m_mappings.setClassDeobfName(classMapping, deobfName); + } else { - if (classMapping.getDeobfName() != null) { - boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null; - assert (wasRemoved); + + ClassMapping outerClassMapping = mappingChain.get(mappingChain.size() - 2); + + if (deobfName != null) { + // make sure we don't rename to an existing obf or deobf inner class + if (outerClassMapping.hasInnerClassByDeobf(deobfName) || outerClassMapping.hasInnerClassByObfSimple(deobfName)) { + throw new IllegalNameException(deobfName, "There is already a class with that name"); + } } - classMapping.setDeobfName(deobfName); - boolean wasAdded = m_mappings.m_classesByDeobf.put(deobfName, classMapping) == null; - assert (wasAdded); + + outerClassMapping.setInnerClassName(obf, deobfName); } } public void removeClassMapping(ClassEntry obf) { - ClassMapping classMapping = getClassMapping(obf); - if (obf.isInnerClass()) { - classMapping.setInnerClassName(obf.getName(), null); - } else { - boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null; - assert (wasRemoved); - classMapping.setDeobfName(null); - } + setClassName(obf, null); } public void markClassAsDeobfuscated(ClassEntry obf) { - ClassMapping classMapping = getOrCreateClassMapping(obf); - if (obf.isInnerClass()) { - String innerClassName = Constants.NonePackage + "/" + obf.getInnerClassName(); - classMapping.setInnerClassName(innerClassName, innerClassName); - } else { - classMapping.setDeobfName(obf.getName()); - boolean wasAdded = m_mappings.m_classesByDeobf.put(obf.getName(), classMapping) == null; - assert (wasAdded); - } + setClassName(obf, obf.isInnerClass() ? obf.getInnermostClassName() : obf.getSimpleName()); } public void setFieldName(FieldEntry obf, String deobfName) { @@ -81,17 +76,17 @@ public class MappingsRenamer { throw new IllegalNameException(deobfName, "There is already a field with that name"); } - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.setFieldName(obf.getName(), obf.getType(), deobfName); } public void removeFieldMapping(FieldEntry obf) { - ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.removeFieldMapping(classMapping.getFieldByObf(obf.getName(), obf.getType())); } public void markFieldAsDeobfuscated(FieldEntry obf) { - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.setFieldName(obf.getName(), obf.getType(), obf.getName()); } @@ -121,7 +116,7 @@ public class MappingsRenamer { throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); } - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.setMethodName(obf.getName(), obf.getSignature(), deobfName); } @@ -132,7 +127,7 @@ public class MappingsRenamer { } public void removeMethodMapping(MethodEntry obf) { - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.setMethodName(obf.getName(), obf.getSignature(), null); } @@ -143,7 +138,7 @@ public class MappingsRenamer { } public void markMethodAsDeobfuscated(MethodEntry obf) { - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.setMethodName(obf.getName(), obf.getSignature(), obf.getName()); } @@ -154,17 +149,17 @@ public class MappingsRenamer { throw new IllegalNameException(deobfName, "There is already an argument with that name"); } - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName); } public void removeArgumentMapping(ArgumentEntry obf) { - ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex()); } public void markArgumentAsDeobfuscated(ArgumentEntry obf) { - ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); + ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), obf.getName()); } @@ -204,34 +199,31 @@ public class MappingsRenamer { gzipout.finish(); } - private ClassMapping getClassMapping(ClassEntry obfClassEntry) { - return m_mappings.m_classesByObf.get(obfClassEntry.getOuterClassName()); - } - private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) { - String obfClassName = obfClassEntry.getOuterClassName(); - ClassMapping classMapping = m_mappings.m_classesByObf.get(obfClassName); - if (classMapping == null) { - classMapping = new ClassMapping(obfClassName); - boolean obfWasAdded = m_mappings.m_classesByObf.put(classMapping.getObfFullName(), classMapping) == null; - assert (obfWasAdded); - } - return classMapping; - } - - private ClassMapping getClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) { - ClassMapping classMapping = getClassMapping(obfClassEntry); - if (obfClassEntry.isInDefaultPackage()) { - classMapping = classMapping.getInnerClassByObf(obfClassEntry.getInnerClassName()); - } - return classMapping; - } - - private ClassMapping getOrCreateClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) { - ClassMapping classMapping = getOrCreateClassMapping(obfClassEntry); - if (obfClassEntry.isInnerClass()) { - classMapping = classMapping.getOrCreateInnerClass(obfClassEntry.getInnerClassName()); + List mappingChain = getOrCreateClassMappingChain(obfClassEntry); + return mappingChain.get(mappingChain.size() - 1); + } + + private List getOrCreateClassMappingChain(ClassEntry obfClassEntry) { + List classChain = obfClassEntry.getClassChain(); + List mappingChain = m_mappings.getClassMappingChain(obfClassEntry); + for (int i=0; i m_classes; private TranslationIndex m_index; + private ClassNameReplacer m_classNameReplacer = new ClassNameReplacer() { + @Override + public String replace(String className) { + return translateEntry(new ClassEntry(className)).getName(); + } + }; + public Translator() { m_direction = null; m_classes = Maps.newHashMap(); @@ -69,48 +76,16 @@ public class Translator { } } - public String translateClass(String className) { - return translate(new ClassEntry(className)); - } - public String translate(ClassEntry in) { - - if (in.isInnerClass()) { - - // translate everything in the class chain, or return null - List mappingsChain = getClassMappingChain(in); - StringBuilder buf = new StringBuilder(); - for (ClassMapping classMapping : mappingsChain) { - if (classMapping == null) { - return null; - } - boolean isFirstClass = buf.length() == 0; - String name = m_direction.choose( - classMapping.getDeobfName(), - isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName() - ); - if (name == null) { - return null; - } - if (!isFirstClass) { - buf.append("$"); - } - buf.append(name); - } - return buf.toString(); - - } else { - - // normal classes are easier - ClassMapping classMapping = m_classes.get(in.getName()); - if (classMapping == null) { - return null; - } - return m_direction.choose( - classMapping.getDeobfName(), - classMapping.getObfFullName() - ); + ClassEntry translated = translateEntry(in); + if (translated.equals(in)) { + return null; } + return translated.getName(); + } + + public String translateClass(String className) { + return translate(new ClassEntry(className)); } public ClassEntry translateEntry(ClassEntry in) { @@ -264,21 +239,11 @@ public class Translator { } public Type translateType(Type type) { - return new Type(type, new ClassNameReplacer() { - @Override - public String replace(String className) { - return translateClass(className); - } - }); + return new Type(type, m_classNameReplacer); } public Signature translateSignature(Signature signature) { - return new Signature(signature, new ClassNameReplacer() { - @Override - public String replace(String className) { - return translateClass(className); - } - }); + return new Signature(signature, m_classNameReplacer); } private ClassMapping findClassMapping(ClassEntry in) { @@ -302,8 +267,8 @@ public class Translator { ClassMapping innerClassMapping = null; if (outerClassMapping != null) { innerClassMapping = m_direction.choose( - outerClassMapping.getInnerClassByObf(parts[i]), - outerClassMapping.getInnerClassByDeobfThenObf(parts[i]) + outerClassMapping.getInnerClassByObfSimple(parts[i]), + outerClassMapping.getInnerClassByDeobfThenObfSimple(parts[i]) ); } mappingsChain.add(innerClassMapping); -- cgit v1.2.3