First draft runtime deobf

This commit is contained in:
Christian 2013-01-27 15:55:37 -05:00
parent 5c99e3488a
commit b4c7fe1d0e
10 changed files with 141 additions and 22 deletions

View File

@ -12,7 +12,7 @@ import cpw.mods.fml.relauncher.IClassTransformer;
public class ASMTransformer implements IClassTransformer
{
@Override
public byte[] transform(String name, byte[] bytes)
public byte[] transform(String name,String transformedName, byte[] bytes)
{
if ("net.minecraft.src.Block".equals(name))
{
@ -24,7 +24,7 @@ public class ASMTransformer implements IClassTransformer
cn.accept(cw);
return cw.toByteArray();
}
return bytes;
}

View File

@ -143,8 +143,9 @@ public class AccessTransformer implements IClassTransformer
@SuppressWarnings("unchecked")
@Override
public byte[] transform(String name, byte[] bytes)
public byte[] transform(String name, String transformedName, byte[] bytes)
{
System.out.printf("AT transforming %s : %s\n",name,transformedName);
if (bytes == null) { return null; }
if (!modifiers.containsKey(name)) { return bytes; }
@ -375,7 +376,7 @@ public class AccessTransformer implements IClassTransformer
for (AccessTransformer trans : transformers)
{
entryData = trans.transform(name, entryData);
entryData = trans.transform(name, name, entryData);
}
}

View File

@ -0,0 +1,44 @@
package cpw.mods.fml.common.asm.transformers;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.RemappingClassAdapter;
import org.objectweb.asm.tree.ClassNode;
import cpw.mods.fml.relauncher.IClassNameTransformer;
import cpw.mods.fml.relauncher.IClassTransformer;
public class DeobfuscationTransformer implements IClassTransformer, IClassNameTransformer {
@Override
public byte[] transform(String name, String transformedName, byte[] bytes)
{
System.out.println("***" + name + ":"+transformedName);
ClassReader classReader = new ClassReader(bytes);
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
RemappingClassAdapter remapAdapter = new RemappingClassAdapter(classWriter, FMLDeobfuscatingRemapper.INSTANCE);
classReader.accept(remapAdapter, ClassReader.EXPAND_FRAMES);
return classWriter.toByteArray();
}
@Override
public String remapClassName(String name)
{
return FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.','/')).replace('/', '.');
}
@Override
public String unmapClassName(String name)
{
if (name.startsWith("hello.world."))
{
return name.replace("hello.world.","").replace("LexManos", "");
}
else
{
return name;
}
}
}

View File

@ -0,0 +1,33 @@
package cpw.mods.fml.common.asm.transformers;
import org.objectweb.asm.commons.Remapper;
public class FMLDeobfuscatingRemapper extends Remapper {
public static final FMLDeobfuscatingRemapper INSTANCE = new FMLDeobfuscatingRemapper();
@Override
public String mapFieldName(String owner, String name, String desc)
{
System.out.println("+++" + owner + "."+name+"."+desc);
if (owner.indexOf('/')<0)
{
return "lexManosWasHere"+name;
}
else
{
return name;
}
}
@Override
public String map(String typeName)
{
if (typeName.indexOf('/') < 0)
{
return "hello/world/"+typeName+"LexManos";
}
else
{
return typeName;
}
}
}

View File

@ -87,7 +87,7 @@ public class MarkerTransformer implements IClassTransformer
@SuppressWarnings("unchecked")
@Override
public byte[] transform(String name, byte[] bytes)
public byte[] transform(String name, String transformedName, byte[] bytes)
{
if (bytes == null) { return null; }
if (!markers.containsKey(name)) { return bytes; }
@ -240,7 +240,7 @@ public class MarkerTransformer implements IClassTransformer
for (MarkerTransformer trans : transformers)
{
entryData = trans.transform(name, entryData);
entryData = trans.transform(name, name, entryData);
}
}

View File

@ -21,7 +21,7 @@ public class SideTransformer implements IClassTransformer
private static final boolean DEBUG = false;
@SuppressWarnings("unchecked")
@Override
public byte[] transform(String name, byte[] bytes)
public byte[] transform(String name, String transformedName, byte[] bytes)
{
if (bytes == null) { return null; }
@ -69,7 +69,7 @@ public class SideTransformer implements IClassTransformer
classNode.accept(writer);
return writer.toByteArray();
}
private boolean remove(List<AnnotationNode> anns, String side)
{
if (anns == null)

View File

@ -13,9 +13,11 @@ public class FMLCorePlugin implements IFMLLoadingPlugin
@Override
public String[] getASMTransformerClass()
{
return new String[] {"cpw.mods.fml.common.asm.transformers.AccessTransformer",
return new String[] {
"cpw.mods.fml.common.asm.transformers.AccessTransformer",
"cpw.mods.fml.common.asm.transformers.MarkerTransformer",
"cpw.mods.fml.common.asm.transformers.SideTransformer"
"cpw.mods.fml.common.asm.transformers.SideTransformer",
"cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer",
};
}

View File

@ -0,0 +1,7 @@
package cpw.mods.fml.relauncher;
public interface IClassNameTransformer {
public String remapClassName(String name);
public String unmapClassName(String name);
}

View File

@ -2,5 +2,5 @@ package cpw.mods.fml.relauncher;
public interface IClassTransformer
{
public byte[] transform(String name, byte[] bytes);
public byte[] transform(String name, String transformedName, byte[] bytes);
}

View File

@ -39,6 +39,7 @@ public class RelaunchClassLoader extends URLClassLoader
private Set<String> classLoaderExceptions = new HashSet<String>();
private Set<String> transformerExceptions = new HashSet<String>();
private Map<Package,Manifest> packageManifests = new HashMap<Package,Manifest>();
private IClassNameTransformer renameTransformer;
private static Manifest EMPTY = new Manifest();
@ -74,7 +75,12 @@ public class RelaunchClassLoader extends URLClassLoader
{
try
{
transformers.add((IClassTransformer) loadClass(transformerClassName).newInstance());
IClassTransformer transformer = (IClassTransformer) loadClass(transformerClassName).newInstance();
transformers.add(transformer);
if (transformer instanceof IClassNameTransformer && renameTransformer == null)
{
renameTransformer = (IClassNameTransformer) transformer;
}
}
catch (Exception e)
{
@ -122,9 +128,11 @@ public class RelaunchClassLoader extends URLClassLoader
try
{
CodeSigner[] signers = null;
int lastDot = name.lastIndexOf('.');
String pkgname = lastDot == -1 ? "" : name.substring(0, lastDot);
String fName = name.replace('.', '/').concat(".class");
String transformedName = transformName(name);
String untransformedName = untransformName(name);
int lastDot = untransformedName.lastIndexOf('.');
String pkgname = lastDot == -1 ? "" : untransformedName.substring(0, lastDot);
String fName = untransformedName.replace('.', '/').concat(".class");
String pkgPath = pkgname.replace('.', '/');
URLConnection urlConnection = findCodeSourceConnectionFor(fName);
if (urlConnection instanceof JarURLConnection && lastDot > -1)
@ -136,7 +144,7 @@ public class RelaunchClassLoader extends URLClassLoader
Manifest mf = jf.getManifest();
JarEntry ent = jf.getJarEntry(fName);
Package pkg = getPackage(pkgname);
getClassBytes(name);
getClassBytes(untransformedName);
signers = ent.getCodeSigners();
if (pkg == null)
{
@ -169,10 +177,10 @@ public class RelaunchClassLoader extends URLClassLoader
FMLLog.severe("The URL %s is defining elements for sealed path %s", urlConnection.getURL(), pkgname);
}
}
byte[] basicClass = getClassBytes(name);
byte[] transformedClass = runTransformers(name, basicClass);
Class<?> cl = defineClass(name, transformedClass, 0, transformedClass.length, new CodeSource(urlConnection.getURL(), signers));
cachedClasses.put(name, cl);
byte[] basicClass = getClassBytes(untransformedName);
byte[] transformedClass = runTransformers(untransformedName, transformedName, basicClass);
Class<?> cl = defineClass(transformedName, transformedClass, 0, transformedClass.length, new CodeSource(urlConnection.getURL(), signers));
cachedClasses.put(transformedName, cl);
return cl;
}
catch (Throwable e)
@ -186,6 +194,30 @@ public class RelaunchClassLoader extends URLClassLoader
}
}
private String untransformName(String name)
{
if (renameTransformer != null)
{
return renameTransformer.unmapClassName(name);
}
else
{
return name;
}
}
private String transformName(String name)
{
if (renameTransformer != null)
{
return renameTransformer.remapClassName(name);
}
else
{
return name;
}
}
private boolean isSealed(String path, Manifest man)
{
Attributes attr = man.getAttributes(path);
@ -221,11 +253,11 @@ public class RelaunchClassLoader extends URLClassLoader
}
}
private byte[] runTransformers(String name, byte[] basicClass)
private byte[] runTransformers(String name, String transformedName, byte[] basicClass)
{
for (IClassTransformer transformer : transformers)
{
basicClass = transformer.transform(name, basicClass);
basicClass = transformer.transform(name, transformedName, basicClass);
}
return basicClass;
}