diff options
| author | 2015-03-08 20:48:30 -0400 | |
|---|---|---|
| committer | 2015-03-08 20:48:30 -0400 | |
| commit | 4ceb8d490058e48df666bf7227ce020e60928be5 (patch) | |
| tree | bdfb432cd1d61dc4914b8591468193dcd7e7421c /src/cuchaz/enigma/convert | |
| parent | lots of small tweaks and improvements (diff) | |
| download | enigma-fork-4ceb8d490058e48df666bf7227ce020e60928be5.tar.gz enigma-fork-4ceb8d490058e48df666bf7227ce020e60928be5.tar.xz enigma-fork-4ceb8d490058e48df666bf7227ce020e60928be5.zip | |
more tweaks, improvements, and bug fixes
Diffstat (limited to 'src/cuchaz/enigma/convert')
| -rw-r--r-- | src/cuchaz/enigma/convert/ClassIdentity.java | 25 | ||||
| -rw-r--r-- | src/cuchaz/enigma/convert/MappingsConverter.java | 60 |
2 files changed, 77 insertions, 8 deletions
diff --git a/src/cuchaz/enigma/convert/ClassIdentity.java b/src/cuchaz/enigma/convert/ClassIdentity.java index d07e0a4..35667b0 100644 --- a/src/cuchaz/enigma/convert/ClassIdentity.java +++ b/src/cuchaz/enigma/convert/ClassIdentity.java | |||
| @@ -16,6 +16,7 @@ import java.security.NoSuchAlgorithmException; | |||
| 16 | import java.util.Enumeration; | 16 | import java.util.Enumeration; |
| 17 | import java.util.List; | 17 | import java.util.List; |
| 18 | import java.util.Map; | 18 | import java.util.Map; |
| 19 | import java.util.Set; | ||
| 19 | 20 | ||
| 20 | import javassist.CannotCompileException; | 21 | import javassist.CannotCompileException; |
| 21 | import javassist.CtBehavior; | 22 | import javassist.CtBehavior; |
| @@ -38,6 +39,7 @@ import com.google.common.collect.HashMultiset; | |||
| 38 | import com.google.common.collect.Lists; | 39 | import com.google.common.collect.Lists; |
| 39 | import com.google.common.collect.Maps; | 40 | import com.google.common.collect.Maps; |
| 40 | import com.google.common.collect.Multiset; | 41 | import com.google.common.collect.Multiset; |
| 42 | import com.google.common.collect.Sets; | ||
| 41 | 43 | ||
| 42 | import cuchaz.enigma.Constants; | 44 | import cuchaz.enigma.Constants; |
| 43 | import cuchaz.enigma.Util; | 45 | import cuchaz.enigma.Util; |
| @@ -67,6 +69,7 @@ public class ClassIdentity { | |||
| 67 | private String m_staticInitializer; | 69 | private String m_staticInitializer; |
| 68 | private String m_extends; | 70 | private String m_extends; |
| 69 | private Multiset<String> m_implements; | 71 | private Multiset<String> m_implements; |
| 72 | private Set<String> m_stringLiterals; | ||
| 70 | private Multiset<String> m_implementations; | 73 | private Multiset<String> m_implementations; |
| 71 | private Multiset<String> m_references; | 74 | private Multiset<String> m_references; |
| 72 | private String m_outer; | 75 | private String m_outer; |
| @@ -140,6 +143,14 @@ public class ClassIdentity { | |||
| 140 | m_implements.add(scrubClassName(Descriptor.toJvmName(interfaceName))); | 143 | m_implements.add(scrubClassName(Descriptor.toJvmName(interfaceName))); |
| 141 | } | 144 | } |
| 142 | 145 | ||
| 146 | m_stringLiterals = Sets.newHashSet(); | ||
| 147 | ConstPool constants = c.getClassFile().getConstPool(); | ||
| 148 | for (int i=1; i<constants.getSize(); i++) { | ||
| 149 | if (constants.getTag(i) == ConstPool.CONST_String) { | ||
| 150 | m_stringLiterals.add(constants.getStringInfo(i)); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 143 | // stuff from the jar index | 154 | // stuff from the jar index |
| 144 | 155 | ||
| 145 | m_implementations = HashMultiset.create(); | 156 | m_implementations = HashMultiset.create(); |
| @@ -410,13 +421,15 @@ public class ClassIdentity { | |||
| 410 | public int getMatchScore(ClassIdentity other) { | 421 | public int getMatchScore(ClassIdentity other) { |
| 411 | return 2*getNumMatches(m_extends, other.m_extends) | 422 | return 2*getNumMatches(m_extends, other.m_extends) |
| 412 | + 2*getNumMatches(m_outer, other.m_outer) | 423 | + 2*getNumMatches(m_outer, other.m_outer) |
| 424 | + 2*getNumMatches(m_implements, other.m_implements) | ||
| 425 | + getNumMatches(m_stringLiterals, other.m_stringLiterals) | ||
| 413 | + getNumMatches(m_fields, other.m_fields) | 426 | + getNumMatches(m_fields, other.m_fields) |
| 414 | + getNumMatches(m_methods, other.m_methods) | 427 | + getNumMatches(m_methods, other.m_methods) |
| 415 | + getNumMatches(m_constructors, other.m_constructors); | 428 | + getNumMatches(m_constructors, other.m_constructors); |
| 416 | } | 429 | } |
| 417 | 430 | ||
| 418 | public int getMaxMatchScore() { | 431 | public int getMaxMatchScore() { |
| 419 | return 2 + 2 + m_fields.size() + m_methods.size() + m_constructors.size(); | 432 | return 2 + 2 + 2*m_implements.size() + m_stringLiterals.size() + m_fields.size() + m_methods.size() + m_constructors.size(); |
| 420 | } | 433 | } |
| 421 | 434 | ||
| 422 | public boolean matches(CtClass c) { | 435 | public boolean matches(CtClass c) { |
| @@ -426,6 +439,16 @@ public class ClassIdentity { | |||
| 426 | && m_constructors.size() == c.getDeclaredConstructors().length; | 439 | && m_constructors.size() == c.getDeclaredConstructors().length; |
| 427 | } | 440 | } |
| 428 | 441 | ||
| 442 | private int getNumMatches(Set<String> a, Set<String> b) { | ||
| 443 | int numMatches = 0; | ||
| 444 | for (String val : a) { | ||
| 445 | if (b.contains(val)) { | ||
| 446 | numMatches++; | ||
| 447 | } | ||
| 448 | } | ||
| 449 | return numMatches; | ||
| 450 | } | ||
| 451 | |||
| 429 | private int getNumMatches(Multiset<String> a, Multiset<String> b) { | 452 | private int getNumMatches(Multiset<String> a, Multiset<String> b) { |
| 430 | int numMatches = 0; | 453 | int numMatches = 0; |
| 431 | for (String val : a) { | 454 | for (String val : a) { |
diff --git a/src/cuchaz/enigma/convert/MappingsConverter.java b/src/cuchaz/enigma/convert/MappingsConverter.java index f38723f..5883878 100644 --- a/src/cuchaz/enigma/convert/MappingsConverter.java +++ b/src/cuchaz/enigma/convert/MappingsConverter.java | |||
| @@ -30,7 +30,10 @@ import cuchaz.enigma.analysis.JarIndex; | |||
| 30 | import cuchaz.enigma.convert.ClassNamer.SidedClassNamer; | 30 | import cuchaz.enigma.convert.ClassNamer.SidedClassNamer; |
| 31 | import cuchaz.enigma.mapping.ClassEntry; | 31 | import cuchaz.enigma.mapping.ClassEntry; |
| 32 | import cuchaz.enigma.mapping.ClassMapping; | 32 | import cuchaz.enigma.mapping.ClassMapping; |
| 33 | import cuchaz.enigma.mapping.ClassNameReplacer; | ||
| 34 | import cuchaz.enigma.mapping.FieldMapping; | ||
| 33 | import cuchaz.enigma.mapping.Mappings; | 35 | import cuchaz.enigma.mapping.Mappings; |
| 36 | import cuchaz.enigma.mapping.MethodMapping; | ||
| 34 | 37 | ||
| 35 | public class MappingsConverter { | 38 | public class MappingsConverter { |
| 36 | 39 | ||
| @@ -129,15 +132,20 @@ public class MappingsConverter { | |||
| 129 | for (Entry<ClassEntry,ClassEntry> match : matchesByDestChainSize.get(chainSize)) { | 132 | for (Entry<ClassEntry,ClassEntry> match : matchesByDestChainSize.get(chainSize)) { |
| 130 | 133 | ||
| 131 | // get class info | 134 | // get class info |
| 132 | ClassEntry sourceClassEntry = match.getKey(); | 135 | ClassEntry obfSourceClassEntry = match.getKey(); |
| 133 | ClassEntry deobfClassEntry = sourceDeobfuscator.deobfuscateEntry(sourceClassEntry); | 136 | ClassEntry obfDestClassEntry = match.getValue(); |
| 134 | ClassEntry destClassEntry = match.getValue(); | 137 | List<ClassEntry> destClassChain = destDeobfuscator.getJarIndex().getObfClassChain(obfDestClassEntry); |
| 135 | List<ClassEntry> destClassChain = destDeobfuscator.getJarIndex().getObfClassChain(destClassEntry); | 138 | |
| 139 | ClassMapping sourceMapping = sourceDeobfuscator.getMappings().getClassByObf(obfSourceClassEntry); | ||
| 140 | if (sourceMapping == null) { | ||
| 141 | // if this class was never deobfuscated, don't try to match it | ||
| 142 | continue; | ||
| 143 | } | ||
| 136 | 144 | ||
| 137 | // find out where to make the dest class mapping | 145 | // find out where to make the dest class mapping |
| 138 | if (destClassChain.size() == 1) { | 146 | if (destClassChain.size() == 1) { |
| 139 | // not an inner class, add directly to mappings | 147 | // not an inner class, add directly to mappings |
| 140 | newMappings.addClassMapping(new ClassMapping(destClassEntry.getName(), deobfClassEntry.getName())); | 148 | newMappings.addClassMapping(migrateClassMapping(obfDestClassEntry, sourceMapping, matches, false)); |
| 141 | } else { | 149 | } else { |
| 142 | // inner class, find the outer class mapping | 150 | // inner class, find the outer class mapping |
| 143 | ClassMapping destMapping = null; | 151 | ClassMapping destMapping = null; |
| @@ -157,14 +165,52 @@ public class MappingsConverter { | |||
| 157 | } | 165 | } |
| 158 | } | 166 | } |
| 159 | } | 167 | } |
| 160 | String deobfName = deobfClassEntry.isInnerClass() ? deobfClassEntry.getInnerClassName() : deobfClassEntry.getSimpleName(); | 168 | destMapping.addInnerClassMapping(migrateClassMapping(obfDestClassEntry, sourceMapping, matches, true)); |
| 161 | destMapping.addInnerClassMapping(new ClassMapping(destClassEntry.getName(), deobfName)); | ||
| 162 | } | 169 | } |
| 163 | } | 170 | } |
| 164 | } | 171 | } |
| 165 | return newMappings; | 172 | return newMappings; |
| 166 | } | 173 | } |
| 167 | 174 | ||
| 175 | private static ClassMapping migrateClassMapping(ClassEntry newObfClass, ClassMapping mapping, final Matches matches, boolean useSimpleName) { | ||
| 176 | |||
| 177 | ClassNameReplacer replacer = new ClassNameReplacer() { | ||
| 178 | @Override | ||
| 179 | public String replace(String className) { | ||
| 180 | ClassEntry newClassEntry = matches.getUniqueMatches().get(new ClassEntry(className)); | ||
| 181 | if (newClassEntry != null) { | ||
| 182 | return newClassEntry.getName(); | ||
| 183 | } | ||
| 184 | return null; | ||
| 185 | } | ||
| 186 | }; | ||
| 187 | |||
| 188 | ClassMapping newMapping; | ||
| 189 | String deobfName = mapping.getDeobfName(); | ||
| 190 | if (deobfName != null) { | ||
| 191 | if (useSimpleName) { | ||
| 192 | deobfName = new ClassEntry(deobfName).getSimpleName(); | ||
| 193 | } | ||
| 194 | newMapping = new ClassMapping(newObfClass.getName(), deobfName); | ||
| 195 | } else { | ||
| 196 | newMapping = new ClassMapping(newObfClass.getName()); | ||
| 197 | } | ||
| 198 | |||
| 199 | // copy fields | ||
| 200 | for (FieldMapping fieldMapping : mapping.fields()) { | ||
| 201 | // TODO: map field obf names too... | ||
| 202 | newMapping.addFieldMapping(new FieldMapping(fieldMapping, replacer)); | ||
| 203 | } | ||
| 204 | |||
| 205 | // copy methods | ||
| 206 | for (MethodMapping methodMapping : mapping.methods()) { | ||
| 207 | // TODO: map method obf names too... | ||
| 208 | newMapping.addMethodMapping(new MethodMapping(methodMapping, replacer)); | ||
| 209 | } | ||
| 210 | |||
| 211 | return newMapping; | ||
| 212 | } | ||
| 213 | |||
| 168 | public static void convertMappings(Mappings mappings, BiMap<ClassEntry,ClassEntry> changes) { | 214 | public static void convertMappings(Mappings mappings, BiMap<ClassEntry,ClassEntry> changes) { |
| 169 | 215 | ||
| 170 | // sort the changes so classes are renamed in the correct order | 216 | // sort the changes so classes are renamed in the correct order |