Skip to content

Commit

Permalink
fix crash in server and fix Devan-Kerman#9 and fix Devan-Kerman#10
Browse files Browse the repository at this point in the history
  • Loading branch information
nnym committed Oct 24, 2020
1 parent 9969ff8 commit 5007cb4
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 157 deletions.
93 changes: 48 additions & 45 deletions src/main/java/net/devtech/grossfabrichacks/GrossFabricHacks.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.ProtectionDomain;
import java.security.SecureClassLoader;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import net.devtech.grossfabrichacks.entrypoints.PrePrePreLaunch;
import net.devtech.grossfabrichacks.reload.GrossFabricHacksReloadException;
import net.devtech.grossfabrichacks.reload.Reloader;
import net.devtech.grossfabrichacks.transformer.TransformerApi;
import net.devtech.grossfabrichacks.transformer.asm.AsmClassTransformer;
import net.devtech.grossfabrichacks.transformer.asm.RawClassTransformer;
import net.devtech.grossfabrichacks.unsafe.UnsafeUtil;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.LanguageAdapter;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.gui.FabricGuiEntry;
import net.fabricmc.loader.launch.common.FabricLauncher;
import net.fabricmc.loader.launch.common.FabricLauncherBase;
import net.fabricmc.loader.launch.knot.UnsafeKnotClassLoader;
import net.gudenau.lib.unsafe.Unsafe;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
Expand All @@ -28,17 +29,30 @@

@SuppressWarnings("ConstantConditions")
public class GrossFabricHacks implements LanguageAdapter {
private static final Logger LOGGER = LogManager.getLogger("GrossFabricHacks");
private static final Logger logger = LogManager.getLogger("GrossFabricHacks");

@Override
public native <T> T create(ModContainer mod, String value, Class<T> type);

/**
* This class is intended to be loaded by the system class loader so that classes loaded by different class loaders may share information.
* It should be safe to load from any class loader after it is loaded by the system class loader.
* This class is intended to be loaded by the class loader that loaded {@linkplain net.fabricmc.loader.launch.knot.KnotClassLoader KnotClassLoader}<br>
* so that classes loaded by different class loaders may share information.<br>
* It may also be used for storing constants.<br>
* It should be safe to load from {@link Common#preKnotClassLoader} and {@linkplain net.fabricmc.loader.launch.knot.KnotClassLoader KnotClassLoader}.
*/
@SuppressWarnings("JavadocReference")
public static class Common {
public static final String reloadedProperty = "gfh.reloaded";
/**
* the system property that indicates whether a {@linkplain Reloader#launchMain(ClassLoader)} reload} has occurred or not
*/
public static final String RELOADED_PROPERTY = "gfh.reloaded";

/**
* the system property used temporarily for transferring information about<br>
* the classes that have to be checked in {@linkplain UnsafeKnotClassLoader#preKnotClassLoader} first
*/
public static final String CLASS_PROPERTY = "gfh.elementary.classes";
public static final String CLASS_DELIMITER = ",";

public static boolean mixinLoaded;
public static boolean shouldHackMixin;
Expand Down Expand Up @@ -95,50 +109,39 @@ public static String getMainClass() {
public static void crash(final Throwable throwable) {
throwable.printStackTrace();

FabricGuiEntry.displayCriticalError(new GrossFabricHacksReloadException(throwable), true);

System.exit(-1);
FabricGuiEntry.displayCriticalError(new RuntimeException("GrossFabricHacks encountered an error. Report it along with a log to https://github.com/user11681/issues", throwable), true);
}
}

static {
LOGGER.info("no good? no, this man is definitely up to evil.");

try {
final FabricLauncher launcher = FabricLauncherBase.getLauncher();
final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
final ProtectionDomain protectionDomain = GrossFabricHacks.class.getProtectionDomain();
final String[] classes = {
"net.gudenau.lib.unsafe.Unsafe",
"user11681.reflect.Accessor",
"user11681.reflect.Invoker",
"user11681.reflect.Classes",
"user11681.reflect.Fields",
"user11681.reflect.Reflect",
"net.devtech.grossfabrichacks.unsafe.UnsafeUtil",
"net.devtech.grossfabrichacks.transformer.asm.AsmClassTransformer",
"net.devtech.grossfabrichacks.transformer.asm.RawClassTransformer",
"net.devtech.grossfabrichacks.GrossFabricHacks$Common",
"net.fabricmc.loader.launch.knot.UnsafeKnotClassLoader"
};

final int totalClassCount = classes.length;
final int definedClassCount = FabricLoader.getInstance().isDevelopmentEnvironment() ? 6 : 0;

for (int i = definedClassCount; i < totalClassCount; i++) {
final String name = classes[i];
final byte[] bytecode = launcher.getClassByteArray(name, true);
final Class<?> klass = Unsafe.defineClass(name, bytecode, 0, bytecode.length, systemClassLoader, protectionDomain);

if (i == totalClassCount - 1) {
Unsafe.ensureClassInitialized(klass);
}
}
} catch (final Throwable throwable) {
Common.crash(throwable);
logger.info("no good? no, this man is definitely up to evil.");

final String[] primaryClasses = new String[]{
"net.gudenau.lib.unsafe.Unsafe",
"user11681.reflect.Accessor",
"user11681.reflect.Classes",
"user11681.reflect.Fields",
"user11681.reflect.Reflect",
"user11681.reflect.Invoker",
"net.devtech.grossfabrichacks.unsafe.UnsafeUtil",
"net.devtech.grossfabrichacks.transformer.asm.AsmClassTransformer",
"net.devtech.grossfabrichacks.transformer.asm.RawClassTransformer",
"net.devtech.grossfabrichacks.transformer.TransformerApi",
"net.devtech.grossfabrichacks.instrumentation.InstrumentationApi",
"net.devtech.grossfabrichacks.GrossFabricHacks$Common"
};

System.setProperty(Common.CLASS_PROPERTY, String.join(Common.CLASS_DELIMITER, primaryClasses));

final ClassLoader preKnotClassLoader = ((SecureClassLoader) GrossFabricHacks.class.getClassLoader()).getClass().getClassLoader();

for (int i = FabricLauncherBase.getLauncher().isDevelopment() ? 6 : 0, length = primaryClasses.length; i < length; i++) {
UnsafeUtil.findClass(primaryClasses[i], preKnotClassLoader);
}

Reloader.ensureReloaded();
Unsafe.ensureClassInitialized(UnsafeUtil.findClass("net.fabricmc.loader.launch.knot.UnsafeKnotClassLoader", preKnotClassLoader));

TransformerApi.registerPostMixinAsmClassTransformer(klass -> logger.info(klass.name));

DynamicEntry.tryExecute("gfh:prePrePreLaunch", PrePrePreLaunch.class, PrePrePreLaunch::onPrePrePreLaunch);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.devtech.grossfabrichacks.mixin;
package net.devtech.grossfabrichacks.asm;

import java.util.List;
import java.util.Set;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ private static void init() {
}

static {
if (UnsafeKnotClassLoader.instance.isClassLoaded("net.devtech.grossfabrichacks.instrumentation") && InstrumentationAgent.instrumentation == null) {
if (!UnsafeKnotClassLoader.instance.isClassLoaded("net.devtech.grossfabrichacks.instrumentation") || InstrumentationAgent.instrumentation == null) {
final File agent = GrossFabricHacks.Common.getAgent();
final String name = ManagementFactory.getRuntimeMXBean().getName();

ByteBuddyAgent.attach(agent, name.substring(0, name.indexOf('@')));

agent.delete();
agent.delete();
}

instrumentation = InstrumentationAgent.instrumentation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

public class GFHMain {
public static void main(final String[] args) {
System.setProperty(GrossFabricHacks.Common.reloadedProperty, "true");
System.setProperty(GrossFabricHacks.Common.RELOADED_PROPERTY, "true");

if (System.getProperty("fabric.side").equals("client")) {
KnotClient.main(args);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
@Experimental
@SuppressWarnings("ConfusingArgumentToVarargsMethod")
public class Reloader {
private static final Logger logger = LogManager.getLogger("SameProcessRelauncher");
private static final Logger logger = LogManager.getLogger("Reloader");

public static boolean isReloaded() {
return Boolean.getBoolean(GrossFabricHacks.Common.reloadedProperty);
return Boolean.getBoolean(GrossFabricHacks.Common.RELOADED_PROPERTY);
}

public static void ensureReloaded() {
Expand Down Expand Up @@ -66,7 +66,7 @@ public static ObjectArrayList<String> getVMArguments() {
}

public static SecureClassLoader getNewLoader() {
logger.info("Commence same-process reload.");
logger.info("Commence reload.");

try {
// close the in-memory file system to avoid later collision
Expand Down Expand Up @@ -146,7 +146,7 @@ public static void launchMain(final ClassLoader newLoader) {

System.exit(0);
} catch (final Throwable throwable) {
GrossFabricHacks.Common.crash(throwable);
GrossFabricHacks.Common.crash(new RuntimeException("Reloading did not succeed.", throwable));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.devtech.grossfabrichacks.GrossFabricHacks;
import net.devtech.grossfabrichacks.transformer.asm.AsmClassTransformer;
import net.devtech.grossfabrichacks.transformer.asm.RawClassTransformer;
import net.fabricmc.loader.launch.knot.UnsafeKnotClassLoader;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.transformer.HackedMixinTransformer;
Expand All @@ -17,7 +18,7 @@ public class TransformerApi {
*/
public static void manualLoad() {
if (GrossFabricHacks.Common.mixinLoaded) {
Classes.load(Classes.systemClassLoader, "org.spongepowered.asm.mixin.transformer.HackedMixinTransformer");
Classes.load(UnsafeKnotClassLoader.preKnotClassLoader, "org.spongepowered.asm.mixin.transformer.HackedMixinTransformer");
} else {
GrossFabricHacks.Common.shouldHackMixin = true;
}
Expand Down
74 changes: 7 additions & 67 deletions src/main/java/net/devtech/grossfabrichacks/unsafe/UnsafeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

import java.io.IOException;
import java.lang.reflect.Array;
import java.security.ProtectionDomain;
import net.fabricmc.loader.launch.common.FabricLauncherBase;
import net.gudenau.lib.unsafe.Unsafe;
import org.apache.commons.io.IOUtils;
import user11681.reflect.Classes;

/**
* works across all normal JVMs I think
*/
public class UnsafeUtil {
public static final FabricLauncherBase launcher = (FabricLauncherBase) FabricLauncherBase.getLauncher();

// constants
public static final long BYTE_ARR_KLASS;
public static final long SHORT_ARR_KLASS;
Expand Down Expand Up @@ -151,31 +152,6 @@ public static long getKlassFromClass0(Class<?> type) {
return Unsafe.getInt(type, CLASS_KLASS_OFFSET);
}

public static void putInt(final Object object, final String field, final int value) {
try {
Unsafe.putInt(object, Unsafe.objectFieldOffset(object.getClass().getDeclaredField(field)), value);
} catch (final NoSuchFieldException exception) {
throw Unsafe.throwException(exception);
}
}

public static void putInt(final Class<?> klass, final Object object, final String field, final int value) {
try {
Unsafe.putInt(object, Unsafe.objectFieldOffset(klass.getDeclaredField(field)), value);
} catch (final NoSuchFieldException exception) {
throw Unsafe.throwException(exception);
}
}

public static <T> T getObject(final long address) {
final Object[] box = new Object[1];
final long baseOffset = Unsafe.arrayBaseOffset(Object[].class);

Unsafe.putLong(box, baseOffset, address);

return (T) box[0];
}

public static long addressOf(final Object object) {
return addressOf(0, object);
}
Expand All @@ -187,47 +163,11 @@ public static long addressOf(final int index, final Object... objects) {
return (Unsafe.getInt(objects, offset + index * scale) & 0xFFFFFFFFL) * Classes.addressFactor;
}

public static <T> Class<T> defineAndInitialize(final String binaryName, final byte[] klass) {
return defineAndInitialize(binaryName, klass, null, null);
}

public static <T> Class<T> defineAndInitialize(final String binaryName, final byte[] klass, final ClassLoader loader) {
return defineAndInitialize(binaryName, klass, loader, null);
}

public static <T> Class<T> defineAndInitialize(final String binaryName, final byte[] bytecode, final ClassLoader loader, final ProtectionDomain protectionDomain) {
final Class<?> klass;

Unsafe.ensureClassInitialized(klass = Unsafe.defineClass(binaryName, bytecode, 0, bytecode.length, loader, protectionDomain));

return (Class<T>) klass;
}

public static <T> Class<T> initializeClass(final Class<?> klass) {
Unsafe.ensureClassInitialized(klass);

return (Class<T>) klass;
}

public static <T> Class<T> defineClass(final String binaryName, final byte[] klass) {
return Unsafe.defineClass(binaryName, klass, 0, klass.length, null, null);
}

public static <T> Class<T> defineClass(final String binaryName, final byte[] klass, final ClassLoader loader) {
return Unsafe.defineClass(binaryName, klass, 0, klass.length, loader, null);
}

public static <T> Class<T> defineClass(final String binaryName, final byte[] klass, final ClassLoader loader, final ProtectionDomain protectionDomain) {
return Unsafe.defineClass(binaryName, klass, 0, klass.length, loader, protectionDomain);
}

public static <T> Class<T> findAndDefineClass(final String binaryName, final ClassLoader loader) {
return defineClass(binaryName, findClass(binaryName), loader);
}

public static byte[] findClass(final String binaryName) {
public static <T> Class<T> findClass(final String binaryName, final ClassLoader loader) {
try {
return IOUtils.toByteArray(Thread.currentThread().getContextClassLoader().getResourceAsStream(binaryName.replace('.', '/') + ".class"));
final byte[] bytecode = launcher.getClassByteArray(binaryName, false);

return Unsafe.defineClass(binaryName, bytecode, 0, bytecode.length, loader, null);
} catch (final IOException exception) {
throw Unsafe.throwException(exception);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ public byte[] getPostMixinClassByteArray(final String name) {
}

return bytecode;

}

static {
Expand All @@ -145,6 +144,6 @@ public byte[] getPostMixinClassByteArray(final String name) {
development = loader.isDevelopmentEnvironment();
environment = loader.getEnvironmentType();
canTransformClass = Invoker.findStatic(superclass, "canTransformClass", MethodType.methodType(boolean.class, String.class));
provider = Accessor.getObject(UnsafeKnotClassLoader.delegate, "provider");
provider = Accessor.getObject(((KnotClassLoader) Thread.currentThread().getContextClassLoader()).getDelegate(), "provider");
}
}
Loading

0 comments on commit 5007cb4

Please sign in to comment.