Remap in reflect calls to defineClass
This commit is contained in:
parent
dd5be5a46d
commit
df6517ee6e
|
@ -2,6 +2,7 @@ package io.izzel.arclight.common.mod.util.remapper;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import io.izzel.arclight.common.mod.ArclightMod;
|
||||
import io.izzel.arclight.common.mod.util.remapper.generated.RemappingURLClassLoader;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
|
@ -21,11 +22,14 @@ import org.objectweb.asm.tree.MethodNode;
|
|||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.SecureClassLoader;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ClassLoaderAdapter implements PluginTransformer {
|
||||
|
||||
|
@ -44,6 +48,27 @@ public class ClassLoaderAdapter implements PluginTransformer {
|
|||
private final Map<String, String> classLoaderTypes = ImmutableMap.<String, String>builder()
|
||||
.put(Type.getInternalName(URLClassLoader.class), Type.getInternalName(RemappingURLClassLoader.class))
|
||||
.build();
|
||||
private final Set<ClassLoaderRemapper.WrappedMethod> defineClassMethods = defineClassTypes.entrySet().stream()
|
||||
.map(LamdbaExceptionUtils.rethrowFunction(entry -> {
|
||||
MethodType type = MethodType.fromMethodDescriptorString(entry.getKey().getDescriptor(), getClass().getClassLoader());
|
||||
return new ClassLoaderRemapper.WrappedMethod("defineClass", type.parameterArray());
|
||||
})).collect(Collectors.toSet());
|
||||
|
||||
public static boolean isDefineClassMethod(Class<?> cl, String bukkitName, Class<?>[] pTypes) {
|
||||
if (bukkitName.equals("defineClass") && ClassLoader.class.isAssignableFrom(cl)) {
|
||||
return INSTANCE.defineClassMethods.contains(new ClassLoaderRemapper.WrappedMethod(bukkitName, pTypes));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDefineClassMethod(Class<?> cl, String bukkitName, MethodType methodType) {
|
||||
if (bukkitName.equals("defineClass") && ClassLoader.class.isAssignableFrom(cl)) {
|
||||
return INSTANCE.defineClassMethods.contains(new ClassLoaderRemapper.WrappedMethod(bukkitName, methodType.parameterArray()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleClass(ClassNode node, ClassLoaderRemapper remapper) {
|
||||
|
|
|
@ -359,7 +359,7 @@ public class ClassLoaderRemapper extends JarRemapper {
|
|||
|
||||
}
|
||||
|
||||
private static class WrappedMethod {
|
||||
static class WrappedMethod {
|
||||
|
||||
private final String name;
|
||||
private final Class<?>[] pTypes;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package io.izzel.arclight.common.mod.util.remapper.generated;
|
||||
|
||||
import io.izzel.arclight.api.Unsafe;
|
||||
import io.izzel.arclight.common.mod.util.remapper.ClassLoaderAdapter;
|
||||
import io.izzel.arclight.common.mod.util.remapper.ClassLoaderRemapper;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
|
@ -8,9 +10,13 @@ import java.lang.invoke.MethodHandles;
|
|||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permissions;
|
||||
import java.security.ProtectionDomain;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ArclightReflectionHandler {
|
||||
public class ArclightReflectionHandler extends ClassLoader {
|
||||
|
||||
private static final String PREFIX = "net.minecraft.";
|
||||
|
||||
|
@ -46,6 +52,12 @@ public class ArclightReflectionHandler {
|
|||
|
||||
// bukkit -> srg
|
||||
public static Method redirectGetMethod(Class<?> cl, String bukkitName, Class<?>... pTypes) throws NoSuchMethodException {
|
||||
if (ClassLoaderAdapter.isDefineClassMethod(cl, bukkitName, pTypes)) {
|
||||
Class<?>[] classes = new Class<?>[pTypes.length + 1];
|
||||
classes[0] = ClassLoader.class;
|
||||
System.arraycopy(pTypes, 0, classes, 1, pTypes.length);
|
||||
return ArclightReflectionHandler.class.getMethod(bukkitName, classes);
|
||||
}
|
||||
Method method = remapper.tryMapMethodToSrg(cl, bukkitName, pTypes);
|
||||
if (method != null) {
|
||||
return method;
|
||||
|
@ -56,6 +68,12 @@ public class ArclightReflectionHandler {
|
|||
|
||||
// bukkit -> srg
|
||||
public static Method redirectGetDeclaredMethod(Class<?> cl, String bukkitName, Class<?>... pTypes) throws NoSuchMethodException {
|
||||
if (ClassLoaderAdapter.isDefineClassMethod(cl, bukkitName, pTypes)) {
|
||||
Class<?>[] classes = new Class<?>[pTypes.length + 1];
|
||||
classes[0] = ClassLoader.class;
|
||||
System.arraycopy(pTypes, 0, classes, 1, pTypes.length);
|
||||
return ArclightReflectionHandler.class.getDeclaredMethod(bukkitName, classes);
|
||||
}
|
||||
Method method = remapper.tryMapMethodToSrg(cl, bukkitName, pTypes);
|
||||
if (method != null) {
|
||||
return method;
|
||||
|
@ -147,6 +165,13 @@ public class ArclightReflectionHandler {
|
|||
|
||||
// bukkit -> srg
|
||||
public static MethodHandle redirectFindVirtual(MethodHandles.Lookup lookup, Class<?> cl, String name, MethodType methodType) throws NoSuchMethodException, IllegalAccessException {
|
||||
if (ClassLoaderAdapter.isDefineClassMethod(cl, name, methodType)) {
|
||||
Class<?>[] pTypes = methodType.parameterArray();
|
||||
Class<?>[] classes = new Class<?>[pTypes.length + 1];
|
||||
classes[0] = ClassLoader.class;
|
||||
System.arraycopy(pTypes, 0, classes, 1, pTypes.length);
|
||||
return lookup.findStatic(ArclightReflectionHandler.class, name, MethodType.methodType(Class.class, classes));
|
||||
}
|
||||
Method method = remapper.tryMapMethodToSrg(cl, name, methodType.parameterArray());
|
||||
if (method != null) {
|
||||
return lookup.findVirtual(cl, method.getName(), methodType);
|
||||
|
@ -197,4 +222,31 @@ public class ArclightReflectionHandler {
|
|||
String replace = remapper.mapType(canonicalName.replace('.', '/')).replace('/', '.');
|
||||
return loader.loadClass(replace);
|
||||
}
|
||||
|
||||
public static Class<?> defineClass(ClassLoader loader, byte[] b, int off, int len) {
|
||||
return defineClass(loader, null, b, off, len);
|
||||
}
|
||||
|
||||
public static Class<?> defineClass(ClassLoader loader, String name, byte[] b, int off, int len) {
|
||||
return defineClass(loader, name, b, off, len, (ProtectionDomain) null);
|
||||
}
|
||||
|
||||
public static Class<?> defineClass(ClassLoader loader, String name, byte[] b, int off, int len, ProtectionDomain pd) {
|
||||
byte[] bytes = remapper.remapClass(b);
|
||||
return Unsafe.defineClass(name, bytes, 0, bytes.length, loader, pd);
|
||||
}
|
||||
|
||||
public static Class<?> defineClass(ClassLoader loader, String name, ByteBuffer b, ProtectionDomain pd) {
|
||||
byte[] bytes = new byte[b.remaining()];
|
||||
b.get(bytes);
|
||||
return defineClass(loader, name, bytes, 0, bytes.length, pd);
|
||||
}
|
||||
|
||||
public static Class<?> defineClass(ClassLoader loader, String name, byte[] b, int off, int len, CodeSource cs) {
|
||||
return defineClass(loader, name, b, off, len, new ProtectionDomain(cs, new Permissions()));
|
||||
}
|
||||
|
||||
public static Class<?> defineClass(ClassLoader loader, String name, ByteBuffer b, CodeSource cs) {
|
||||
return defineClass(loader, name, b, new ProtectionDomain(cs, new Permissions()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user