Remap in reflect calls to defineClass

This commit is contained in:
IzzelAliz 2020-12-11 20:45:19 +08:00
parent b2fab264b6
commit 281c84ecc5
3 changed files with 38 additions and 2 deletions

View File

@ -1,11 +1,15 @@
package io.izzel.arclight.common.mod.util.remapper;
import com.google.common.collect.ImmutableMap;
import io.izzel.arclight.common.mod.ArclightMod;
import io.izzel.arclight.common.mod.util.remapper.generated.ArclightReflectionHandler;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
@ -20,6 +24,7 @@ import java.util.Objects;
public class ArclightRedirectAdapter implements PluginTransformer {
public static final ArclightRedirectAdapter INSTANCE = new ArclightRedirectAdapter();
private static final Marker MARKER = MarkerManager.getMarker("REDIRECT");
private static final String REPLACED_NAME = Type.getInternalName(ArclightReflectionHandler.class);
private static final Map<MethodInsnNode, MethodInsnNode> METHOD_REDIRECTS = ImmutableMap
.<MethodInsnNode, MethodInsnNode>builder()
@ -104,6 +109,8 @@ public class ArclightRedirectAdapter implements PluginTransformer {
method(Opcodes.INVOKESTATIC, ArclightReflectionHandler.class, "redirectClassLoaderLoadClass", ClassLoader.class, String.class)
)
.build();
private static final String METHOD_SIG = Type.getInternalName(Method.class);
private static final String INVOKE_SIG = Type.getMethodDescriptor(Type.getType(Object.class), Type.getType(Object.class), Type.getType(Object[].class));
@Override
public void handleClass(ClassNode node, ClassLoaderRemapper remapper) {
@ -111,6 +118,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
}
private static void redirect(ClassNode classNode, String generatedOwner) {
boolean defineClassFound = false;
for (MethodNode methodNode : classNode.methods) {
ListIterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
while (iterator.hasNext()) {
@ -134,6 +142,25 @@ public class ArclightRedirectAdapter implements PluginTransformer {
}
}
}
} else if (insnNode.getOpcode() == Opcodes.LDC) {
defineClassFound |= "defineClass".equals(((LdcInsnNode) insnNode).cst);
}
}
}
if (defineClassFound) {
for (MethodNode methodNode : classNode.methods) {
for (AbstractInsnNode insnNode : methodNode.instructions) {
if (insnNode.getOpcode() == Opcodes.INVOKEVIRTUAL) {
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
if (methodInsnNode.owner.equals(METHOD_SIG) && methodInsnNode.name.equals("invoke") && methodInsnNode.desc.equals(INVOKE_SIG)) {
methodInsnNode.setOpcode(Opcodes.INVOKESTATIC);
methodInsnNode.owner = generatedOwner;
methodInsnNode.name = "redirectDefineClassInvoke";
methodInsnNode.desc = "(L" + METHOD_SIG + ";" + methodInsnNode.desc.substring(1);
ArclightMod.LOGGER.debug(MARKER, "Redirect candidate defineClass method invoke in {}/{} {}"
, classNode.name, methodNode.name, methodNode.desc);
}
}
}
}
}

View File

@ -322,11 +322,11 @@ public class ClassLoaderRemapper extends JarRemapper {
}
@Override
public String mapType(String internalName) {
public String map(String internalName) {
if (internalName.equals(ORIGIN)) {
return internal;
}
return super.mapType(internalName);
return super.map(internalName);
}
}

View File

@ -223,6 +223,15 @@ public class ArclightReflectionHandler extends ClassLoader {
return loader.loadClass(replace);
}
public static Object redirectDefineClassInvoke(Method method, Object src, Object[] param) throws Exception {
if (method.getDeclaringClass() == ArclightReflectionHandler.class && method.getName().equals("defineClass")) {
Object[] args = new Object[param.length + 1];
args[0] = src;
System.arraycopy(param, 0, args, 1, param.length);
return method.invoke(null, args);
} else return method.invoke(src, param);
}
public static Class<?> defineClass(ClassLoader loader, byte[] b, int off, int len) {
return defineClass(loader, null, b, off, len);
}