From 5adfff6dc7cd7b3e8ea20c4f99d087fa9d64f3ef Mon Sep 17 00:00:00 2001 From: Zetrith Date: Thu, 19 Oct 2023 23:19:20 +0200 Subject: [PATCH] Version 0.9.1, fix desyncs related to method names in traces --- Source/Client/MultiplayerStatic.cs | 4 ++- Source/Common/DeferredStackTracingImpl.cs | 6 ++--- Source/Common/Native.cs | 30 +++++++++++++++++++---- Source/Common/Version.cs | 4 +-- Source/TestsOnMono/Program.cs | 16 +++++++++--- Source/TestsOnMono/TestsOnMono.csproj | 1 + 6 files changed, 47 insertions(+), 14 deletions(-) diff --git a/Source/Client/MultiplayerStatic.cs b/Source/Client/MultiplayerStatic.cs index 57bf6db2..062c7140 100644 --- a/Source/Client/MultiplayerStatic.cs +++ b/Source/Client/MultiplayerStatic.cs @@ -33,7 +33,7 @@ public static class MultiplayerStatic public static readonly Texture2D DiscordIcon = ContentFinder.Get("Multiplayer/Discord"); public static readonly Texture2D Pulse = ContentFinder.Get("Multiplayer/Pulse"); - public static readonly Texture2D ChangeRelationIcon = ContentFinder.Get("UI/Memes/Loyalist"); + public static readonly Texture2D ChangeRelationIcon = ContentFinder.Get("UI/Icons/VisitorsHelp"); static MultiplayerStatic() { @@ -48,6 +48,8 @@ static MultiplayerStatic() } ); + Native.HarmonyOriginalGetter = MpUtil.GetOriginalFromHarmonyReplacement; + // UnityEngine.Debug.Log instead of Verse.Log.Message because the server runs on its own thread ServerLog.info = str => Debug.Log($"MpServerLog: {str}"); ServerLog.error = str => Debug.Log($"MpServerLog Error: {str}"); diff --git a/Source/Common/DeferredStackTracingImpl.cs b/Source/Common/DeferredStackTracingImpl.cs index 8e5cdd43..53a86fce 100644 --- a/Source/Common/DeferredStackTracingImpl.cs +++ b/Source/Common/DeferredStackTracingImpl.cs @@ -96,7 +96,7 @@ public unsafe static int TraceImpl(long[] traceIn, ref int hash) trace[depth] = ret; - if (depth < HashInfluence) + if (depth < HashInfluence && info.nameHash != 0) hash = HashCombineInt(hash, (int)info.nameHash); if (++depth == MaxDepth) @@ -135,7 +135,7 @@ static long UpdateNewElement(ref AddrInfo info, long ret) info.stackUsage = stackUsage; var rawName = Native.MethodNameFromAddr(ret, true); // Use the original instead of replacement for hashing - info.nameHash = rawName != null ? StableStringHash(rawName) : 1; + info.nameHash = rawName != null ? Native.GetMethodAggressiveInlining(ret) ? 0 : StableStringHash(rawName) : 1; hashtableEntries++; if (hashtableEntries > hashtableSize * LoadFactor) @@ -179,7 +179,7 @@ static int ResizeHashtable() return indexmask; } - unsafe static long GetStackUsage(long addr) + static unsafe long GetStackUsage(long addr) { var ji = Native.mono_jit_info_table_find(Native.DomainPtr, (IntPtr)addr); diff --git a/Source/Common/Native.cs b/Source/Common/Native.cs index 290aad7a..76db753e 100644 --- a/Source/Common/Native.cs +++ b/Source/Common/Native.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using HarmonyLib; namespace Multiplayer.Client { @@ -19,6 +20,8 @@ public enum NativeOS // current_thread->internal_thread->thread_info->tls[4] public static long LmfPtr { get; private set; } + public static Func? HarmonyOriginalGetter { get; set; } + public static void EarlyInit(NativeOS os) { if (os == NativeOS.Linux) @@ -70,7 +73,7 @@ public static unsafe void InitLmfPtr(NativeOS os) } } - public static string MethodNameFromAddr(long addr, bool harmonyOriginals) + public static string? MethodNameFromAddr(long addr, bool harmonyOriginals) { var domain = DomainPtr; var ji = mono_jit_info_table_find(domain, (IntPtr)addr); @@ -80,11 +83,11 @@ public static string MethodNameFromAddr(long addr, bool harmonyOriginals) var ptrToPrint = mono_jit_info_get_method(ji); var codeStart = (long)mono_jit_info_get_code_start(ji); - if (harmonyOriginals) + if (harmonyOriginals && HarmonyOriginalGetter != null) { - // var original = MpUtil.GetOriginalFromHarmonyReplacement(codeStart); - // if (original != null) - // ptrToPrint = original.MethodHandle.Value; + var original = HarmonyOriginalGetter(codeStart); + if (original != null) + ptrToPrint = original.MethodHandle.Value; } var name = mono_debug_print_stack_frame(ptrToPrint, -1, domain); @@ -92,6 +95,23 @@ public static string MethodNameFromAddr(long addr, bool harmonyOriginals) return string.IsNullOrEmpty(name) ? null : name; } + private static ConstructorInfo RuntimeMethodHandleCtor = AccessTools.Constructor(typeof(RuntimeMethodHandle), new[]{typeof(IntPtr)}); + + public static bool GetMethodAggressiveInlining(long addr) + { + var domain = DomainPtr; + var ji = mono_jit_info_table_find(domain, (IntPtr)addr); + + if (ji == IntPtr.Zero) return false; + + var methodHandle = mono_jit_info_get_method(ji); + var methodInfo = + MethodBase.GetMethodFromHandle((RuntimeMethodHandle)RuntimeMethodHandleCtor.Invoke(new[] { (object)methodHandle })); + + return (methodInfo.MethodImplementationFlags & MethodImplAttributes.AggressiveInlining) != 0; + } + + // const string MonoWindows = "mono-2.0-sgen.dll"; const string MonoWindows = "mono-2.0-bdwgc"; const string MonoLinux = "libmonobdwgc-2.0.so"; const string MonoOSX = "libmonobdwgc-2.0.dylib"; diff --git a/Source/Common/Version.cs b/Source/Common/Version.cs index 88d4297c..132182a9 100644 --- a/Source/Common/Version.cs +++ b/Source/Common/Version.cs @@ -2,8 +2,8 @@ namespace Multiplayer.Common { public static class MpVersion { - public const string Version = "0.9"; - public const int Protocol = 34; + public const string Version = "0.9.1"; + public const int Protocol = 35; public const string ApiAssemblyName = "0MultiplayerAPI"; diff --git a/Source/TestsOnMono/Program.cs b/Source/TestsOnMono/Program.cs index ae06c9bb..ac302a1e 100644 --- a/Source/TestsOnMono/Program.cs +++ b/Source/TestsOnMono/Program.cs @@ -1,25 +1,35 @@ using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using HarmonyLib; using Multiplayer.Client; using Multiplayer.Client.Desyncs; class Program { - public static unsafe void Main(string[] args) + public static void Main(string[] args) { Native.mini_parse_debug_option("disable_omit_fp"); Native.InitLmfPtr(Native.NativeOS.Dummy); Native.EarlyInit(Native.NativeOS.Dummy); - Test(); + Test1(); } public static void Test() { int hash = 0; - long[] trace = new long[32]; + long[] trace = new long[8]; DeferredStackTracingImpl.TraceImpl(trace, ref hash); + Console.WriteLine(hash); foreach (long l in trace) Console.WriteLine(Native.MethodNameFromAddr(l, false)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.NoInlining)] + public static void Test1() + { + Test(); + } } diff --git a/Source/TestsOnMono/TestsOnMono.csproj b/Source/TestsOnMono/TestsOnMono.csproj index 0c139e47..c113fa1f 100644 --- a/Source/TestsOnMono/TestsOnMono.csproj +++ b/Source/TestsOnMono/TestsOnMono.csproj @@ -10,6 +10,7 @@ +