mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 12:27:59 +01:00
Move obfhelper/stack deobf diff into original patch
This commit is contained in:
parent
e0adb01ddc
commit
e20beef9c7
@ -10,13 +10,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
--- a/build.gradle.kts
|
--- a/build.gradle.kts
|
||||||
+++ b/build.gradle.kts
|
+++ b/build.gradle.kts
|
||||||
@@ -0,0 +0,0 @@ dependencies {
|
@@ -0,0 +0,0 @@ dependencies {
|
||||||
implementation("org.ow2.asm:asm-commons:9.7")
|
testImplementation("org.mockito:mockito-core:5.11.0")
|
||||||
implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") // Paper - config files
|
testImplementation("org.ow2.asm:asm-tree:9.7")
|
||||||
implementation("commons-lang:commons-lang:2.6")
|
testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // Paper - CartesianTest
|
||||||
+ implementation("net.fabricmc:mapping-io:0.5.0") // Paper - needed to read mappings for stacktrace deobfuscation
|
+ implementation("net.neoforged:srgutils:1.0.9") // Paper - mappings handling
|
||||||
runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
|
}
|
||||||
|
|
||||||
runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6")
|
val craftbukkitPackageVersion = "1_20_R4" // Paper
|
||||||
diff --git a/src/log4jPlugins/java/io/papermc/paper/logging/StacktraceDeobfuscatingRewritePolicy.java b/src/log4jPlugins/java/io/papermc/paper/logging/StacktraceDeobfuscatingRewritePolicy.java
|
diff --git a/src/log4jPlugins/java/io/papermc/paper/logging/StacktraceDeobfuscatingRewritePolicy.java b/src/log4jPlugins/java/io/papermc/paper/logging/StacktraceDeobfuscatingRewritePolicy.java
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
@ -99,19 +99,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+
|
+
|
||||||
+import java.io.IOException;
|
+import java.io.IOException;
|
||||||
+import java.io.InputStream;
|
+import java.io.InputStream;
|
||||||
+import java.io.InputStreamReader;
|
|
||||||
+import java.nio.charset.StandardCharsets;
|
|
||||||
+import java.util.HashMap;
|
+import java.util.HashMap;
|
||||||
+import java.util.HashSet;
|
+import java.util.HashSet;
|
||||||
+import java.util.Map;
|
+import java.util.Map;
|
||||||
+import java.util.Objects;
|
+import java.util.Objects;
|
||||||
+import java.util.Set;
|
+import java.util.Set;
|
||||||
+import java.util.function.Function;
|
|
||||||
+import java.util.stream.Collectors;
|
+import java.util.stream.Collectors;
|
||||||
+import net.fabricmc.mappingio.MappingReader;
|
+import net.neoforged.srgutils.IMappingFile;
|
||||||
+import net.fabricmc.mappingio.format.MappingFormat;
|
|
||||||
+import net.fabricmc.mappingio.tree.MappingTree;
|
|
||||||
+import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
|
||||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
@ -120,9 +114,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+public enum ObfHelper {
|
+public enum ObfHelper {
|
||||||
+ INSTANCE;
|
+ INSTANCE;
|
||||||
+
|
+
|
||||||
+ public static final String MOJANG_PLUS_YARN_NAMESPACE = "mojang+yarn";
|
|
||||||
+ public static final String SPIGOT_NAMESPACE = "spigot";
|
|
||||||
+
|
|
||||||
+ private final @Nullable Map<String, ClassMapping> mappingsByObfName;
|
+ private final @Nullable Map<String, ClassMapping> mappingsByObfName;
|
||||||
+ private final @Nullable Map<String, ClassMapping> mappingsByMojangName;
|
+ private final @Nullable Map<String, ClassMapping> mappingsByMojangName;
|
||||||
+
|
+
|
||||||
@ -190,56 +181,74 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ if (mappingsInputStream == null) {
|
+ if (mappingsInputStream == null) {
|
||||||
+ return null;
|
+ return null;
|
||||||
+ }
|
+ }
|
||||||
+ final MemoryMappingTree tree = new MemoryMappingTree();
|
+ final IMappingFile mappings = IMappingFile.load(mappingsInputStream); // Mappings are mojang->spigot
|
||||||
+ MappingReader.read(new InputStreamReader(mappingsInputStream, StandardCharsets.UTF_8), MappingFormat.TINY_2_FILE, tree);
|
|
||||||
+ final Set<ClassMapping> classes = new HashSet<>();
|
+ final Set<ClassMapping> classes = new HashSet<>();
|
||||||
+
|
+
|
||||||
+ final StringPool pool = new StringPool();
|
+ final StringPool pool = new StringPool();
|
||||||
+ for (final MappingTree.ClassMapping cls : tree.getClasses()) {
|
+ for (final IMappingFile.IClass cls : mappings.getClasses()) {
|
||||||
+ final Map<String, String> methods = new HashMap<>();
|
+ final Map<String, String> methods = new HashMap<>();
|
||||||
|
+ final Map<String, String> fields = new HashMap<>();
|
||||||
|
+ final Map<String, String> strippedMethods = new HashMap<>();
|
||||||
+
|
+
|
||||||
+ for (final MappingTree.MethodMapping methodMapping : cls.getMethods()) {
|
+ for (final IMappingFile.IMethod methodMapping : cls.getMethods()) {
|
||||||
+ methods.put(
|
+ methods.put(
|
||||||
+ pool.string(methodKey(
|
+ pool.string(methodKey(
|
||||||
+ Objects.requireNonNull(methodMapping.getName(SPIGOT_NAMESPACE)),
|
+ Objects.requireNonNull(methodMapping.getMapped()),
|
||||||
+ Objects.requireNonNull(methodMapping.getDesc(SPIGOT_NAMESPACE))
|
+ Objects.requireNonNull(methodMapping.getMappedDescriptor())
|
||||||
+ )),
|
+ )),
|
||||||
+ pool.string(Objects.requireNonNull(methodMapping.getName(MOJANG_PLUS_YARN_NAMESPACE)))
|
+ pool.string(Objects.requireNonNull(methodMapping.getOriginal()))
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ strippedMethods.put(
|
||||||
|
+ pool.string(pool.string(strippedMethodKey(
|
||||||
|
+ methodMapping.getMapped(),
|
||||||
|
+ methodMapping.getDescriptor()
|
||||||
|
+ ))),
|
||||||
|
+ pool.string(methodMapping.getOriginal())
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ for (final IMappingFile.IField field : cls.getFields()) {
|
||||||
|
+ fields.put(
|
||||||
|
+ pool.string(field.getMapped()),
|
||||||
|
+ pool.string(field.getOriginal())
|
||||||
+ );
|
+ );
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ final ClassMapping map = new ClassMapping(
|
+ final ClassMapping map = new ClassMapping(
|
||||||
+ Objects.requireNonNull(cls.getName(SPIGOT_NAMESPACE)).replace('/', '.'),
|
+ Objects.requireNonNull(cls.getMapped()).replace('/', '.'),
|
||||||
+ Objects.requireNonNull(cls.getName(MOJANG_PLUS_YARN_NAMESPACE)).replace('/', '.'),
|
+ Objects.requireNonNull(cls.getOriginal()).replace('/', '.'),
|
||||||
+ Map.copyOf(methods)
|
+ Map.copyOf(methods),
|
||||||
|
+ Map.copyOf(fields),
|
||||||
|
+ Map.copyOf(strippedMethods)
|
||||||
+ );
|
+ );
|
||||||
+ classes.add(map);
|
+ classes.add(map);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ return Set.copyOf(classes);
|
+ return Set.copyOf(classes);
|
||||||
+ } catch (final IOException ex) {
|
+ } catch (final IOException ex) {
|
||||||
+ System.err.println("Failed to load mappings for stacktrace deobfuscation.");
|
+ System.err.println("Failed to load mappings.");
|
||||||
+ ex.printStackTrace();
|
+ ex.printStackTrace();
|
||||||
+ return null;
|
+ return null;
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ public static String methodKey(final String obfName, final String obfDescriptor) {
|
+ public static String strippedMethodKey(final String methodName, final String methodDescriptor) {
|
||||||
+ return obfName + obfDescriptor;
|
+ final String methodKey = methodKey(methodName, methodDescriptor);
|
||||||
|
+ final int returnDescriptorEnd = methodKey.indexOf(')');
|
||||||
|
+ return methodKey.substring(0, returnDescriptorEnd + 1);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ private static final class StringPool {
|
+ public static String methodKey(final String methodName, final String methodDescriptor) {
|
||||||
+ private final Map<String, String> pool = new HashMap<>();
|
+ return methodName + methodDescriptor;
|
||||||
+
|
|
||||||
+ public String string(final String string) {
|
|
||||||
+ return this.pool.computeIfAbsent(string, Function.identity());
|
|
||||||
+ }
|
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ public record ClassMapping(
|
+ public record ClassMapping(
|
||||||
+ String obfName,
|
+ String obfName,
|
||||||
+ String mojangName,
|
+ String mojangName,
|
||||||
+ Map<String, String> methodsByObf
|
+ Map<String, String> methodsByObf,
|
||||||
|
+ Map<String, String> fieldsByObf,
|
||||||
|
+ // obf name with mapped desc to mapped name. return value is excluded from desc as reflection doesn't use it
|
||||||
|
+ Map<String, String> strippedMethods
|
||||||
+ ) {}
|
+ ) {}
|
||||||
+}
|
+}
|
||||||
diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
||||||
@ -251,12 +260,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+package io.papermc.paper.util;
|
+package io.papermc.paper.util;
|
||||||
+
|
+
|
||||||
+import io.papermc.paper.configuration.GlobalConfiguration;
|
+import io.papermc.paper.configuration.GlobalConfiguration;
|
||||||
+import it.unimi.dsi.fastutil.ints.IntArrayList;
|
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
+import it.unimi.dsi.fastutil.ints.IntList;
|
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
+import java.io.IOException;
|
+import java.io.IOException;
|
||||||
+import java.io.InputStream;
|
+import java.io.InputStream;
|
||||||
+import java.util.Collections;
|
+import java.util.Collections;
|
||||||
+import java.util.HashMap;
|
|
||||||
+import java.util.LinkedHashMap;
|
+import java.util.LinkedHashMap;
|
||||||
+import java.util.Map;
|
+import java.util.Map;
|
||||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
@ -272,9 +280,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+public enum StacktraceDeobfuscator {
|
+public enum StacktraceDeobfuscator {
|
||||||
+ INSTANCE;
|
+ INSTANCE;
|
||||||
+
|
+
|
||||||
+ private final Map<Class<?>, Map<String, IntList>> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) {
|
+ private final Map<Class<?>, Int2ObjectMap<String>> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) {
|
||||||
+ @Override
|
+ @Override
|
||||||
+ protected boolean removeEldestEntry(final Map.Entry<Class<?>, Map<String, IntList>> eldest) {
|
+ protected boolean removeEldestEntry(final Map.Entry<Class<?>, Int2ObjectMap<String>> eldest) {
|
||||||
+ return this.size() > 127;
|
+ return this.size() > 127;
|
||||||
+ }
|
+ }
|
||||||
+ });
|
+ });
|
||||||
@ -339,18 +347,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ private @Nullable String determineMethodForLine(final Class<?> clazz, final int lineNumber) {
|
+ private @Nullable String determineMethodForLine(final Class<?> clazz, final int lineNumber) {
|
||||||
+ final Map<String, IntList> lineMap = this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap);
|
+ return this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap).get(lineNumber);
|
||||||
+ for (final var entry : lineMap.entrySet()) {
|
|
||||||
+ final String methodKey = entry.getKey();
|
|
||||||
+ final IntList lines = entry.getValue();
|
|
||||||
+ for (int i = 0, linesSize = lines.size(); i < linesSize; i++) {
|
|
||||||
+ final int num = lines.getInt(i);
|
|
||||||
+ if (num == lineNumber) {
|
|
||||||
+ return methodKey;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return null;
|
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ private static String sourceFileName(final String fullClassName) {
|
+ private static String sourceFileName(final String fullClassName) {
|
||||||
@ -362,34 +359,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ return rootClassName + ".java";
|
+ return rootClassName + ".java";
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ private static Map<String, IntList> buildLineMap(final Class<?> key) {
|
+ private static Int2ObjectMap<String> buildLineMap(final Class<?> key) {
|
||||||
+ final Map<String, IntList> lineMap = new HashMap<>();
|
+ final StringPool pool = new StringPool();
|
||||||
|
+ final Int2ObjectMap<String> lineMap = new Int2ObjectOpenHashMap<>();
|
||||||
+ final class LineCollectingMethodVisitor extends MethodVisitor {
|
+ final class LineCollectingMethodVisitor extends MethodVisitor {
|
||||||
+ private final IntList lines = new IntArrayList();
|
|
||||||
+ private final String name;
|
+ private final String name;
|
||||||
+ private final String descriptor;
|
+ private final String descriptor;
|
||||||
+
|
+
|
||||||
+ LineCollectingMethodVisitor(String name, String descriptor) {
|
+ LineCollectingMethodVisitor(final String name, final String descriptor) {
|
||||||
+ super(Opcodes.ASM9);
|
+ super(Opcodes.ASM9);
|
||||||
+ this.name = name;
|
+ this.name = name;
|
||||||
+ this.descriptor = descriptor;
|
+ this.descriptor = descriptor;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ @Override
|
+ @Override
|
||||||
+ public void visitLineNumber(int line, Label start) {
|
+ public void visitLineNumber(final int line, final Label start) {
|
||||||
+ super.visitLineNumber(line, start);
|
+ lineMap.put(line, pool.string(ObfHelper.methodKey(this.name, this.descriptor)));
|
||||||
+ this.lines.add(line);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ @Override
|
|
||||||
+ public void visitEnd() {
|
|
||||||
+ super.visitEnd();
|
|
||||||
+ lineMap.put(ObfHelper.methodKey(this.name, this.descriptor), this.lines);
|
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ final ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9) {
|
+ final ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9) {
|
||||||
+ @Override
|
+ @Override
|
||||||
+ public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
+ public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) {
|
||||||
+ return new LineCollectingMethodVisitor(name, descriptor);
|
+ return new LineCollectingMethodVisitor(name, descriptor);
|
||||||
+ }
|
+ }
|
||||||
+ };
|
+ };
|
||||||
@ -411,6 +401,46 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ return lineMap;
|
+ return lineMap;
|
||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/util/StringPool.java b/src/main/java/io/papermc/paper/util/StringPool.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/util/StringPool.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+package io.papermc.paper.util;
|
||||||
|
+
|
||||||
|
+import java.util.HashMap;
|
||||||
|
+import java.util.Map;
|
||||||
|
+import java.util.function.Function;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * De-duplicates {@link String} instances without using {@link String#intern()}.
|
||||||
|
+ *
|
||||||
|
+ * <p>Interning may not be desired as we may want to use the heap for our pool,
|
||||||
|
+ * so it can be garbage collected as normal, etc.</p>
|
||||||
|
+ *
|
||||||
|
+ * <p>Additionally, interning can be slow due to the potentially large size of the
|
||||||
|
+ * pool (as it is shared for the entire JVM), and because most JVMs implement
|
||||||
|
+ * it using JNI.</p>
|
||||||
|
+ */
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public final class StringPool {
|
||||||
|
+ private final Map<String, String> pool;
|
||||||
|
+
|
||||||
|
+ public StringPool() {
|
||||||
|
+ this(new HashMap<>());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public StringPool(final Map<String, String> map) {
|
||||||
|
+ this.pool = map;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public String string(final String string) {
|
||||||
|
+ return this.pool.computeIfAbsent(string, Function.identity());
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java
|
diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/CrashReport.java
|
--- a/src/main/java/net/minecraft/CrashReport.java
|
||||||
|
@ -10,11 +10,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
--- a/build.gradle.kts
|
--- a/build.gradle.kts
|
||||||
+++ b/build.gradle.kts
|
+++ b/build.gradle.kts
|
||||||
@@ -0,0 +0,0 @@ dependencies {
|
@@ -0,0 +0,0 @@ dependencies {
|
||||||
testImplementation("org.mockito:mockito-core:5.11.0")
|
|
||||||
testImplementation("org.ow2.asm:asm-tree:9.7")
|
testImplementation("org.ow2.asm:asm-tree:9.7")
|
||||||
testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // Paper - CartesianTest
|
testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // Paper - CartesianTest
|
||||||
|
implementation("net.neoforged:srgutils:1.0.9") // Paper - mappings handling
|
||||||
+ implementation("net.neoforged:AutoRenamingTool:2.0.3") // Paper - remap plugins
|
+ implementation("net.neoforged:AutoRenamingTool:2.0.3") // Paper - remap plugins
|
||||||
+ implementation("net.neoforged:srgutils:1.0.9") // Paper - remap plugins - bump transitive of ART
|
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+paperweight {
|
+paperweight {
|
||||||
@ -38,9 +37,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
runtime.filterNot { it.asFile.absolutePath == vanilla }
|
runtime.filterNot { it.asFile.absolutePath == vanilla }
|
||||||
}
|
}
|
||||||
|
|
||||||
-tasks.registerRunTask("runShadow") {
|
-tasks.registerRunTask("runServerJar") {
|
||||||
- description = "Spin up a test server from the shadowJar archiveFile"
|
- description = "Spin up a test server from the serverJar archiveFile"
|
||||||
- classpath(tasks.shadowJar.flatMap { it.archiveFile })
|
- classpath(tasks.serverJar.flatMap { it.archiveFile })
|
||||||
+tasks.registerRunTask("runServer") {
|
+tasks.registerRunTask("runServer") {
|
||||||
+ description = "Spin up a test server from the Mojang mapped server jar"
|
+ description = "Spin up a test server from the Mojang mapped server jar"
|
||||||
+ classpath(tasks.includeMappings.flatMap { it.outputJar })
|
+ classpath(tasks.includeMappings.flatMap { it.outputJar })
|
||||||
@ -1377,9 +1376,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ return null;
|
+ return null;
|
||||||
+ }
|
+ }
|
||||||
+ try (final InputStream mappingsInputStream = MappingEnvironment.mappingsStream()) {
|
+ try (final InputStream mappingsInputStream = MappingEnvironment.mappingsStream()) {
|
||||||
final MemoryMappingTree tree = new MemoryMappingTree();
|
final IMappingFile mappings = IMappingFile.load(mappingsInputStream); // Mappings are mojang->spigot
|
||||||
MappingReader.read(new InputStreamReader(mappingsInputStream, StandardCharsets.UTF_8), MappingFormat.TINY_2_FILE, tree);
|
|
||||||
final Set<ClassMapping> classes = new HashSet<>();
|
final Set<ClassMapping> classes = new HashSet<>();
|
||||||
|
|
||||||
diff --git a/src/main/java/io/papermc/paper/util/concurrent/ScalingThreadPool.java b/src/main/java/io/papermc/paper/util/concurrent/ScalingThreadPool.java
|
diff --git a/src/main/java/io/papermc/paper/util/concurrent/ScalingThreadPool.java b/src/main/java/io/papermc/paper/util/concurrent/ScalingThreadPool.java
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
|
@ -9,18 +9,10 @@ diff --git a/build.gradle.kts b/build.gradle.kts
|
|||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/build.gradle.kts
|
--- a/build.gradle.kts
|
||||||
+++ b/build.gradle.kts
|
+++ b/build.gradle.kts
|
||||||
@@ -0,0 +0,0 @@ dependencies {
|
|
||||||
implementation("org.ow2.asm:asm-commons:9.7")
|
|
||||||
implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") // Paper - config files
|
|
||||||
implementation("commons-lang:commons-lang:2.6")
|
|
||||||
- implementation("net.fabricmc:mapping-io:0.5.0") // Paper - needed to read mappings for stacktrace deobfuscation
|
|
||||||
runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
|
|
||||||
|
|
||||||
runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6")
|
|
||||||
@@ -0,0 +0,0 @@ dependencies {
|
@@ -0,0 +0,0 @@ dependencies {
|
||||||
testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // Paper - CartesianTest
|
testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // Paper - CartesianTest
|
||||||
|
implementation("net.neoforged:srgutils:1.0.9") // Paper - mappings handling
|
||||||
implementation("net.neoforged:AutoRenamingTool:2.0.3") // Paper - remap plugins
|
implementation("net.neoforged:AutoRenamingTool:2.0.3") // Paper - remap plugins
|
||||||
implementation("net.neoforged:srgutils:1.0.9") // Paper - remap plugins - bump transitive of ART
|
|
||||||
+ // Paper start - Remap reflection
|
+ // Paper start - Remap reflection
|
||||||
+ val reflectionRewriterVersion = "0.0.1"
|
+ val reflectionRewriterVersion = "0.0.1"
|
||||||
+ implementation("io.papermc:reflection-rewriter:$reflectionRewriterVersion")
|
+ implementation("io.papermc:reflection-rewriter:$reflectionRewriterVersion")
|
||||||
@ -364,165 +356,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
private static final @Nullable String MAPPINGS_HASH = readMappingsHash();
|
private static final @Nullable String MAPPINGS_HASH = readMappingsHash();
|
||||||
private static final boolean REOBF = checkReobf();
|
private static final boolean REOBF = checkReobf();
|
||||||
|
|
||||||
diff --git a/src/main/java/io/papermc/paper/util/ObfHelper.java b/src/main/java/io/papermc/paper/util/ObfHelper.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/io/papermc/paper/util/ObfHelper.java
|
|
||||||
+++ b/src/main/java/io/papermc/paper/util/ObfHelper.java
|
|
||||||
@@ -0,0 +0,0 @@ package io.papermc.paper.util;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
-import java.io.InputStreamReader;
|
|
||||||
-import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
-import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
-import net.fabricmc.mappingio.MappingReader;
|
|
||||||
-import net.fabricmc.mappingio.format.MappingFormat;
|
|
||||||
-import net.fabricmc.mappingio.tree.MappingTree;
|
|
||||||
-import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
|
||||||
+import net.neoforged.srgutils.IMappingFile;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
@@ -0,0 +0,0 @@ import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
public enum ObfHelper {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
- public static final String MOJANG_PLUS_YARN_NAMESPACE = "mojang+yarn";
|
|
||||||
- public static final String SPIGOT_NAMESPACE = "spigot";
|
|
||||||
-
|
|
||||||
private final @Nullable Map<String, ClassMapping> mappingsByObfName;
|
|
||||||
private final @Nullable Map<String, ClassMapping> mappingsByMojangName;
|
|
||||||
|
|
||||||
@@ -0,0 +0,0 @@ public enum ObfHelper {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try (final InputStream mappingsInputStream = MappingEnvironment.mappingsStream()) {
|
|
||||||
- final MemoryMappingTree tree = new MemoryMappingTree();
|
|
||||||
- MappingReader.read(new InputStreamReader(mappingsInputStream, StandardCharsets.UTF_8), MappingFormat.TINY_2_FILE, tree);
|
|
||||||
+ final IMappingFile mappings = IMappingFile.load(mappingsInputStream); // Mappings are mojang->spigot
|
|
||||||
final Set<ClassMapping> classes = new HashSet<>();
|
|
||||||
|
|
||||||
final StringPool pool = new StringPool();
|
|
||||||
- for (final MappingTree.ClassMapping cls : tree.getClasses()) {
|
|
||||||
+ for (final IMappingFile.IClass cls : mappings.getClasses()) {
|
|
||||||
final Map<String, String> methods = new HashMap<>();
|
|
||||||
+ final Map<String, String> fields = new HashMap<>();
|
|
||||||
+ final Map<String, String> strippedMethods = new HashMap<>();
|
|
||||||
|
|
||||||
- for (final MappingTree.MethodMapping methodMapping : cls.getMethods()) {
|
|
||||||
+ for (final IMappingFile.IMethod methodMapping : cls.getMethods()) {
|
|
||||||
methods.put(
|
|
||||||
pool.string(methodKey(
|
|
||||||
- Objects.requireNonNull(methodMapping.getName(SPIGOT_NAMESPACE)),
|
|
||||||
- Objects.requireNonNull(methodMapping.getDesc(SPIGOT_NAMESPACE))
|
|
||||||
+ Objects.requireNonNull(methodMapping.getMapped()),
|
|
||||||
+ Objects.requireNonNull(methodMapping.getMappedDescriptor())
|
|
||||||
)),
|
|
||||||
- pool.string(Objects.requireNonNull(methodMapping.getName(MOJANG_PLUS_YARN_NAMESPACE)))
|
|
||||||
+ pool.string(Objects.requireNonNull(methodMapping.getOriginal()))
|
|
||||||
+ );
|
|
||||||
+
|
|
||||||
+ strippedMethods.put(
|
|
||||||
+ pool.string(pool.string(strippedMethodKey(
|
|
||||||
+ methodMapping.getMapped(),
|
|
||||||
+ methodMapping.getDescriptor()
|
|
||||||
+ ))),
|
|
||||||
+ pool.string(methodMapping.getOriginal())
|
|
||||||
+ );
|
|
||||||
+ }
|
|
||||||
+ for (final IMappingFile.IField field : cls.getFields()) {
|
|
||||||
+ fields.put(
|
|
||||||
+ pool.string(field.getMapped()),
|
|
||||||
+ pool.string(field.getOriginal())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ClassMapping map = new ClassMapping(
|
|
||||||
- Objects.requireNonNull(cls.getName(SPIGOT_NAMESPACE)).replace('/', '.'),
|
|
||||||
- Objects.requireNonNull(cls.getName(MOJANG_PLUS_YARN_NAMESPACE)).replace('/', '.'),
|
|
||||||
- Map.copyOf(methods)
|
|
||||||
+ Objects.requireNonNull(cls.getMapped()).replace('/', '.'),
|
|
||||||
+ Objects.requireNonNull(cls.getOriginal()).replace('/', '.'),
|
|
||||||
+ Map.copyOf(methods),
|
|
||||||
+ Map.copyOf(fields),
|
|
||||||
+ Map.copyOf(strippedMethods)
|
|
||||||
);
|
|
||||||
classes.add(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Set.copyOf(classes);
|
|
||||||
} catch (final IOException ex) {
|
|
||||||
- System.err.println("Failed to load mappings for stacktrace deobfuscation.");
|
|
||||||
+ System.err.println("Failed to load mappings.");
|
|
||||||
ex.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- public static String methodKey(final String obfName, final String obfDescriptor) {
|
|
||||||
- return obfName + obfDescriptor;
|
|
||||||
+ public static String strippedMethodKey(final String methodName, final String methodDescriptor) {
|
|
||||||
+ final String methodKey = methodKey(methodName, methodDescriptor);
|
|
||||||
+ final int returnDescriptorEnd = methodKey.indexOf(')');
|
|
||||||
+ return methodKey.substring(0, returnDescriptorEnd + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static final class StringPool {
|
|
||||||
- private final Map<String, String> pool = new HashMap<>();
|
|
||||||
-
|
|
||||||
- public String string(final String string) {
|
|
||||||
- return this.pool.computeIfAbsent(string, Function.identity());
|
|
||||||
- }
|
|
||||||
+ public static String methodKey(final String methodName, final String methodDescriptor) {
|
|
||||||
+ return methodName + methodDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public record ClassMapping(
|
|
||||||
String obfName,
|
|
||||||
String mojangName,
|
|
||||||
- Map<String, String> methodsByObf
|
|
||||||
+ Map<String, String> methodsByObf,
|
|
||||||
+ Map<String, String> fieldsByObf,
|
|
||||||
+ // obf name with mapped desc to mapped name. return value is excluded from desc as reflection doesn't use it
|
|
||||||
+ Map<String, String> strippedMethods
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
--- a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
||||||
+++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
+++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
||||||
@@ -0,0 +0,0 @@
|
@@ -0,0 +0,0 @@ public enum StacktraceDeobfuscator {
|
||||||
package io.papermc.paper.util;
|
|
||||||
|
|
||||||
import io.papermc.paper.configuration.GlobalConfiguration;
|
|
||||||
-import it.unimi.dsi.fastutil.ints.IntArrayList;
|
|
||||||
-import it.unimi.dsi.fastutil.ints.IntList;
|
|
||||||
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
||||||
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Collections;
|
|
||||||
-import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
@@ -0,0 +0,0 @@ import org.objectweb.asm.Opcodes;
|
|
||||||
public enum StacktraceDeobfuscator {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
- private final Map<Class<?>, Map<String, IntList>> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) {
|
|
||||||
+ private final Map<Class<?>, Int2ObjectMap<String>> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) {
|
|
||||||
@Override
|
|
||||||
- protected boolean removeEldestEntry(final Map.Entry<Class<?>, Map<String, IntList>> eldest) {
|
|
||||||
+ protected boolean removeEldestEntry(final Map.Entry<Class<?>, Int2ObjectMap<String>> eldest) {
|
|
||||||
return this.size() > 127;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
public void deobfuscateThrowable(final Throwable throwable) {
|
public void deobfuscateThrowable(final Throwable throwable) {
|
||||||
@ -542,108 +380,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
if (GlobalConfiguration.get() != null && !GlobalConfiguration.get().logging.deobfuscateStacktraces) { // handle null as true
|
if (GlobalConfiguration.get() != null && !GlobalConfiguration.get().logging.deobfuscateStacktraces) { // handle null as true
|
||||||
return traceElements;
|
return traceElements;
|
||||||
}
|
}
|
||||||
@@ -0,0 +0,0 @@ public enum StacktraceDeobfuscator {
|
|
||||||
}
|
|
||||||
|
|
||||||
private @Nullable String determineMethodForLine(final Class<?> clazz, final int lineNumber) {
|
|
||||||
- final Map<String, IntList> lineMap = this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap);
|
|
||||||
- for (final var entry : lineMap.entrySet()) {
|
|
||||||
- final String methodKey = entry.getKey();
|
|
||||||
- final IntList lines = entry.getValue();
|
|
||||||
- for (int i = 0, linesSize = lines.size(); i < linesSize; i++) {
|
|
||||||
- final int num = lines.getInt(i);
|
|
||||||
- if (num == lineNumber) {
|
|
||||||
- return methodKey;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- return null;
|
|
||||||
+ return this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap).get(lineNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String sourceFileName(final String fullClassName) {
|
|
||||||
@@ -0,0 +0,0 @@ public enum StacktraceDeobfuscator {
|
|
||||||
return rootClassName + ".java";
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static Map<String, IntList> buildLineMap(final Class<?> key) {
|
|
||||||
- final Map<String, IntList> lineMap = new HashMap<>();
|
|
||||||
+ private static Int2ObjectMap<String> buildLineMap(final Class<?> key) {
|
|
||||||
+ final StringPool pool = new StringPool();
|
|
||||||
+ final Int2ObjectMap<String> lineMap = new Int2ObjectOpenHashMap<>();
|
|
||||||
final class LineCollectingMethodVisitor extends MethodVisitor {
|
|
||||||
- private final IntList lines = new IntArrayList();
|
|
||||||
private final String name;
|
|
||||||
private final String descriptor;
|
|
||||||
|
|
||||||
- LineCollectingMethodVisitor(String name, String descriptor) {
|
|
||||||
+ LineCollectingMethodVisitor(final String name, final String descriptor) {
|
|
||||||
super(Opcodes.ASM9);
|
|
||||||
this.name = name;
|
|
||||||
this.descriptor = descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
- public void visitLineNumber(int line, Label start) {
|
|
||||||
- super.visitLineNumber(line, start);
|
|
||||||
- this.lines.add(line);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- @Override
|
|
||||||
- public void visitEnd() {
|
|
||||||
- super.visitEnd();
|
|
||||||
- lineMap.put(ObfHelper.methodKey(this.name, this.descriptor), this.lines);
|
|
||||||
+ public void visitLineNumber(final int line, final Label start) {
|
|
||||||
+ lineMap.put(line, pool.string(ObfHelper.methodKey(this.name, this.descriptor)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9) {
|
|
||||||
@Override
|
|
||||||
- public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
|
||||||
+ public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) {
|
|
||||||
return new LineCollectingMethodVisitor(name, descriptor);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
diff --git a/src/main/java/io/papermc/paper/util/StringPool.java b/src/main/java/io/papermc/paper/util/StringPool.java
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/src/main/java/io/papermc/paper/util/StringPool.java
|
|
||||||
@@ -0,0 +0,0 @@
|
|
||||||
+package io.papermc.paper.util;
|
|
||||||
+
|
|
||||||
+import java.util.HashMap;
|
|
||||||
+import java.util.Map;
|
|
||||||
+import java.util.function.Function;
|
|
||||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * De-duplicates {@link String} instances without using {@link String#intern()}.
|
|
||||||
+ *
|
|
||||||
+ * <p>Interning may not be desired as we may want to use the heap for our pool,
|
|
||||||
+ * so it can be garbage collected as normal, etc.</p>
|
|
||||||
+ *
|
|
||||||
+ * <p>Additionally, interning can be slow due to the potentially large size of the
|
|
||||||
+ * pool (as it is shared for the entire JVM), and because most JVMs implement
|
|
||||||
+ * it using JNI.</p>
|
|
||||||
+ */
|
|
||||||
+@DefaultQualifier(NonNull.class)
|
|
||||||
+public final class StringPool {
|
|
||||||
+ private final Map<String, String> pool;
|
|
||||||
+
|
|
||||||
+ public StringPool() {
|
|
||||||
+ this(new HashMap<>());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public StringPool(final Map<String, String> map) {
|
|
||||||
+ this.pool = map;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public String string(final String string) {
|
|
||||||
+ return this.pool.computeIfAbsent(string, Function.identity());
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
|
diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
|
--- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
|
||||||
|
@ -135,9 +135,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ runtime.filterNot { it.asFile.absolutePath == vanilla }
|
+ runtime.filterNot { it.asFile.absolutePath == vanilla }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+tasks.registerRunTask("runShadow") {
|
+tasks.registerRunTask("runServerJar") {
|
||||||
+ description = "Spin up a test server from the shadowJar archiveFile"
|
+ description = "Spin up a test server from the serverJar archiveFile"
|
||||||
+ classpath(tasks.shadowJar.flatMap { it.archiveFile })
|
+ classpath(tasks.serverJar.flatMap { it.archiveFile })
|
||||||
+ classpath(runtimeClasspathWithoutVanillaServer)
|
+ classpath(runtimeClasspathWithoutVanillaServer)
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
|
Loading…
Reference in New Issue
Block a user