mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-29 11:41:36 +01:00
[ci skip] Put mappings util in a separate class to the stacktrace deobfuscator (#6230)
This commit is contained in:
parent
d3ba412286
commit
4ca56ff079
@ -157,60 +157,49 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ return new StacktraceDeobfuscatingRewritePolicy();
|
+ return new StacktraceDeobfuscatingRewritePolicy();
|
||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
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/ObfHelper.java b/src/main/java/io/papermc/paper/util/ObfHelper.java
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
+++ b/src/main/java/io/papermc/paper/util/ObfHelper.java
|
||||||
@@ -0,0 +0,0 @@
|
@@ -0,0 +0,0 @@
|
||||||
+package io.papermc.paper.util;
|
+package io.papermc.paper.util;
|
||||||
+
|
+
|
||||||
+import com.destroystokyo.paper.PaperConfig;
|
|
||||||
+import com.google.common.base.Charsets;
|
+import com.google.common.base.Charsets;
|
||||||
+import com.google.common.collect.ImmutableMap;
|
+import com.google.common.collect.ImmutableMap;
|
||||||
+import com.mojang.datafixers.util.Pair;
|
+import com.mojang.datafixers.util.Pair;
|
||||||
+import it.unimi.dsi.fastutil.ints.IntArrayList;
|
|
||||||
+import it.unimi.dsi.fastutil.ints.IntList;
|
|
||||||
+import java.io.BufferedReader;
|
+import java.io.BufferedReader;
|
||||||
+import java.io.IOException;
|
+import java.io.IOException;
|
||||||
+import java.io.InputStream;
|
+import java.io.InputStream;
|
||||||
+import java.io.InputStreamReader;
|
+import java.io.InputStreamReader;
|
||||||
+import java.util.Collections;
|
|
||||||
+import java.util.HashMap;
|
|
||||||
+import java.util.LinkedHashMap;
|
|
||||||
+import java.util.Map;
|
+import java.util.Map;
|
||||||
+import net.fabricmc.mapping.tree.ClassDef;
|
+import net.fabricmc.mapping.tree.ClassDef;
|
||||||
+import net.fabricmc.mapping.tree.MethodDef;
|
+import net.fabricmc.mapping.tree.MethodDef;
|
||||||
+import net.fabricmc.mapping.tree.TinyMappingFactory;
|
+import net.fabricmc.mapping.tree.TinyMappingFactory;
|
||||||
+import net.fabricmc.mapping.tree.TinyTree;
|
+import net.fabricmc.mapping.tree.TinyTree;
|
||||||
+import org.jetbrains.annotations.NotNull;
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
+import org.jetbrains.annotations.Nullable;
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
+import org.objectweb.asm.ClassReader;
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
+import org.objectweb.asm.ClassVisitor;
|
|
||||||
+import org.objectweb.asm.Label;
|
|
||||||
+import org.objectweb.asm.MethodVisitor;
|
|
||||||
+import org.objectweb.asm.Opcodes;
|
|
||||||
+
|
+
|
||||||
+public enum StacktraceDeobfuscator {
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public enum ObfHelper {
|
||||||
+ INSTANCE;
|
+ INSTANCE;
|
||||||
+
|
+
|
||||||
+ private static final String MOJANG_PLUS_YARN_NAMESPACE = "mojang+yarn";
|
+ public static final String MOJANG_PLUS_YARN_NAMESPACE = "mojang+yarn";
|
||||||
+ private static final String SPIGOT_NAMESPACE = "spigot";
|
+ public static final String SPIGOT_NAMESPACE = "spigot";
|
||||||
+
|
+
|
||||||
+ private final @Nullable Map<String, ClassMapping> mappings;
|
+ private final @Nullable Map<String, ClassMapping> mappings;
|
||||||
+ private final Map<Class<?>, Map<Pair<String, String>, IntList>> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(64, 0.75f, true) {
|
|
||||||
+ @Override
|
|
||||||
+ protected boolean removeEldestEntry(final Map.Entry<Class<?>, Map<Pair<String, String>, IntList>> eldest) {
|
|
||||||
+ return this.size() > 63;
|
|
||||||
+ }
|
|
||||||
+ });
|
|
||||||
+
|
+
|
||||||
+ StacktraceDeobfuscator() {
|
+ ObfHelper() {
|
||||||
+ this.mappings = loadMappingsIfPresent();
|
+ this.mappings = loadMappingsIfPresent();
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ public @Nullable Map<String, ClassMapping> mappings() {
|
||||||
|
+ return this.mappings;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ private static @Nullable Map<String, ClassMapping> loadMappingsIfPresent() {
|
+ private static @Nullable Map<String, ClassMapping> loadMappingsIfPresent() {
|
||||||
+ try (final InputStream mappingsInputStream = StacktraceDeobfuscator.class.getClassLoader().getResourceAsStream("META-INF/mappings/reobf.tiny")) {
|
+ try (final @Nullable InputStream mappingsInputStream = StacktraceDeobfuscator.class.getClassLoader().getResourceAsStream("META-INF/mappings/reobf.tiny")) {
|
||||||
+ if (mappingsInputStream == null) {
|
+ if (mappingsInputStream == null) {
|
||||||
+ return null;
|
+ return null;
|
||||||
+ }
|
+ }
|
||||||
@ -249,6 +238,55 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ public record ClassMapping(
|
||||||
|
+ String obfName,
|
||||||
|
+ String mojangName,
|
||||||
|
+ Map<Pair<String, String>, MethodMapping> methodMappings
|
||||||
|
+ ) {}
|
||||||
|
+
|
||||||
|
+ public record MethodMapping(
|
||||||
|
+ String obfName,
|
||||||
|
+ String mojangName,
|
||||||
|
+ String descriptor
|
||||||
|
+ ) {}
|
||||||
|
+}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+package io.papermc.paper.util;
|
||||||
|
+
|
||||||
|
+import com.destroystokyo.paper.PaperConfig;
|
||||||
|
+import com.mojang.datafixers.util.Pair;
|
||||||
|
+import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
+import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
+import java.io.IOException;
|
||||||
|
+import java.util.Collections;
|
||||||
|
+import java.util.HashMap;
|
||||||
|
+import java.util.LinkedHashMap;
|
||||||
|
+import java.util.Map;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
+import org.objectweb.asm.ClassReader;
|
||||||
|
+import org.objectweb.asm.ClassVisitor;
|
||||||
|
+import org.objectweb.asm.Label;
|
||||||
|
+import org.objectweb.asm.MethodVisitor;
|
||||||
|
+import org.objectweb.asm.Opcodes;
|
||||||
|
+
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public enum StacktraceDeobfuscator {
|
||||||
|
+ INSTANCE;
|
||||||
|
+
|
||||||
|
+ private final Map<Class<?>, Map<Pair<String, String>, IntList>> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) {
|
||||||
|
+ @Override
|
||||||
|
+ protected boolean removeEldestEntry(final Map.Entry<Class<?>, Map<Pair<String, String>, IntList>> eldest) {
|
||||||
|
+ return this.size() > 127;
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+
|
||||||
+ public void deobfuscateThrowable(final Throwable throwable) {
|
+ public void deobfuscateThrowable(final Throwable throwable) {
|
||||||
+ if (!PaperConfig.deobfuscateStacktraces) {
|
+ if (!PaperConfig.deobfuscateStacktraces) {
|
||||||
+ return;
|
+ return;
|
||||||
@ -269,7 +307,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ return traceElements;
|
+ return traceElements;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if (this.mappings == null || traceElements.length == 0) {
|
+ final @Nullable Map<String, ObfHelper.ClassMapping> mappings = ObfHelper.INSTANCE.mappings();
|
||||||
|
+ if (mappings == null || traceElements.length == 0) {
|
||||||
+ return traceElements;
|
+ return traceElements;
|
||||||
+ }
|
+ }
|
||||||
+ final StackTraceElement[] result = new StackTraceElement[traceElements.length];
|
+ final StackTraceElement[] result = new StackTraceElement[traceElements.length];
|
||||||
@ -279,21 +318,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ final String className = element.getClassName();
|
+ final String className = element.getClassName();
|
||||||
+ final String methodName = element.getMethodName();
|
+ final String methodName = element.getMethodName();
|
||||||
+
|
+
|
||||||
+ final ClassMapping classMapping = this.mappings.get(className);
|
+ final ObfHelper.ClassMapping classMapping = mappings.get(className);
|
||||||
+ if (classMapping == null) {
|
+ if (classMapping == null) {
|
||||||
+ result[i] = element;
|
+ result[i] = element;
|
||||||
+ continue;
|
+ continue;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ final Pair<String, String> nameDescriptorPair;
|
+ final Class<?> clazz;
|
||||||
+ try {
|
+ try {
|
||||||
+ final Class<?> clazz = Class.forName(className);
|
+ clazz = Class.forName(className);
|
||||||
+ nameDescriptorPair = this.determineMethodForLine(clazz, element.getLineNumber());
|
+ } catch (final ClassNotFoundException ex) {
|
||||||
+ } catch (final ReflectiveOperationException ex) {
|
|
||||||
+ throw new RuntimeException(ex);
|
+ throw new RuntimeException(ex);
|
||||||
+ }
|
+ }
|
||||||
+
|
+ final @Nullable Pair<String, String> nameDescriptorPair = this.determineMethodForLine(clazz, element.getLineNumber());
|
||||||
+ final MethodMapping methodMapping = classMapping.methodMappings().get(nameDescriptorPair);
|
+ final ObfHelper.@Nullable MethodMapping methodMapping = nameDescriptorPair == null
|
||||||
|
+ ? null
|
||||||
|
+ : classMapping.methodMappings().get(nameDescriptorPair);
|
||||||
+
|
+
|
||||||
+ result[i] = new StackTraceElement(
|
+ result[i] = new StackTraceElement(
|
||||||
+ element.getClassLoaderName(),
|
+ element.getClassLoaderName(),
|
||||||
@ -301,14 +341,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ element.getModuleVersion(),
|
+ element.getModuleVersion(),
|
||||||
+ classMapping.mojangName(),
|
+ classMapping.mojangName(),
|
||||||
+ methodMapping != null ? methodMapping.mojangName() : methodName,
|
+ methodMapping != null ? methodMapping.mojangName() : methodName,
|
||||||
+ this.mappedFileName(classMapping.mojangName()),
|
+ sourceFileName(classMapping.mojangName()),
|
||||||
+ element.getLineNumber()
|
+ element.getLineNumber()
|
||||||
+ );
|
+ );
|
||||||
+ }
|
+ }
|
||||||
+ return result;
|
+ return result;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ private static @NotNull Map<Pair<String, String>, IntList> buildLineMap(final @NotNull Class<?> key) {
|
+ private @Nullable Pair<String, String> determineMethodForLine(final Class<?> clazz, final int lineNumber) {
|
||||||
|
+ final Map<Pair<String, String>, IntList> lineMap = this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap);
|
||||||
|
+ for (final var entry : lineMap.entrySet()) {
|
||||||
|
+ final Pair<String, String> pair = 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 pair;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return null;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private static String sourceFileName(final String fullClassName) {
|
||||||
|
+ final int dot = fullClassName.lastIndexOf('.');
|
||||||
|
+ final String className = dot == -1
|
||||||
|
+ ? fullClassName
|
||||||
|
+ : fullClassName.substring(dot + 1);
|
||||||
|
+ final String rootClassName = className.split("\\$")[0];
|
||||||
|
+ return rootClassName + ".java";
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private static Map<Pair<String, String>, IntList> buildLineMap(final Class<?> key) {
|
||||||
+ final Map<Pair<String, String>, IntList> lineMap = new HashMap<>();
|
+ final Map<Pair<String, String>, IntList> lineMap = new HashMap<>();
|
||||||
+ final class LineCollectingMethodVisitor extends MethodVisitor {
|
+ final class LineCollectingMethodVisitor extends MethodVisitor {
|
||||||
+ private final IntList lines = new IntArrayList();
|
+ private final IntList lines = new IntArrayList();
|
||||||
@ -347,48 +411,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
+ }
|
+ }
|
||||||
+ return lineMap;
|
+ return lineMap;
|
||||||
+ }
|
+ }
|
||||||
+
|
|
||||||
+ private @Nullable Pair<String, String> determineMethodForLine(final @NotNull Class<?> clazz, final int lineNumber) {
|
|
||||||
+ final Map<Pair<String, String>, IntList> lineMap = this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap);
|
|
||||||
+ for (final var entry : lineMap.entrySet()) {
|
|
||||||
+ final Pair<String, String> pair = 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 pair;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return null;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private @NotNull String mappedFileName(final @NotNull String fullClassName) {
|
|
||||||
+ final int dot = fullClassName.lastIndexOf('.');
|
|
||||||
+ final String className = dot == -1
|
|
||||||
+ ? fullClassName
|
|
||||||
+ : fullClassName.substring(dot + 1);
|
|
||||||
+ final String rootClassName = className.split("\\$")[0];
|
|
||||||
+ return rootClassName + ".java";
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public record ClassMapping(
|
|
||||||
+ String obfName,
|
|
||||||
+ String mojangName,
|
|
||||||
+ Map<Pair<String, String>, MethodMapping> methodMappings
|
|
||||||
+ ) {
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public record MethodMapping(
|
|
||||||
+ String obfName,
|
|
||||||
+ String mojangName,
|
|
||||||
+ String descriptor
|
|
||||||
+ ) {
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public @Nullable Map<String, ClassMapping> mappings() {
|
|
||||||
+ return mappings;
|
|
||||||
+ }
|
|
||||||
+}
|
+}
|
||||||
diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java
|
diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
@ -444,7 +466,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
com.destroystokyo.paper.PaperConfig.registerCommands();
|
com.destroystokyo.paper.PaperConfig.registerCommands();
|
||||||
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
|
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
|
||||||
io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider
|
io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider
|
||||||
+ io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.getClass(); // load mappings for stacktrace deobf
|
+ io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // load mappings for stacktrace deobf and etc.
|
||||||
// Paper end
|
// Paper end
|
||||||
|
|
||||||
this.setPvpAllowed(dedicatedserverproperties.pvp);
|
this.setPvpAllowed(dedicatedserverproperties.pvp);
|
||||||
|
@ -130,16 +130,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
this.maxDuration = maxRunTime;
|
this.maxDuration = maxRunTime;
|
||||||
this.entryCondition = requiredMemoryState;
|
this.entryCondition = requiredMemoryState;
|
||||||
+ // Paper start - configurable behavior tick rate and timings
|
+ // Paper start - configurable behavior tick rate and timings
|
||||||
+ Map<String, io.papermc.paper.util.StacktraceDeobfuscator.ClassMapping> mappings = io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.mappings();
|
+ String key = this.getClass().getSimpleName();
|
||||||
+ String key;
|
+ final var mappings = io.papermc.paper.util.ObfHelper.INSTANCE.mappings();
|
||||||
+ if (mappings != null) {
|
+ if (mappings != null) {
|
||||||
+ key = mappings.get(getClass().getName()).mojangName();
|
+ final var classMapping = mappings.get(this.getClass().getName());
|
||||||
|
+ if (classMapping != null) {
|
||||||
|
+ key = classMapping.mojangName();
|
||||||
+ int lastSeparator = key.lastIndexOf('.');
|
+ int lastSeparator = key.lastIndexOf('.');
|
||||||
+ if (lastSeparator != -1) {
|
+ if (lastSeparator != -1) {
|
||||||
+ key = key.substring(lastSeparator + 1);
|
+ key = key.substring(lastSeparator + 1);
|
||||||
+ }
|
+ }
|
||||||
+ } else {
|
+ }
|
||||||
+ key = getClass().getSimpleName();
|
|
||||||
+ }
|
+ }
|
||||||
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
||||||
+ this.timing = co.aikar.timings.MinecraftTimings.getBehaviorTimings(configKey);
|
+ this.timing = co.aikar.timings.MinecraftTimings.getBehaviorTimings(configKey);
|
||||||
@ -196,16 +197,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
|
|
||||||
public Sensor(int senseInterval) {
|
public Sensor(int senseInterval) {
|
||||||
+ // Paper start - configurable sensor tick rate and timings
|
+ // Paper start - configurable sensor tick rate and timings
|
||||||
+ java.util.Map<String, io.papermc.paper.util.StacktraceDeobfuscator.ClassMapping> mappings = io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.mappings();
|
+ String key = this.getClass().getSimpleName();
|
||||||
+ String key;
|
+ final var mappings = io.papermc.paper.util.ObfHelper.INSTANCE.mappings();
|
||||||
+ if (mappings != null) {
|
+ if (mappings != null) {
|
||||||
+ key = mappings.get(getClass().getName()).mojangName();
|
+ final var classMapping = mappings.get(this.getClass().getName());
|
||||||
|
+ if (classMapping != null) {
|
||||||
|
+ key = classMapping.mojangName();
|
||||||
+ int lastSeparator = key.lastIndexOf('.');
|
+ int lastSeparator = key.lastIndexOf('.');
|
||||||
+ if (lastSeparator != -1) {
|
+ if (lastSeparator != -1) {
|
||||||
+ key = key.substring(lastSeparator + 1);
|
+ key = key.substring(lastSeparator + 1);
|
||||||
+ }
|
+ }
|
||||||
+ } else {
|
+ }
|
||||||
+ key = getClass().getSimpleName();
|
|
||||||
+ }
|
+ }
|
||||||
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
||||||
+ this.timing = co.aikar.timings.MinecraftTimings.getSensorTimings(configKey);
|
+ this.timing = co.aikar.timings.MinecraftTimings.getSensorTimings(configKey);
|
||||||
|
Loading…
Reference in New Issue
Block a user