From 1c1704e15443d565370ea5340788e9a3884bec98 Mon Sep 17 00:00:00 2001 From: FalsePattern <30945458+FalsePattern@users.noreply.github.com> Date: Mon, 25 Jul 2022 21:10:54 +0200 Subject: [PATCH] more ASM work... --- .../com/falsepattern/lib/asm/ASMUtil.java | 21 +++++++ .../lib/asm/IClassNodeTransformer.java | 13 +++++ .../lib/asm/SmartTransformer.java | 55 +++++++++++++++++++ .../AsmClassNotFoundException.java | 2 +- .../AsmFieldNotFoundException.java | 2 +- .../AsmMethodNotFoundException.java | 2 +- .../AsmTransformException.java | 2 +- 7 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/falsepattern/lib/asm/IClassNodeTransformer.java create mode 100644 src/main/java/com/falsepattern/lib/asm/SmartTransformer.java rename src/main/java/com/falsepattern/lib/asm/{ => exceptions}/AsmClassNotFoundException.java (80%) rename src/main/java/com/falsepattern/lib/asm/{ => exceptions}/AsmFieldNotFoundException.java (80%) rename src/main/java/com/falsepattern/lib/asm/{ => exceptions}/AsmMethodNotFoundException.java (80%) rename src/main/java/com/falsepattern/lib/asm/{ => exceptions}/AsmTransformException.java (88%) diff --git a/src/main/java/com/falsepattern/lib/asm/ASMUtil.java b/src/main/java/com/falsepattern/lib/asm/ASMUtil.java index f7b8c56..03459cc 100644 --- a/src/main/java/com/falsepattern/lib/asm/ASMUtil.java +++ b/src/main/java/com/falsepattern/lib/asm/ASMUtil.java @@ -1,5 +1,8 @@ package com.falsepattern.lib.asm; +import com.falsepattern.lib.asm.exceptions.AsmClassNotFoundException; +import com.falsepattern.lib.asm.exceptions.AsmFieldNotFoundException; +import com.falsepattern.lib.asm.exceptions.AsmMethodNotFoundException; import com.falsepattern.lib.internal.CoreLoadingPlugin; import com.falsepattern.lib.mapping.MappingManager; import com.falsepattern.lib.mapping.types.MappingType; @@ -9,9 +12,15 @@ import com.falsepattern.lib.mapping.types.UniversalField; import com.falsepattern.lib.mapping.types.UniversalMethod; import lombok.SneakyThrows; import lombok.val; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.util.CheckClassAdapter; import java.util.Arrays; import java.util.Objects; @@ -133,6 +142,18 @@ public class ASMUtil { } } + public static ClassNode parseClass(byte[] bytes, int readerFlags) { + val cn = new ClassNode(Opcodes.ASM5); + val reader = new ClassReader(bytes); + reader.accept(cn, readerFlags); + return cn; + } + + public static byte[] serializeClass(ClassNode cn, int writerFlags) { + val writer = new ClassWriter(writerFlags); + return writer.toByteArray(); + } + public static boolean anyEquals(String str, String... options) { for (val option: options) { if (Objects.equals(str, option)) { diff --git a/src/main/java/com/falsepattern/lib/asm/IClassNodeTransformer.java b/src/main/java/com/falsepattern/lib/asm/IClassNodeTransformer.java new file mode 100644 index 0000000..ca155cf --- /dev/null +++ b/src/main/java/com/falsepattern/lib/asm/IClassNodeTransformer.java @@ -0,0 +1,13 @@ +package com.falsepattern.lib.asm; + +import org.objectweb.asm.tree.ClassNode; + +public interface IClassNodeTransformer { + String getName(); + boolean shouldTransform(ClassNode cn, String transformedName, boolean obfuscated); + default int internalSortingOrder() { + return 0; + } + + void transform(ClassNode cn, String transformedName, boolean obfuscated); +} diff --git a/src/main/java/com/falsepattern/lib/asm/SmartTransformer.java b/src/main/java/com/falsepattern/lib/asm/SmartTransformer.java new file mode 100644 index 0000000..811e947 --- /dev/null +++ b/src/main/java/com/falsepattern/lib/asm/SmartTransformer.java @@ -0,0 +1,55 @@ +package com.falsepattern.lib.asm; + +import com.falsepattern.lib.asm.exceptions.AsmTransformException; +import com.falsepattern.lib.internal.CoreLoadingPlugin; +import lombok.val; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + +import net.minecraft.launchwrapper.IClassTransformer; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * An ASM transformation dispatcher utility, inspired by mixins. + */ +public interface SmartTransformer extends IClassTransformer { + Logger logger(); + List transformers(); + @Override + default byte[] transform(String name, String transformedName, byte[] bytes) { + if (bytes == null) { + return null; + } + val transformers = new ArrayList(); + val cn = ASMUtil.parseClass(bytes, ClassReader.EXPAND_FRAMES); + for (val transformer: transformers()) { + if (transformer.shouldTransform(cn, transformedName, CoreLoadingPlugin.isObfuscated())) { + transformers.add(transformer); + } + } + if (transformers.isEmpty()) { + return bytes; + } + transformers.sort(Comparator.comparingInt(IClassNodeTransformer::internalSortingOrder)); + val log = logger(); + for (val transformer: transformers) { + log.debug("Patching {} with {}...", transformedName, transformer.getName()); + try { + transformer.transform(cn, transformedName, CoreLoadingPlugin.isObfuscated()); + } catch (RuntimeException | Error t) { + log.error("Error transforming {} with {}: {}", transformedName, transformer.getName(), t.getMessage()); + throw t; + } catch (Throwable t) { + log.error("Error transforming {} with {}: {}", transformedName, transformer.getName(), t.getMessage()); + throw new RuntimeException(t); + } + } + val result = ASMUtil.serializeClass(cn, ClassWriter.COMPUTE_FRAMES); + log.debug("Patched {} successfully.", transformedName); + return result; + } +} diff --git a/src/main/java/com/falsepattern/lib/asm/AsmClassNotFoundException.java b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmClassNotFoundException.java similarity index 80% rename from src/main/java/com/falsepattern/lib/asm/AsmClassNotFoundException.java rename to src/main/java/com/falsepattern/lib/asm/exceptions/AsmClassNotFoundException.java index 8f60896..80b38f7 100644 --- a/src/main/java/com/falsepattern/lib/asm/AsmClassNotFoundException.java +++ b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmClassNotFoundException.java @@ -1,4 +1,4 @@ -package com.falsepattern.lib.asm; +package com.falsepattern.lib.asm.exceptions; public class AsmClassNotFoundException extends AsmTransformException { public AsmClassNotFoundException(final String clazz) { diff --git a/src/main/java/com/falsepattern/lib/asm/AsmFieldNotFoundException.java b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmFieldNotFoundException.java similarity index 80% rename from src/main/java/com/falsepattern/lib/asm/AsmFieldNotFoundException.java rename to src/main/java/com/falsepattern/lib/asm/exceptions/AsmFieldNotFoundException.java index 2cdc133..cbed56a 100644 --- a/src/main/java/com/falsepattern/lib/asm/AsmFieldNotFoundException.java +++ b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmFieldNotFoundException.java @@ -1,4 +1,4 @@ -package com.falsepattern.lib.asm; +package com.falsepattern.lib.asm.exceptions; public class AsmFieldNotFoundException extends AsmTransformException { public AsmFieldNotFoundException(final String field) { diff --git a/src/main/java/com/falsepattern/lib/asm/AsmMethodNotFoundException.java b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmMethodNotFoundException.java similarity index 80% rename from src/main/java/com/falsepattern/lib/asm/AsmMethodNotFoundException.java rename to src/main/java/com/falsepattern/lib/asm/exceptions/AsmMethodNotFoundException.java index e6d6d4c..98dea8e 100644 --- a/src/main/java/com/falsepattern/lib/asm/AsmMethodNotFoundException.java +++ b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmMethodNotFoundException.java @@ -1,4 +1,4 @@ -package com.falsepattern.lib.asm; +package com.falsepattern.lib.asm.exceptions; public class AsmMethodNotFoundException extends AsmTransformException { public AsmMethodNotFoundException(final String method) { diff --git a/src/main/java/com/falsepattern/lib/asm/AsmTransformException.java b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmTransformException.java similarity index 88% rename from src/main/java/com/falsepattern/lib/asm/AsmTransformException.java rename to src/main/java/com/falsepattern/lib/asm/exceptions/AsmTransformException.java index d7277f8..7dea783 100644 --- a/src/main/java/com/falsepattern/lib/asm/AsmTransformException.java +++ b/src/main/java/com/falsepattern/lib/asm/exceptions/AsmTransformException.java @@ -1,4 +1,4 @@ -package com.falsepattern.lib.asm; +package com.falsepattern.lib.asm.exceptions; public class AsmTransformException extends RuntimeException { public AsmTransformException(final String message) {