From 13890cefd7a9ad6f4e400c7c07e7fc3a5fe208d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 13 Dec 2024 10:12:52 +0100 Subject: [PATCH 1/2] Fix calling convention mismatch in GC callouts Fixes #110607. The native side expects fastcall. Filed #110684 on the test hole. We would have caught it during x86 bringup if this had _any_ tests since this is a guaranteed stack corruption and crash. --- .../TrackerObjectManager.NativeAot.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs index 2e2674fb0e1f8b..6bd46ffed15257 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs @@ -137,9 +137,9 @@ public static void EndReferenceTracking() public static unsafe void RegisterGCCallbacks() { - delegate* unmanaged gcStartCallback = &GCStartCollection; - delegate* unmanaged gcStopCallback = &GCStopCollection; - delegate* unmanaged gcAfterMarkCallback = &GCAfterMarkPhase; + delegate* unmanaged[Fastcall] gcStartCallback = &GCStartCollection; + delegate* unmanaged[Fastcall] gcStopCallback = &GCStopCollection; + delegate* unmanaged[Fastcall] gcAfterMarkCallback = &GCAfterMarkPhase; if (!RuntimeImports.RhRegisterGcCallout(RuntimeImports.GcRestrictedCalloutKind.StartCollection, (IntPtr)gcStartCallback) || !RuntimeImports.RhRegisterGcCallout(RuntimeImports.GcRestrictedCalloutKind.EndCollection, (IntPtr)gcStopCallback) || @@ -155,7 +155,7 @@ public static bool AddReferencePath(object target, object foundReference) } // Used during GC callback - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvFastcall)])] private static void GCStartCollection(int condemnedGeneration) { if (condemnedGeneration >= 2) @@ -167,7 +167,7 @@ private static void GCStartCollection(int condemnedGeneration) } // Used during GC callback - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvFastcall)])] private static void GCStopCollection(int condemnedGeneration) { if (condemnedGeneration >= 2) @@ -177,7 +177,7 @@ private static void GCStopCollection(int condemnedGeneration) } // Used during GC callback - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvFastcall)])] private static void GCAfterMarkPhase(int condemnedGeneration) { DetachNonPromotedObjects(); From 37ce31cde49de3cffea8d199c64b259f6603d023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Mon, 16 Dec 2024 07:07:44 +0100 Subject: [PATCH 2/2] Change native side instead --- src/coreclr/nativeaot/Runtime/RestrictedCallouts.h | 2 +- .../TrackerObjectManager.NativeAot.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h b/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h index 2c1a2e61e0951b..cf0295db456038 100644 --- a/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h +++ b/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h @@ -97,6 +97,6 @@ class RestrictedCallouts static CrstStatic s_sLock; // Prototypes for the callouts. - typedef void (F_CALL_CONV * GcRestrictedCallbackFunction)(uint32_t uiCondemnedGeneration); + typedef void (* GcRestrictedCallbackFunction)(uint32_t uiCondemnedGeneration); typedef CLR_BOOL (* HandleTableRestrictedCallbackFunction)(Object * pObject); }; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs index 6bd46ffed15257..2e2674fb0e1f8b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs @@ -137,9 +137,9 @@ public static void EndReferenceTracking() public static unsafe void RegisterGCCallbacks() { - delegate* unmanaged[Fastcall] gcStartCallback = &GCStartCollection; - delegate* unmanaged[Fastcall] gcStopCallback = &GCStopCollection; - delegate* unmanaged[Fastcall] gcAfterMarkCallback = &GCAfterMarkPhase; + delegate* unmanaged gcStartCallback = &GCStartCollection; + delegate* unmanaged gcStopCallback = &GCStopCollection; + delegate* unmanaged gcAfterMarkCallback = &GCAfterMarkPhase; if (!RuntimeImports.RhRegisterGcCallout(RuntimeImports.GcRestrictedCalloutKind.StartCollection, (IntPtr)gcStartCallback) || !RuntimeImports.RhRegisterGcCallout(RuntimeImports.GcRestrictedCalloutKind.EndCollection, (IntPtr)gcStopCallback) || @@ -155,7 +155,7 @@ public static bool AddReferencePath(object target, object foundReference) } // Used during GC callback - [UnmanagedCallersOnly(CallConvs = [typeof(CallConvFastcall)])] + [UnmanagedCallersOnly] private static void GCStartCollection(int condemnedGeneration) { if (condemnedGeneration >= 2) @@ -167,7 +167,7 @@ private static void GCStartCollection(int condemnedGeneration) } // Used during GC callback - [UnmanagedCallersOnly(CallConvs = [typeof(CallConvFastcall)])] + [UnmanagedCallersOnly] private static void GCStopCollection(int condemnedGeneration) { if (condemnedGeneration >= 2) @@ -177,7 +177,7 @@ private static void GCStopCollection(int condemnedGeneration) } // Used during GC callback - [UnmanagedCallersOnly(CallConvs = [typeof(CallConvFastcall)])] + [UnmanagedCallersOnly] private static void GCAfterMarkPhase(int condemnedGeneration) { DetachNonPromotedObjects();