Add debugging for deobfuscation

Add negative caching for field and method maps. Should shortcut some work

Fix handling the case where a class doesn't exist, but still needs deobf

Ask the patch manager for the bytes for the class, not the classLoader

Fix up some more places where we should look for a patched class

Fix problem with empty source classes and runtime deobfuscation
This commit is contained in:
Christian 2013-09-24 11:09:27 -04:00
parent c1623cb8e3
commit 96d9c3b8bc
4 changed files with 57 additions and 22 deletions

View file

@ -241,8 +241,8 @@ public class FMLSanityChecker implements IFMLCallHook
cl = (LaunchClassLoader) data.get("classLoader");
File mcDir = (File)data.get("mcLocation");
fmlLocation = (File)data.get("coremodLocation");
FMLDeobfuscatingRemapper.INSTANCE.setup(mcDir, cl, (String) data.get("deobfuscationFileName"));
ClassPatchManager.INSTANCE.setup(FMLLaunchHandler.side());
FMLDeobfuscatingRemapper.INSTANCE.setup(mcDir, cl, (String) data.get("deobfuscationFileName"));
}
}

View file

@ -53,6 +53,7 @@ import com.google.common.io.CharStreams;
import com.google.common.io.InputSupplier;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.patcher.ClassPatchManager;
import cpw.mods.fml.relauncher.FMLRelaunchLog;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
@ -71,6 +72,11 @@ public class FMLDeobfuscatingRemapper extends Remapper {
private LaunchClassLoader classLoader;
private static final boolean DEBUG_REMAPPING = Boolean.parseBoolean(System.getProperty("fml.remappingDebug", "false"));
private static final boolean DUMP_FIELD_MAPS = Boolean.parseBoolean(System.getProperty("fml.remappingDebug.dumpFieldMaps", "false")) && DEBUG_REMAPPING;
private static final boolean DUMP_METHOD_MAPS = Boolean.parseBoolean(System.getProperty("fml.remappingDebug.dumpMethodMaps", "false")) && DEBUG_REMAPPING;
private FMLDeobfuscatingRemapper()
{
classNameBiMap=ImmutableBiMap.of();
@ -202,6 +208,10 @@ public class FMLDeobfuscatingRemapper extends Remapper {
*/
private Map<String,Map<String,String>> fieldDescriptions = Maps.newHashMap();
// Cache null values so we don't waste time trying to recompute classes with no field or method maps
private Set<String> negativeCacheMethods = Sets.newHashSet();
private Set<String> negativeCacheFields = Sets.newHashSet();
private String getFieldType(String owner, String name)
{
if (fieldDescriptions.containsKey(owner))
@ -212,7 +222,7 @@ public class FMLDeobfuscatingRemapper extends Remapper {
{
try
{
byte[] classBytes = classLoader.getClassBytes(owner);
byte[] classBytes = ClassPatchManager.INSTANCE.getPatchedResource(owner, map(owner).replace('/', '.'), classLoader);
if (classBytes == null)
{
return null;
@ -288,7 +298,6 @@ public class FMLDeobfuscatingRemapper extends Remapper {
String result = classNameBiMap.containsKey(realType) ? classNameBiMap.get(realType) : mcpNameBiMap.containsKey(realType) ? mcpNameBiMap.get(realType) : realType;
result = dollarIdx > -1 ? result+"$"+subType : result;
// System.out.printf("Mapping %s=>%s\n",typeName,result);
return result;
}
@ -305,7 +314,6 @@ public class FMLDeobfuscatingRemapper extends Remapper {
String result = classNameBiMap.containsValue(realType) ? classNameBiMap.inverse().get(realType) : mcpNameBiMap.containsValue(realType) ? mcpNameBiMap.inverse().get(realType) : realType;
result = dollarIdx > -1 ? result+"$"+subType : result;
// System.out.printf("Unmapping %s=>%s\n",typeName,result);
return result;
}
@ -324,18 +332,36 @@ public class FMLDeobfuscatingRemapper extends Remapper {
private Map<String,String> getFieldMap(String className)
{
if (!fieldNameMaps.containsKey(className))
if (!fieldNameMaps.containsKey(className) && !negativeCacheFields.contains(className))
{
findAndMergeSuperMaps(className);
if (!fieldNameMaps.containsKey(className))
{
negativeCacheFields.add(className);
}
if (DUMP_FIELD_MAPS)
{
FMLRelaunchLog.finest("Field map for %s : %s", className, fieldNameMaps.get(className));
}
}
return fieldNameMaps.get(className);
}
private Map<String,String> getMethodMap(String className)
{
if (!methodNameMaps.containsKey(className))
if (!methodNameMaps.containsKey(className) && !negativeCacheMethods.contains(className))
{
findAndMergeSuperMaps(className);
if (!methodNameMaps.containsKey(className))
{
negativeCacheMethods.add(className);
}
if (DUMP_METHOD_MAPS)
{
FMLRelaunchLog.finest("Method map for %s : %s", className, methodNameMaps.get(className));
}
}
return methodNameMaps.get(className);
}
@ -344,17 +370,14 @@ public class FMLDeobfuscatingRemapper extends Remapper {
{
try
{
byte[] classBytes = classLoader.getClassBytes(name);
if (classBytes == null)
String superName = null;
String[] interfaces = new String[0];
byte[] classBytes = ClassPatchManager.INSTANCE.getPatchedResource(name, map(name), classLoader);
if (classBytes != null)
{
return;
}
ClassReader cr = new ClassReader(classBytes);
String superName = cr.getSuperName();
String[] interfaces = cr.getInterfaces();
if (interfaces == null)
{
interfaces = new String[0];
ClassReader cr = new ClassReader(classBytes);
superName = cr.getSuperName();
interfaces = cr.getInterfaces();
}
mergeSuperMaps(name, superName, interfaces);
}

View file

@ -11,6 +11,7 @@ import java.security.CodeSource;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
@ -19,6 +20,8 @@ import java.util.jar.Pack200;
import java.util.logging.Level;
import java.util.regex.Pattern;
import net.minecraft.launchwrapper.LaunchClassLoader;
import LZMA.LzmaInputStream;
import com.google.common.base.Joiner;
@ -26,6 +29,7 @@ import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
@ -44,6 +48,7 @@ public class ClassPatchManager {
private GDiffPatcher patcher = new GDiffPatcher();
private ListMultimap<String, ClassPatch> patches;
private Map<String,byte[]> patchedClasses = Maps.newHashMap();
private File tempDir;
private ClassPatchManager()
{
@ -54,12 +59,22 @@ public class ClassPatchManager {
}
}
public byte[] getPatchedResource(String name, String mappedName, LaunchClassLoader loader) throws IOException
{
byte[] rawClassBytes = loader.getClassBytes(name);
return applyPatch(name, mappedName, rawClassBytes);
}
public byte[] applyPatch(String name, String mappedName, byte[] inputData)
{
if (patches == null)
{
return inputData;
}
if (patchedClasses.containsKey(name))
{
return patchedClasses.get(name);
}
List<ClassPatch> list = patches.get(name);
if (list.isEmpty())
{
@ -69,7 +84,7 @@ public class ClassPatchManager {
FMLRelaunchLog.fine("Runtime patching class %s (input size %d), found %d patch%s", mappedName, (inputData == null ? 0 : inputData.length), list.size(), list.size()!=1 ? "es" : "");
for (ClassPatch patch: list)
{
if (!patch.targetClassName.equals(mappedName))
if (!patch.targetClassName.equals(mappedName) && !patch.sourceClassName.equals(name))
{
FMLRelaunchLog.warning("Binary patch found %s for wrong class %s", patch.targetClassName, mappedName);
}
@ -128,6 +143,7 @@ public class ClassPatchManager {
FMLRelaunchLog.log(Level.SEVERE, e, "Failed to write %s to %s", mappedName, tempDir.getAbsolutePath());
}
}
patchedClasses.put(name,inputData);
return inputData;
}
@ -185,6 +201,7 @@ public class ClassPatchManager {
} while (true);
FMLRelaunchLog.fine("Read %d binary patches", patches.size());
FMLRelaunchLog.fine("Patch list :\n\t%s", Joiner.on("\t\n").join(patches.asMap().entrySet()));
patchedClasses.clear();
}
private ClassPatch readPatch(JarEntry patchEntry, JarInputStream jis)

View file

@ -1,5 +0,0 @@
package cpw.mods.fml.common.patcher;
public class ClassPatchingTransformer {
}