From 0d65a16ea653e6dfec3a4c3d97b2e09029daf4ca Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Mon, 2 Sep 2024 02:33:43 +0200 Subject: [PATCH 1/3] add ASMUtil to dump classes --- .../com/gtnewhorizon/gtnhlib/asm/ASMUtil.java | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java diff --git a/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java b/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java new file mode 100644 index 0000000..17dce22 --- /dev/null +++ b/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java @@ -0,0 +1,160 @@ +package com.gtnewhorizon.gtnhlib.asm; + +import net.minecraft.launchwrapper.Launch; +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.util.ASMifier; +import org.objectweb.asm.util.Textifier; +import org.objectweb.asm.util.TraceClassVisitor; + +import java.io.*; +import java.nio.file.Files; + +public class ASMUtil { + + private static final Logger logger = LogManager.getLogger("ASMUtil - GTNHLib"); + private static File outputDir = null; + + private static void emptyClassOutputFolder() { + outputDir = new File(Launch.minecraftHome, "ASM_GTNH"); + try { + FileUtils.deleteDirectory(outputDir); + } catch (IOException ignored) {} + if (!outputDir.exists()) { + //noinspection ResultOfMethodCallIgnored + outputDir.mkdirs(); + } + } + + public static void saveClassToDisk(Class clazz) { + try (InputStream is = clazz.getResourceAsStream('/' + clazz.getName().replace('.', '/') + ".class")) { + final byte[] bytes = getClassBytes(is); + ASMUtil.saveTransformedClass(bytes, clazz.getName()); + } catch (IOException e) { + logger.error("Couldn't load bytes of " + clazz.getName(), e); + } + } + + private static byte[] getClassBytes(InputStream is) throws IOException { + if (is == null) { + throw new IOException("Class not found"); + } + byte[] b = new byte[is.available()]; + int len = 0; + while (true) { + int n = is.read(b, len, b.length - len); + if (n == -1) { + if (len < b.length) { + byte[] c = new byte[len]; + System.arraycopy(b, 0, c, 0, len); + b = c; + } + return b; + } + len += n; + if (len == b.length) { + int last = is.read(); + if (last < 0) { + return b; + } + byte[] c = new byte[b.length + 1000]; + System.arraycopy(b, 0, c, 0, len); + c[len++] = (byte) last; + b = c; + } + } + } + + public static void saveTransformedClass(final byte[] classBytes, final String transformedName) { + final String fileName = transformedName.replace('.', File.separatorChar); + saveAsRawClassFile(classBytes, transformedName, fileName); + saveAsBytecodeFile(classBytes, transformedName, fileName); + saveAsASMFile(classBytes, transformedName, fileName); + } + + public static void saveAsRawClassFile(byte[] classBytes, String transformedName) { + final String fileName = transformedName.replace('.', File.separatorChar); + ASMUtil.saveAsRawClassFile(classBytes, transformedName, fileName); + } + + public static void saveAsRawClassFile(byte[] classBytes, String transformedName, String fileName) { + if (outputDir == null) { + emptyClassOutputFolder(); + } + final File classFile = new File(outputDir, fileName + ".class"); + final File outDir = classFile.getParentFile(); + if (!outDir.exists()) { + //noinspection ResultOfMethodCallIgnored + outDir.mkdirs(); + } + if (classFile.exists()) { + //noinspection ResultOfMethodCallIgnored + classFile.delete(); + } + try (final OutputStream output = Files.newOutputStream(classFile.toPath())) { + output.write(classBytes); + logger.info("Saved class (byte[]) to " + classFile.toPath()); + } catch (IOException e) { + logger.error("Could not save class (byte[]) " + transformedName, e); + } + } + + public static void saveAsBytecodeFile(byte[] classBytes, String transformedName) { + final String fileName = transformedName.replace('.', File.separatorChar); + ASMUtil.saveAsBytecodeFile(classBytes, transformedName, fileName); + } + + public static void saveAsBytecodeFile(byte[] data, String transformedName, String fileName) { + if (outputDir == null) { + emptyClassOutputFolder(); + } + final File bytecodeFile = new File(outputDir, fileName + "_BYTECODE.txt"); + final File outDir = bytecodeFile.getParentFile(); + if (!outDir.exists()) { + //noinspection ResultOfMethodCallIgnored + outDir.mkdirs(); + } + if (bytecodeFile.exists()) { + //noinspection ResultOfMethodCallIgnored + bytecodeFile.delete(); + } + try (final OutputStream output = Files.newOutputStream(bytecodeFile.toPath())) { + final ClassReader classReader = new ClassReader(data); + classReader.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(output)), 0); + logger.info("Saved class (bytecode) to " + bytecodeFile.toPath()); + } catch (IOException e) { + logger.error("Could not save class (bytecode) " + transformedName, e); + } + } + + public static void saveAsASMFile(byte[] classBytes, String transformedName) { + final String fileName = transformedName.replace('.', File.separatorChar); + ASMUtil.saveAsASMFile(classBytes, transformedName, fileName); + } + + public static void saveAsASMFile(byte[] data, String transformedName, String fileName) { + if (outputDir == null) { + emptyClassOutputFolder(); + } + final File asmifiedFile = new File(outputDir, fileName + "_ASM.txt"); + final File outDir = asmifiedFile.getParentFile(); + if (!outDir.exists()) { + //noinspection ResultOfMethodCallIgnored + outDir.mkdirs(); + } + if (asmifiedFile.exists()) { + //noinspection ResultOfMethodCallIgnored + asmifiedFile.delete(); + } + try (final OutputStream output = Files.newOutputStream(asmifiedFile.toPath())) { + final ClassReader classReader = new ClassReader(data); + classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(output)), 0); + logger.info("Saved class (ASMified) to " + asmifiedFile.toPath()); + } catch (IOException e) { + logger.error("Could not save class (ASMified) " + transformedName, e); + } + } + +} From 4a38312c44e5d096e58cc1bed1cad3592aa1b0da Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 03:05:26 +0200 Subject: [PATCH 2/3] spotlessApply (#64) Co-authored-by: GitHub GTNH Actions <> --- .../com/gtnewhorizon/gtnhlib/asm/ASMUtil.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java b/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java index 17dce22..34bba9c 100644 --- a/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java +++ b/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java @@ -1,6 +1,10 @@ package com.gtnewhorizon.gtnhlib.asm; +import java.io.*; +import java.nio.file.Files; + import net.minecraft.launchwrapper.Launch; + import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -9,9 +13,6 @@ import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceClassVisitor; -import java.io.*; -import java.nio.file.Files; - public class ASMUtil { private static final Logger logger = LogManager.getLogger("ASMUtil - GTNHLib"); @@ -23,7 +24,7 @@ private static void emptyClassOutputFolder() { FileUtils.deleteDirectory(outputDir); } catch (IOException ignored) {} if (!outputDir.exists()) { - //noinspection ResultOfMethodCallIgnored + // noinspection ResultOfMethodCallIgnored outputDir.mkdirs(); } } @@ -86,11 +87,11 @@ public static void saveAsRawClassFile(byte[] classBytes, String transformedName, final File classFile = new File(outputDir, fileName + ".class"); final File outDir = classFile.getParentFile(); if (!outDir.exists()) { - //noinspection ResultOfMethodCallIgnored + // noinspection ResultOfMethodCallIgnored outDir.mkdirs(); } if (classFile.exists()) { - //noinspection ResultOfMethodCallIgnored + // noinspection ResultOfMethodCallIgnored classFile.delete(); } try (final OutputStream output = Files.newOutputStream(classFile.toPath())) { @@ -113,11 +114,11 @@ public static void saveAsBytecodeFile(byte[] data, String transformedName, Strin final File bytecodeFile = new File(outputDir, fileName + "_BYTECODE.txt"); final File outDir = bytecodeFile.getParentFile(); if (!outDir.exists()) { - //noinspection ResultOfMethodCallIgnored + // noinspection ResultOfMethodCallIgnored outDir.mkdirs(); } if (bytecodeFile.exists()) { - //noinspection ResultOfMethodCallIgnored + // noinspection ResultOfMethodCallIgnored bytecodeFile.delete(); } try (final OutputStream output = Files.newOutputStream(bytecodeFile.toPath())) { @@ -141,11 +142,11 @@ public static void saveAsASMFile(byte[] data, String transformedName, String fil final File asmifiedFile = new File(outputDir, fileName + "_ASM.txt"); final File outDir = asmifiedFile.getParentFile(); if (!outDir.exists()) { - //noinspection ResultOfMethodCallIgnored + // noinspection ResultOfMethodCallIgnored outDir.mkdirs(); } if (asmifiedFile.exists()) { - //noinspection ResultOfMethodCallIgnored + // noinspection ResultOfMethodCallIgnored asmifiedFile.delete(); } try (final OutputStream output = Files.newOutputStream(asmifiedFile.toPath())) { From 86bfc637bf6261f4c6defb81d94c294c4e2154bb Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Mon, 2 Sep 2024 03:07:14 +0200 Subject: [PATCH 3/3] wildcard import --- src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java b/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java index 34bba9c..cd1d688 100644 --- a/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java +++ b/src/main/java/com/gtnewhorizon/gtnhlib/asm/ASMUtil.java @@ -1,6 +1,10 @@ package com.gtnewhorizon.gtnhlib.asm; -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; import java.nio.file.Files; import net.minecraft.launchwrapper.Launch;