From 6c7e2b02d6acf7fe7427472ccb6523732099c8c7 Mon Sep 17 00:00:00 2001 From: Andreas Pardeike Date: Mon, 10 Feb 2020 03:31:44 +0100 Subject: [PATCH] Fixed IntPtr result buffers for real --- Harmony/GlobalSuppressions.cs | 7 +- Harmony/Internal/MethodPatcher.cs | 36 ++++--- Harmony/Internal/NativeThisPointerCheck.cs | 116 +++++++++++++-------- Harmony/Public/PatchProcessor.cs | 4 +- HarmonyTests/IL/TestMethodBodyReader.cs | 2 +- 5 files changed, 101 insertions(+), 64 deletions(-) diff --git a/Harmony/GlobalSuppressions.cs b/Harmony/GlobalSuppressions.cs index 7cbe047a..55c52344 100644 --- a/Harmony/GlobalSuppressions.cs +++ b/Harmony/GlobalSuppressions.cs @@ -8,4 +8,9 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1825:Avoid zero-length array allocations.")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1813:Avoid unsealed attributes")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types")] \ No newline at end of file +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Code Quality", "IDE0051:Remove unused private members", Justification = "", Scope = "member", Target = "~F:HarmonyLib.Sandbox.SomeStruct.b1")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Code Quality", "IDE0051:Remove unused private members", Justification = "", Scope = "member", Target = "~F:HarmonyLib.Sandbox.SomeStruct.b2")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Code Quality", "IDE0051:Remove unused private members", Justification = "", Scope = "member", Target = "~F:HarmonyLib.Sandbox.SomeStruct.b3")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "", Scope = "member", Target = "~M:HarmonyLib.Sandbox.GetStruct(System.IntPtr,System.IntPtr)~HarmonyLib.Sandbox.SomeStruct")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "", Scope = "member", Target = "~M:HarmonyLib.Sandbox.GetStructReplacement(HarmonyLib.Sandbox,System.IntPtr,System.IntPtr,System.IntPtr)")] diff --git a/Harmony/Internal/MethodPatcher.cs b/Harmony/Internal/MethodPatcher.cs index 22948e0d..ea933816 100644 --- a/Harmony/Internal/MethodPatcher.cs +++ b/Harmony/Internal/MethodPatcher.cs @@ -29,7 +29,6 @@ internal class MethodPatcher readonly List finalizers; readonly int idx; readonly bool firstArgIsReturnBuffer; - readonly OpCode Ldarg_instance; readonly Type returnType; readonly DynamicMethodDefinition patch; readonly ILGenerator il; @@ -58,10 +57,9 @@ internal MethodPatcher(MethodBase original, MethodBase source, List idx = prefixes.Count() + postfixes.Count() + finalizers.Count(); firstArgIsReturnBuffer = NativeThisPointer.NeedsNativeThisPointerFix(original); - Ldarg_instance = firstArgIsReturnBuffer ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0; - if (debug && firstArgIsReturnBuffer) FileLog.Log($"### Special case: Ldarg.0 is return buffer, not instance!"); + if (debug && firstArgIsReturnBuffer) FileLog.Log($"### Special case: extra argument after 'this' is pointer to valuetype (simulate return value)"); returnType = AccessTools.GetReturnedType(original); - patch = CreateDynamicMethod(original, $"_Patch{idx}"); + patch = CreateDynamicMethod(original, $"_Patch{idx}", debug); if (patch == null) throw new Exception("Could not create replacement method"); @@ -107,7 +105,7 @@ internal MethodInfo CreateReplacement(out Dictionary final } if (firstArgIsReturnBuffer) - emitter.Emit(OpCodes.Ldarg_1); // load ref to return value + emitter.Emit(original.IsStatic ? OpCodes.Ldarg_0 : OpCodes.Ldarg_1); // load ref to return value var skipOriginalLabel = il.DefineLabel(); var canHaveJump = AddPrefixes(privateVars, skipOriginalLabel); @@ -116,7 +114,12 @@ internal MethodInfo CreateReplacement(out Dictionary final foreach (var transpiler in transpilers) copier.AddTranspiler(transpiler); if (firstArgIsReturnBuffer) - copier.AddTranspiler(NativeThisPointer.m_ArgumentShiftTranspiler); + { + if (original.IsStatic) + copier.AddTranspiler(NativeThisPointer.m_ArgumentShiftTranspilerStatic); + else + copier.AddTranspiler(NativeThisPointer.m_ArgumentShiftTranspilerInstance); + } var endLabels = new List