From aa175532dfcc0a168293cfd28c63cfca5c717799 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Sat, 15 May 2021 20:03:23 -0700 Subject: [PATCH 01/17] Support checking for overridden methods during P/Invoke inline pass Clear any pending exception when calling a method that may return a pending exception. Rewrite PendingException test to be more direct. --- .../src/System/StubHelpers.cs | 5 ++ src/coreclr/vm/corelib.h | 3 +- src/coreclr/vm/dllimport.cpp | 50 +++++++++++-------- src/coreclr/vm/dllimport.h | 8 ++- src/coreclr/vm/interoplibinterface.h | 7 ++- src/coreclr/vm/interoplibinterface_shared.cpp | 30 ++++++++++- .../ObjectiveC/PendingExceptionTests.cs | 47 +++++++---------- 7 files changed, 96 insertions(+), 54 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 33435681e9e93..2811f5faf3053 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1247,6 +1247,11 @@ internal static void SetPendingExceptionObject(Exception? exception) s_pendingExceptionObject = exception; } + internal static void ClearPendingExceptionObject() + { + s_pendingExceptionObject = null; + } + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IntPtr CreateCustomMarshalerHelper(IntPtr pMD, int paramToken, IntPtr hndManagedType); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index f9e0de124108b..8e7a67b327def 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -997,7 +997,8 @@ DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_SAFEHANDLE, AddToClea DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveViaCleanupList, SM_RefCleanupWorkListElement_Obj_RetVoid) DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) -DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) +DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) +DEFINE_METHOD(STUBHELPERS, CLEAR_PENDING_EXCEPTION_OBJECT, ClearPendingExceptionObject, SM_RetVoid) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr) DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid) diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index b6a8a8031a225..631d85728871e 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -662,6 +662,12 @@ class ILStubState : public StubState } #endif // PROFILING_SUPPORTED + if (SF_IsCheckPendingException(m_dwStubFlags) + && SF_IsForwardStub(m_dwStubFlags)) + { + pcsDispatch->EmitCALL(METHOD__STUBHELPERS__CLEAR_PENDING_EXCEPTION_OBJECT, 0, 0); + } + // For CoreClr, clear the last error before calling the target that returns last error. // There isn't always a way to know the function have failed without checking last error, // in particular on Unix. @@ -2613,8 +2619,10 @@ void PInvokeStaticSigInfo::PreInit(Module* pModule, MethodTable * pMT) // initialize data members m_wFlags = 0; + m_entryPointName = NULL; m_pModule = pModule; m_callConv = CallConvWinApiSentinel; + m_externModref = mdModuleRefNil; SetBestFitMapping (TRUE); SetThrowOnUnmappableChar (FALSE); SetLinkFlags (nlfNone); @@ -2657,7 +2665,7 @@ void PInvokeStaticSigInfo::PreInit(MethodDesc* pMD) } PInvokeStaticSigInfo::PInvokeStaticSigInfo( - _In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName, _Outptr_opt_ LPCUTF8 *pEntryPointName) + _In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName) { CONTRACTL { @@ -2666,7 +2674,7 @@ PInvokeStaticSigInfo::PInvokeStaticSigInfo( } CONTRACTL_END; - DllImportInit(pMD, pLibName, pEntryPointName); + DllImportInit(pMD, pLibName); } PInvokeStaticSigInfo::PInvokeStaticSigInfo(_In_ MethodDesc* pMD) @@ -2684,7 +2692,7 @@ PInvokeStaticSigInfo::PInvokeStaticSigInfo(_In_ MethodDesc* pMD) if (!pMT->IsDelegate()) { - DllImportInit(pMD, NULL, NULL); + DllImportInit(pMD, NULL); return; } @@ -2755,7 +2763,7 @@ PInvokeStaticSigInfo::PInvokeStaticSigInfo( InitCallConv(CallConvWinApiSentinel, FALSE); } -void PInvokeStaticSigInfo::DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *ppLibName, _Outptr_opt_ LPCUTF8 *ppEntryPointName) +void PInvokeStaticSigInfo::DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *ppLibName) { CONTRACTL { @@ -2767,7 +2775,6 @@ void PInvokeStaticSigInfo::DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCU // where pMD->ndirect.m_szLibName was passed in directly, cleared // by this API, then accessed on another thread before being reset here. PRECONDITION(CheckPointer(ppLibName, NULL_OK) && (!ppLibName || *ppLibName == NULL)); - PRECONDITION(CheckPointer(ppEntryPointName, NULL_OK) && (!ppEntryPointName || *ppEntryPointName == NULL)); } CONTRACTL_END; @@ -2777,21 +2784,19 @@ void PInvokeStaticSigInfo::DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCU // System.Runtime.InteropServices.DllImportAttribute IMDInternalImport *pInternalImport = pMD->GetMDImport(); CorPinvokeMap mappingFlags = pmMaxValue; - mdModuleRef modref = mdModuleRefNil; - if (FAILED(pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, ppEntryPointName, &modref))) + if (FAILED(pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, &m_entryPointName, &m_externModref))) { InitCallConv(CallConvWinApiSentinel, pMD->IsVarArg()); return; } - // out parameter pEntryPointName - if (ppEntryPointName && *ppEntryPointName == NULL) - *ppEntryPointName = pMD->GetName(); + if (m_entryPointName == NULL) + m_entryPointName = pMD->GetName(); // out parameter pLibName if (ppLibName != NULL) { - if (FAILED(pInternalImport->GetModuleRefProps(modref, ppLibName))) + if (FAILED(pInternalImport->GetModuleRefProps(m_externModref, ppLibName))) { ThrowError(IDS_CLASSLOAD_BADFORMAT); } @@ -3098,6 +3103,11 @@ HRESULT NDirect::HasNAT_LAttribute(IMDInternalImport *pInternalImport, mdToken t // Either MD or signature & module must be given. +// +// N.B. This method can be called at a time when the associated NDirectMethodDesc +// has not been fully populated. This means the optimized path for this call is to rely +// on the most basic P/Invoke metadata. An example when this can happen is when the JIT +// is compiling a method containing a P/Invoke that is being considered for inlining. /*static*/ BOOL NDirect::MarshalingRequired( _In_opt_ MethodDesc* pMD, @@ -3156,7 +3166,7 @@ BOOL NDirect::MarshalingRequired( #ifndef CROSSGEN_COMPILE // Pending exceptions are handled by stub - if (Interop::ShouldCheckForPendingException(pNMD)) + if (Interop::ShouldCheckForPendingException(pNMD, &sigInfo)) return TRUE; #endif // !CROSSGEN_COMPILE } @@ -4225,7 +4235,7 @@ static void CreateNDirectStubAccessMetadata( namespace { - void PopulateNDirectMethodDescImpl(_Inout_ NDirectMethodDesc* pNMD, _In_ const PInvokeStaticSigInfo& sigInfo, _In_opt_z_ LPCUTF8 libName, _In_opt_z_ LPCUTF8 entryPointName) + void PopulateNDirectMethodDescImpl(_Inout_ NDirectMethodDesc* pNMD, _In_ const PInvokeStaticSigInfo& sigInfo, _In_opt_z_ LPCUTF8 libName) { CONTRACTL { @@ -4260,7 +4270,7 @@ namespace else { pNMD->ndirect.m_pszLibName.SetValueMaybeNull(libName); - pNMD->ndirect.m_pszEntrypointName.SetValueMaybeNull(entryPointName); + pNMD->ndirect.m_pszEntrypointName.SetValueMaybeNull(sigInfo.GetEntryPointName()); } // Call this exactly ONCE per thread. Do not publish incomplete prestub flags @@ -4281,9 +4291,9 @@ void NDirect::PopulateNDirectMethodDesc(_Inout_ NDirectMethodDesc* pNMD) if (pNMD->IsSynchronized()) COMPlusThrow(kTypeLoadException, IDS_EE_NOSYNCHRONIZED); - LPCUTF8 szLibName = NULL, szEntryPointName = NULL; - PInvokeStaticSigInfo sigInfo(pNMD, &szLibName, &szEntryPointName); - PopulateNDirectMethodDescImpl(pNMD, sigInfo, szLibName, szEntryPointName); + LPCUTF8 szLibName = NULL; + PInvokeStaticSigInfo sigInfo(pNMD, &szLibName); + PopulateNDirectMethodDescImpl(pNMD, sigInfo, szLibName); } void NDirect::InitializeSigInfoAndPopulateNDirectMethodDesc(_Inout_ NDirectMethodDesc* pNMD, _Inout_ PInvokeStaticSigInfo* pSigInfo) @@ -4299,10 +4309,10 @@ void NDirect::InitializeSigInfoAndPopulateNDirectMethodDesc(_Inout_ NDirectMetho if (pNMD->IsSynchronized()) COMPlusThrow(kTypeLoadException, IDS_EE_NOSYNCHRONIZED); - LPCUTF8 szLibName = NULL, szEntryPointName = NULL; - new (pSigInfo) PInvokeStaticSigInfo(pNMD, &szLibName, &szEntryPointName); + LPCUTF8 szLibName = NULL; + new (pSigInfo) PInvokeStaticSigInfo(pNMD, &szLibName); - PopulateNDirectMethodDescImpl(pNMD, *pSigInfo, szLibName, szEntryPointName); + PopulateNDirectMethodDescImpl(pNMD, *pSigInfo, szLibName); } #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index d713cb9bb5cc3..b2420caa1f568 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -312,12 +312,12 @@ struct PInvokeStaticSigInfo PInvokeStaticSigInfo(_In_ MethodDesc* pMdDelegate); - PInvokeStaticSigInfo(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName, _Outptr_opt_ LPCUTF8 *pEntryPointName); + PInvokeStaticSigInfo(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName); private: void ThrowError(WORD errorResourceID); void InitCallConv(CorInfoCallConvExtension callConv, BOOL bIsVarArg); - void DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName, _Outptr_opt_ LPCUTF8 *pEntryPointName); + void DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName); void PreInit(Module* pModule, MethodTable *pClass); void PreInit(MethodDesc* pMD); @@ -350,6 +350,8 @@ struct PInvokeStaticSigInfo BOOL IsDelegateInterop() const { LIMITED_METHOD_CONTRACT; return m_wFlags & PINVOKE_STATIC_SIGINFO_IS_DELEGATE_INTEROP; } CorInfoCallConvExtension GetCallConv() const { LIMITED_METHOD_CONTRACT; return m_callConv; } Signature GetSignature() const { LIMITED_METHOD_CONTRACT; return m_sig; } + LPCUTF8 GetEntryPointName() const { LIMITED_METHOD_CONTRACT; return m_entryPointName; } + mdModuleRef GetExternModuleRefToken() const { LIMITED_METHOD_CONTRACT; return m_externModref; } CorNativeLinkType GetCharSet() const { LIMITED_METHOD_CONTRACT; return (CorNativeLinkType)((m_wFlags & COR_NATIVE_LINK_TYPE_MASK) >> COR_NATIVE_LINK_TYPE_SHIFT); } CorNativeLinkFlags GetLinkFlags() const { LIMITED_METHOD_CONTRACT; return (CorNativeLinkFlags)((m_wFlags & COR_NATIVE_LINK_FLAGS_MASK) >> COR_NATIVE_LINK_FLAGS_SHIFT); } @@ -404,7 +406,9 @@ struct PInvokeStaticSigInfo private: Module* m_pModule; Signature m_sig; + LPCUTF8 m_entryPointName; CorInfoCallConvExtension m_callConv; + mdModuleRef m_externModref; WORD m_wFlags; }; diff --git a/src/coreclr/vm/interoplibinterface.h b/src/coreclr/vm/interoplibinterface.h index b3bf554d5d9a3..c0096dee78521 100644 --- a/src/coreclr/vm/interoplibinterface.h +++ b/src/coreclr/vm/interoplibinterface.h @@ -165,11 +165,16 @@ class ObjCMarshalNative #endif // FEATURE_OBJCMARSHAL +// Forward declaration of type. +struct PInvokeStaticSigInfo; + class Interop { public: // Check if pending exceptions are possible for the following native export. - static bool ShouldCheckForPendingException(_In_ NDirectMethodDesc* md); + static bool ShouldCheckForPendingException( + _In_ NDirectMethodDesc* md, + _In_opt_ PInvokeStaticSigInfo* sigInfo = NULL); // A no return callback that is designed to help propagate a managed // exception going from Managed to Native. diff --git a/src/coreclr/vm/interoplibinterface_shared.cpp b/src/coreclr/vm/interoplibinterface_shared.cpp index a36db92805a38..521015f47d47b 100644 --- a/src/coreclr/vm/interoplibinterface_shared.cpp +++ b/src/coreclr/vm/interoplibinterface_shared.cpp @@ -3,12 +3,15 @@ // Runtime headers #include "common.h" +#include "dllimport.h" #include "interoplibinterface.h" using ManagedToNativeExceptionCallback = Interop::ManagedToNativeExceptionCallback; -bool Interop::ShouldCheckForPendingException(_In_ NDirectMethodDesc* md) +bool Interop::ShouldCheckForPendingException( + _In_ NDirectMethodDesc* md, + _In_opt_ PInvokeStaticSigInfo* sigInfo) { CONTRACTL { @@ -22,7 +25,30 @@ bool Interop::ShouldCheckForPendingException(_In_ NDirectMethodDesc* md) PTR_CUTF8 libraryName = md->GetLibNameRaw(); PTR_CUTF8 entrypointName = md->GetEntrypointName(); if (libraryName == NULL || entrypointName == NULL) - return false; + { + // If no sig info was supplied we have no recourse. + if (sigInfo == NULL) + return false; + + if (libraryName == NULL) + { + // If the library name is unknown, see if we can get the token + // from the sig info. + mdModuleRef modRef = sigInfo->GetExternModuleRefToken(); + if (modRef != mdModuleRefNil) + { + IMDInternalImport* mdImport = md->GetMDImport(); + (void)mdImport->GetModuleRefProps(modRef, &libraryName); + } + } + + if (entrypointName == NULL) + entrypointName = sigInfo->GetEntryPointName(); + + // Still no luck so return false. + if (libraryName == NULL || entrypointName == NULL) + return false; + } if (ObjCMarshalNative::IsRuntimeMsgSendFunctionOverridden(libraryName, entrypointName)) return true; diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs index 77e0274383eca..cbb89626c09c1 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs @@ -44,15 +44,6 @@ private static IntPtr SetPendingException([CallerMemberName] string callerName = return IntPtr.Zero; } - private static (MessageSendFunction MsgSend, IntPtr Func)[] msgSendOverrides = - { - (MessageSendFunction.MsgSend, (IntPtr)(delegate* unmanaged)&MsgSend), - (MessageSendFunction.MsgSendFpret, (IntPtr)(delegate* unmanaged)&MsgSendFpret), - (MessageSendFunction.MsgSendStret, (IntPtr)(delegate* unmanaged)&MsgSendStret), - (MessageSendFunction.MsgSendSuper, (IntPtr)(delegate* unmanaged)&MsgSendSuper), - (MessageSendFunction.MsgSendSuperStret, (IntPtr)(delegate* unmanaged)&MsgSendSuperStret), - }; - [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(MessageSendFunction.MsgSend)] [InlineData(MessageSendFunction.MsgSendFpret)] @@ -71,27 +62,27 @@ public void ValidateSetMessageSendPendingException(MessageSendFunction func) }, func.ToString()).Dispose(); } - private static void ValidateSetMessageSendPendingExceptionImpl(MessageSendFunction funcToOverride) + private static void ValidateSetMessageSendPendingExceptionImpl(MessageSendFunction msgSend) { - foreach (var (msgSend, func) in msgSendOverrides) + IntPtr func = msgSend switch { - if (funcToOverride != msgSend) - { - continue; - } - - // Override message send function - ObjectiveCMarshal.SetMessageSendCallback(msgSend, func); - - // Call message send function through P/Invoke - IntPtr inst = IntPtr.Zero; - IntPtr sel = IntPtr.Zero; - - Exception ex = Assert.Throws(() => LibObjC.CallPInvoke(msgSend, inst, sel)); - Assert.Equal(msgSend.ToString(), ex.Message); - - break; - } + MessageSendFunction.MsgSend => (IntPtr)(delegate* unmanaged)&MsgSend, + MessageSendFunction.MsgSendFpret => (IntPtr)(delegate* unmanaged)&MsgSendFpret, + MessageSendFunction.MsgSendStret => (IntPtr)(delegate* unmanaged)&MsgSendStret, + MessageSendFunction.MsgSendSuper => (IntPtr)(delegate* unmanaged)&MsgSendSuper, + MessageSendFunction.MsgSendSuperStret => (IntPtr)(delegate* unmanaged)&MsgSendSuperStret, + _ => throw new Exception($"Unknown {nameof(MessageSendFunction)}"), + }; + + // Override message send function + ObjectiveCMarshal.SetMessageSendCallback(msgSend, func); + + // Call message send function through P/Invoke + IntPtr inst = IntPtr.Zero; + IntPtr sel = IntPtr.Zero; + + Exception ex = Assert.Throws(() => LibObjC.CallPInvoke(msgSend, inst, sel)); + Assert.Equal(msgSend.ToString(), ex.Message); } } } \ No newline at end of file From 2f8e56c8bff831c95fd9e8567f49a738b5e7bb95 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Mon, 17 May 2021 09:17:10 -0700 Subject: [PATCH 02/17] Objective-C runtime msgSend* functions are never inlinable. --- src/coreclr/vm/interoplibinterface.h | 2 +- src/coreclr/vm/interoplibinterface_objc.cpp | 18 ++++++++++-------- src/coreclr/vm/interoplibinterface_shared.cpp | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/coreclr/vm/interoplibinterface.h b/src/coreclr/vm/interoplibinterface.h index c0096dee78521..6225222c8513a 100644 --- a/src/coreclr/vm/interoplibinterface.h +++ b/src/coreclr/vm/interoplibinterface.h @@ -147,7 +147,7 @@ class ObjCMarshalNative static bool IsTrackedReference(_In_ OBJECTREF object, _Out_ bool* isReferenced); public: // Identification - static bool IsRuntimeMsgSendFunctionOverridden( + static bool IsRuntimeMessageSendFunction( _In_z_ const char* libraryName, _In_z_ const char* entrypointName); diff --git a/src/coreclr/vm/interoplibinterface_objc.cpp b/src/coreclr/vm/interoplibinterface_objc.cpp index 131c3c277b81a..92f07759123c8 100644 --- a/src/coreclr/vm/interoplibinterface_objc.cpp +++ b/src/coreclr/vm/interoplibinterface_objc.cpp @@ -127,14 +127,16 @@ namespace OBJC_MSGSEND "Super_stret", }; - const void* STDMETHODCALLTYPE MessageSendPInvokeOverride(_In_z_ const char* libraryName, _In_z_ const char* entrypointName) + bool IsObjectiveCMessageSendFunction(_In_z_ const char* libraryName, _In_z_ const char* entrypointName) { - // All overrides are in libobjc - if (strcmp(libraryName, ObjectiveCLibrary) != 0) - return nullptr; + // Is the function in libobjc and named appropriately. + return ((strcmp(libraryName, ObjectiveCLibrary) == 0) + && (strncmp(entrypointName, OBJC_MSGSEND, _countof(OBJC_MSGSEND) -1) == 0)); + } - // All overrides start with objc_msgSend - if (strncmp(entrypointName, OBJC_MSGSEND, _countof(OBJC_MSGSEND) -1) != 0) + const void* STDMETHODCALLTYPE MessageSendPInvokeOverride(_In_z_ const char* libraryName, _In_z_ const char* entrypointName) + { + if (!IsObjectiveCMessageSendFunction(libraryName, entrypointName)) return nullptr; for (int i = 0; i < _countof(MsgSendEntryPoints); ++i) @@ -227,7 +229,7 @@ bool ObjCMarshalNative::IsTrackedReference(_In_ OBJECTREF object, _Out_ bool* is return true; } -bool ObjCMarshalNative::IsRuntimeMsgSendFunctionOverridden( +bool ObjCMarshalNative::IsRuntimeMessageSendFunction( _In_z_ const char* libraryName, _In_z_ const char* entrypointName) { @@ -240,7 +242,7 @@ bool ObjCMarshalNative::IsRuntimeMsgSendFunctionOverridden( } CONTRACTL_END; - return MessageSendPInvokeOverride(libraryName, entrypointName) != NULL; + return IsObjectiveCMessageSendFunction(libraryName, entrypointName); } namespace diff --git a/src/coreclr/vm/interoplibinterface_shared.cpp b/src/coreclr/vm/interoplibinterface_shared.cpp index 521015f47d47b..ca03670594070 100644 --- a/src/coreclr/vm/interoplibinterface_shared.cpp +++ b/src/coreclr/vm/interoplibinterface_shared.cpp @@ -50,7 +50,7 @@ bool Interop::ShouldCheckForPendingException( return false; } - if (ObjCMarshalNative::IsRuntimeMsgSendFunctionOverridden(libraryName, entrypointName)) + if (ObjCMarshalNative::IsRuntimeMessageSendFunction(libraryName, entrypointName)) return true; #endif // FEATURE_OBJCMARSHAL From ce002599b539fd3d6e0408e446e03db8dabf1fd5 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 17 May 2021 11:53:36 -0700 Subject: [PATCH 03/17] Update CrossGen2. --- .../TypeSystem/Interop/MethodDesc.Interop.cs | 15 +++++++++++++++ .../IL/Stubs/PInvokeILEmitter.cs | 5 ++++- .../Interop/IL/Marshaller.ReadyToRun.cs | 6 +++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs b/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs index 6444ca97c8721..0da037bb4a1d7 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs @@ -347,6 +347,21 @@ public PInvokeMetadata(string module, string entrypoint, PInvokeFlags flags) Module = module; Flags = flags; } + + public bool CheckPendingException() + { + const string ObjectiveCLibrary = "/usr/lib/libobjc.dylib"; + const string ObjectiveCMsgSend = "objc_msgSend"; + + // This is for the objc_msgSend suite of functions. + // objc_msgSend + // objc_msgSend_fpret + // objc_msgSend_stret + // objc_msgSendSuper + // objc_msgSendSuper_stret + return Module.Equals(ObjectiveCLibrary) + && Name.StartsWith(ObjectiveCMsgSend); + } } partial class InstantiatedMethod diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs index 1bb6e66b5f8fc..defc6b25bda5c 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs @@ -43,7 +43,7 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) MetadataType stubHelpersType = InteropTypes.GetStubHelpers(context); - // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke + // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( @@ -78,6 +78,9 @@ private MethodIL EmitIL() if (!_importMetadata.Flags.PreserveSig) throw new NotSupportedException(); + if (_importMetadata.CheckPendingException()) + throw new NotSupportedException(); + if (_targetMethod.IsUnmanagedCallersOnly) throw new NotSupportedException(); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs index 04b939334a21e..af07b774087ce 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs @@ -93,7 +93,8 @@ public static bool IsMarshallingRequired(MethodDesc targetMethod) if (targetMethod.IsUnmanagedCallersOnly) return true; - PInvokeFlags flags = targetMethod.GetPInvokeMethodMetadata().Flags; + PInvokeMetadata metadata = targetMethod.GetPInvokeMethodMetadata(); + PInvokeFlags flags = metadata.Flags; if (flags.SetLastError) return true; @@ -101,6 +102,9 @@ public static bool IsMarshallingRequired(MethodDesc targetMethod) if (!flags.PreserveSig) return true; + if (metadata.CheckPendingException()) + return true; + var marshallers = GetMarshallersForMethod(targetMethod); for (int i = 0; i < marshallers.Length; i++) { From 2e0ee974060bfd36602acf25e206391254c5019e Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 17 May 2021 12:31:27 -0700 Subject: [PATCH 04/17] Move member function to static function on MarshalHelpers. Only perform check for OSX target. --- .../TypeSystem/Interop/IL/MarshalHelpers.cs | 18 ++++++++++++++++++ .../TypeSystem/Interop/MethodDesc.Interop.cs | 15 --------------- .../IL/Stubs/PInvokeILEmitter.cs | 2 +- .../Interop/IL/Marshaller.ReadyToRun.cs | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index 730812ed495cf..28c09cd5e571a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -797,5 +797,23 @@ private static MarshallerKind GetArrayElementMarshallerKind( return MarshallerKind.Invalid; } } + + internal static bool ShouldCheckForPendingException(TargetDetails target, PInvokeMetadata metadata) + { + if (!target.IsOSX) + return false; + + const string ObjectiveCLibrary = "/usr/lib/libobjc.dylib"; + const string ObjectiveCMsgSend = "objc_msgSend"; + + // This is for the objc_msgSend suite of functions. + // objc_msgSend + // objc_msgSend_fpret + // objc_msgSend_stret + // objc_msgSendSuper + // objc_msgSendSuper_stret + return metadata.Module.Equals(ObjectiveCLibrary) + && metadata.Name.StartsWith(ObjectiveCMsgSend); + } } } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs b/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs index 0da037bb4a1d7..6444ca97c8721 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/MethodDesc.Interop.cs @@ -347,21 +347,6 @@ public PInvokeMetadata(string module, string entrypoint, PInvokeFlags flags) Module = module; Flags = flags; } - - public bool CheckPendingException() - { - const string ObjectiveCLibrary = "/usr/lib/libobjc.dylib"; - const string ObjectiveCMsgSend = "objc_msgSend"; - - // This is for the objc_msgSend suite of functions. - // objc_msgSend - // objc_msgSend_fpret - // objc_msgSend_stret - // objc_msgSendSuper - // objc_msgSendSuper_stret - return Module.Equals(ObjectiveCLibrary) - && Name.StartsWith(ObjectiveCMsgSend); - } } partial class InstantiatedMethod diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs index defc6b25bda5c..8fcdaa1640bd2 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs @@ -78,7 +78,7 @@ private MethodIL EmitIL() if (!_importMetadata.Flags.PreserveSig) throw new NotSupportedException(); - if (_importMetadata.CheckPendingException()) + if (MarshalHelpers.ShouldCheckForPendingException(_targetMethod.Context.Target, _importMetadata)) throw new NotSupportedException(); if (_targetMethod.IsUnmanagedCallersOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs index af07b774087ce..636c698e8d589 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs @@ -102,7 +102,7 @@ public static bool IsMarshallingRequired(MethodDesc targetMethod) if (!flags.PreserveSig) return true; - if (metadata.CheckPendingException()) + if (MarshalHelpers.ShouldCheckForPendingException(targetMethod.Context.Target, metadata)) return true; var marshallers = GetMarshallersForMethod(targetMethod); From e7b777374b6f83d6daf4662947940c6dc3f32c99 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Mon, 17 May 2021 14:38:21 -0700 Subject: [PATCH 05/17] Rework detection of Objective-C msgSend* functions. --- src/coreclr/vm/dllimport.cpp | 84 ++++++++++++------- src/coreclr/vm/dllimport.h | 8 +- src/coreclr/vm/interoplibinterface.h | 7 +- src/coreclr/vm/interoplibinterface_shared.cpp | 29 +------ src/coreclr/vm/method.hpp | 8 ++ 5 files changed, 65 insertions(+), 71 deletions(-) diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 631d85728871e..3ae845f292686 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -2619,10 +2619,8 @@ void PInvokeStaticSigInfo::PreInit(Module* pModule, MethodTable * pMT) // initialize data members m_wFlags = 0; - m_entryPointName = NULL; m_pModule = pModule; m_callConv = CallConvWinApiSentinel; - m_externModref = mdModuleRefNil; SetBestFitMapping (TRUE); SetThrowOnUnmappableChar (FALSE); SetLinkFlags (nlfNone); @@ -2665,7 +2663,9 @@ void PInvokeStaticSigInfo::PreInit(MethodDesc* pMD) } PInvokeStaticSigInfo::PInvokeStaticSigInfo( - _In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName) + _In_ MethodDesc* pMD, + _Outptr_opt_ LPCUTF8* pLibName, + _Outptr_opt_ LPCUTF8* pEntryPointName) { CONTRACTL { @@ -2674,7 +2674,7 @@ PInvokeStaticSigInfo::PInvokeStaticSigInfo( } CONTRACTL_END; - DllImportInit(pMD, pLibName); + DllImportInit(pMD, pLibName, pEntryPointName); } PInvokeStaticSigInfo::PInvokeStaticSigInfo(_In_ MethodDesc* pMD) @@ -2692,7 +2692,7 @@ PInvokeStaticSigInfo::PInvokeStaticSigInfo(_In_ MethodDesc* pMD) if (!pMT->IsDelegate()) { - DllImportInit(pMD, NULL); + DllImportInit(pMD, NULL, NULL); return; } @@ -2763,7 +2763,10 @@ PInvokeStaticSigInfo::PInvokeStaticSigInfo( InitCallConv(CallConvWinApiSentinel, FALSE); } -void PInvokeStaticSigInfo::DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *ppLibName) +void PInvokeStaticSigInfo::DllImportInit( + _In_ MethodDesc* pMD, + _Outptr_opt_ LPCUTF8* ppLibName, + _Outptr_opt_ LPCUTF8* ppEntryPointName) { CONTRACTL { @@ -2775,6 +2778,7 @@ void PInvokeStaticSigInfo::DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCU // where pMD->ndirect.m_szLibName was passed in directly, cleared // by this API, then accessed on another thread before being reset here. PRECONDITION(CheckPointer(ppLibName, NULL_OK) && (!ppLibName || *ppLibName == NULL)); + PRECONDITION(CheckPointer(ppEntryPointName, NULL_OK) && (!ppEntryPointName || *ppEntryPointName == NULL)); } CONTRACTL_END; @@ -2784,19 +2788,20 @@ void PInvokeStaticSigInfo::DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCU // System.Runtime.InteropServices.DllImportAttribute IMDInternalImport *pInternalImport = pMD->GetMDImport(); CorPinvokeMap mappingFlags = pmMaxValue; - if (FAILED(pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, &m_entryPointName, &m_externModref))) + mdModuleRef modref = mdModuleRefNil; + if (FAILED(pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, ppEntryPointName, &modref))) { InitCallConv(CallConvWinApiSentinel, pMD->IsVarArg()); return; } - if (m_entryPointName == NULL) - m_entryPointName = pMD->GetName(); + if (ppEntryPointName && *ppEntryPointName == NULL) + *ppEntryPointName = pMD->GetName(); // out parameter pLibName if (ppLibName != NULL) { - if (FAILED(pInternalImport->GetModuleRefProps(m_externModref, ppLibName))) + if (FAILED(pInternalImport->GetModuleRefProps(modref, ppLibName))) { ThrowError(IDS_CLASSLOAD_BADFORMAT); } @@ -3138,16 +3143,12 @@ BOOL NDirect::MarshalingRequired( return TRUE; } - // SetLastError is handled by stub - PInvokeStaticSigInfo sigInfo(pMD); - if (sigInfo.GetLinkFlags() & nlfLastError) - return TRUE; - - // LCID argument is handled by stub - if (GetLCIDParameterIndex(pMD) != -1) - return TRUE; - - if (pMD->IsNDirect()) + PInvokeStaticSigInfo sigInfo; + if (!pMD->IsNDirect()) + { + new (&sigInfo) PInvokeStaticSigInfo(pMD); + } + else { // A P/Invoke marked with UnmanagedCallersOnlyAttribute // doesn't technically require marshalling. However, we @@ -3164,13 +3165,23 @@ BOOL NDirect::MarshalingRequired( if (pNMD->IsClassConstructorTriggeredByILStub()) return TRUE; + InitializeSigInfoAndPopulateNDirectMethodDesc(pNMD, &sigInfo); + #ifndef CROSSGEN_COMPILE // Pending exceptions are handled by stub - if (Interop::ShouldCheckForPendingException(pNMD, &sigInfo)) + if (Interop::ShouldCheckForPendingException(pNMD)) return TRUE; #endif // !CROSSGEN_COMPILE } + // SetLastError is handled by stub + if (sigInfo.GetLinkFlags() & nlfLastError) + return TRUE; + + // LCID argument is handled by stub + if (GetLCIDParameterIndex(pMD) != -1) + return TRUE; + callConv = sigInfo.GetCallConv(); } @@ -4235,7 +4246,11 @@ static void CreateNDirectStubAccessMetadata( namespace { - void PopulateNDirectMethodDescImpl(_Inout_ NDirectMethodDesc* pNMD, _In_ const PInvokeStaticSigInfo& sigInfo, _In_opt_z_ LPCUTF8 libName) + void PopulateNDirectMethodDescImpl( + _Inout_ NDirectMethodDesc* pNMD, + _In_ const PInvokeStaticSigInfo& sigInfo, + _In_opt_z_ LPCUTF8 libName, + _In_opt_z_ LPCUTF8 entryPointName) { CONTRACTL { @@ -4270,12 +4285,11 @@ namespace else { pNMD->ndirect.m_pszLibName.SetValueMaybeNull(libName); - pNMD->ndirect.m_pszEntrypointName.SetValueMaybeNull(sigInfo.GetEntryPointName()); + pNMD->ndirect.m_pszEntrypointName.SetValueMaybeNull(entryPointName); } - // Call this exactly ONCE per thread. Do not publish incomplete prestub flags - // or you will introduce a race condition. - pNMD->InterlockedSetNDirectFlags(ndirectflags); + // Do not publish incomplete prestub flags or you will introduce a race condition. + pNMD->InterlockedSetNDirectFlags(ndirectflags | NDirectMethodDesc::kNDirectPopulated); } } @@ -4291,9 +4305,12 @@ void NDirect::PopulateNDirectMethodDesc(_Inout_ NDirectMethodDesc* pNMD) if (pNMD->IsSynchronized()) COMPlusThrow(kTypeLoadException, IDS_EE_NOSYNCHRONIZED); - LPCUTF8 szLibName = NULL; - PInvokeStaticSigInfo sigInfo(pNMD, &szLibName); - PopulateNDirectMethodDescImpl(pNMD, sigInfo, szLibName); + if (pNMD->IsPopulated()) + return; + + LPCUTF8 szLibName = NULL, szEntryPointName = NULL; + PInvokeStaticSigInfo sigInfo(pNMD, &szLibName, &szEntryPointName); + PopulateNDirectMethodDescImpl(pNMD, sigInfo, szLibName, szEntryPointName); } void NDirect::InitializeSigInfoAndPopulateNDirectMethodDesc(_Inout_ NDirectMethodDesc* pNMD, _Inout_ PInvokeStaticSigInfo* pSigInfo) @@ -4309,10 +4326,13 @@ void NDirect::InitializeSigInfoAndPopulateNDirectMethodDesc(_Inout_ NDirectMetho if (pNMD->IsSynchronized()) COMPlusThrow(kTypeLoadException, IDS_EE_NOSYNCHRONIZED); - LPCUTF8 szLibName = NULL; - new (pSigInfo) PInvokeStaticSigInfo(pNMD, &szLibName); + LPCUTF8 szLibName = NULL, szEntryPointName = NULL; + new (pSigInfo) PInvokeStaticSigInfo(pNMD, &szLibName, &szEntryPointName); + + if (pNMD->IsPopulated()) + return; - PopulateNDirectMethodDescImpl(pNMD, *pSigInfo, szLibName); + PopulateNDirectMethodDescImpl(pNMD, *pSigInfo, szLibName, szEntryPointName); } #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index b2420caa1f568..86fea61e8c71a 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -312,12 +312,12 @@ struct PInvokeStaticSigInfo PInvokeStaticSigInfo(_In_ MethodDesc* pMdDelegate); - PInvokeStaticSigInfo(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName); + PInvokeStaticSigInfo(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8* pLibName, _Outptr_opt_ LPCUTF8* pEntryPointName); private: void ThrowError(WORD errorResourceID); void InitCallConv(CorInfoCallConvExtension callConv, BOOL bIsVarArg); - void DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8 *pLibName); + void DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8* pLibName, _Outptr_opt_ LPCUTF8* pEntryPointName); void PreInit(Module* pModule, MethodTable *pClass); void PreInit(MethodDesc* pMD); @@ -350,8 +350,6 @@ struct PInvokeStaticSigInfo BOOL IsDelegateInterop() const { LIMITED_METHOD_CONTRACT; return m_wFlags & PINVOKE_STATIC_SIGINFO_IS_DELEGATE_INTEROP; } CorInfoCallConvExtension GetCallConv() const { LIMITED_METHOD_CONTRACT; return m_callConv; } Signature GetSignature() const { LIMITED_METHOD_CONTRACT; return m_sig; } - LPCUTF8 GetEntryPointName() const { LIMITED_METHOD_CONTRACT; return m_entryPointName; } - mdModuleRef GetExternModuleRefToken() const { LIMITED_METHOD_CONTRACT; return m_externModref; } CorNativeLinkType GetCharSet() const { LIMITED_METHOD_CONTRACT; return (CorNativeLinkType)((m_wFlags & COR_NATIVE_LINK_TYPE_MASK) >> COR_NATIVE_LINK_TYPE_SHIFT); } CorNativeLinkFlags GetLinkFlags() const { LIMITED_METHOD_CONTRACT; return (CorNativeLinkFlags)((m_wFlags & COR_NATIVE_LINK_FLAGS_MASK) >> COR_NATIVE_LINK_FLAGS_SHIFT); } @@ -406,9 +404,7 @@ struct PInvokeStaticSigInfo private: Module* m_pModule; Signature m_sig; - LPCUTF8 m_entryPointName; CorInfoCallConvExtension m_callConv; - mdModuleRef m_externModref; WORD m_wFlags; }; diff --git a/src/coreclr/vm/interoplibinterface.h b/src/coreclr/vm/interoplibinterface.h index 6225222c8513a..28139dbbee663 100644 --- a/src/coreclr/vm/interoplibinterface.h +++ b/src/coreclr/vm/interoplibinterface.h @@ -165,16 +165,11 @@ class ObjCMarshalNative #endif // FEATURE_OBJCMARSHAL -// Forward declaration of type. -struct PInvokeStaticSigInfo; - class Interop { public: // Check if pending exceptions are possible for the following native export. - static bool ShouldCheckForPendingException( - _In_ NDirectMethodDesc* md, - _In_opt_ PInvokeStaticSigInfo* sigInfo = NULL); + static bool ShouldCheckForPendingException(_In_ NDirectMethodDesc* md); // A no return callback that is designed to help propagate a managed // exception going from Managed to Native. diff --git a/src/coreclr/vm/interoplibinterface_shared.cpp b/src/coreclr/vm/interoplibinterface_shared.cpp index ca03670594070..19ee32f258545 100644 --- a/src/coreclr/vm/interoplibinterface_shared.cpp +++ b/src/coreclr/vm/interoplibinterface_shared.cpp @@ -9,9 +9,7 @@ using ManagedToNativeExceptionCallback = Interop::ManagedToNativeExceptionCallback; -bool Interop::ShouldCheckForPendingException( - _In_ NDirectMethodDesc* md, - _In_opt_ PInvokeStaticSigInfo* sigInfo) +bool Interop::ShouldCheckForPendingException(_In_ NDirectMethodDesc* md) { CONTRACTL { @@ -25,30 +23,7 @@ bool Interop::ShouldCheckForPendingException( PTR_CUTF8 libraryName = md->GetLibNameRaw(); PTR_CUTF8 entrypointName = md->GetEntrypointName(); if (libraryName == NULL || entrypointName == NULL) - { - // If no sig info was supplied we have no recourse. - if (sigInfo == NULL) - return false; - - if (libraryName == NULL) - { - // If the library name is unknown, see if we can get the token - // from the sig info. - mdModuleRef modRef = sigInfo->GetExternModuleRefToken(); - if (modRef != mdModuleRefNil) - { - IMDInternalImport* mdImport = md->GetMDImport(); - (void)mdImport->GetModuleRefProps(modRef, &libraryName); - } - } - - if (entrypointName == NULL) - entrypointName = sigInfo->GetEntryPointName(); - - // Still no luck so return false. - if (libraryName == NULL || entrypointName == NULL) - return false; - } + return false; if (ObjCMarshalNative::IsRuntimeMessageSendFunction(libraryName, entrypointName)) return true; diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index b536101c5dd91..4d816b65885e7 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -3027,6 +3027,8 @@ class NDirectMethodDesc : public MethodDesc kIsQCall = 0x1000, kDefaultDllImportSearchPathsStatus = 0x2000, // either method has custom attribute or not. + + kNDirectPopulated = 0x8000, // Indicate if the NDirect has been fully populated. }; // Resolve the import to the NDirect target and set it on the NDirectMethodDesc. @@ -3159,6 +3161,12 @@ class NDirectMethodDesc : public MethodDesc return (ndirect.m_wFlags & kDefaultDllImportSearchPathsIsCached) != 0; } + BOOL IsPopulated() + { + LIMITED_METHOD_CONTRACT; + return (ndirect.m_wFlags & kNDirectPopulated) != 0; + } + ULONG DefaultDllImportSearchPathsAttributeCachedValue() { LIMITED_METHOD_CONTRACT; From 7a4dd16c885d6524dfdc9122888ca8274fcc943b Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Mon, 17 May 2021 21:07:12 -0700 Subject: [PATCH 06/17] Remove unnecessary clear function. --- .../System.Private.CoreLib/src/System/StubHelpers.cs | 5 ----- src/coreclr/vm/corelib.h | 1 - src/coreclr/vm/dllimport.cpp | 6 ------ 3 files changed, 12 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 2811f5faf3053..33435681e9e93 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1247,11 +1247,6 @@ internal static void SetPendingExceptionObject(Exception? exception) s_pendingExceptionObject = exception; } - internal static void ClearPendingExceptionObject() - { - s_pendingExceptionObject = null; - } - [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IntPtr CreateCustomMarshalerHelper(IntPtr pMD, int paramToken, IntPtr hndManagedType); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 8e7a67b327def..664b57c2d0d7c 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -998,7 +998,6 @@ DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveVia DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) -DEFINE_METHOD(STUBHELPERS, CLEAR_PENDING_EXCEPTION_OBJECT, ClearPendingExceptionObject, SM_RetVoid) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr) DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid) diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 3ae845f292686..3e07760f80183 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -662,12 +662,6 @@ class ILStubState : public StubState } #endif // PROFILING_SUPPORTED - if (SF_IsCheckPendingException(m_dwStubFlags) - && SF_IsForwardStub(m_dwStubFlags)) - { - pcsDispatch->EmitCALL(METHOD__STUBHELPERS__CLEAR_PENDING_EXCEPTION_OBJECT, 0, 0); - } - // For CoreClr, clear the last error before calling the target that returns last error. // There isn't always a way to know the function have failed without checking last error, // in particular on Unix. From 661447fc3ca339d93c3dc621e98667dc8bbeb6af Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 00:02:45 -0700 Subject: [PATCH 07/17] Revert white space change. --- src/coreclr/vm/corelib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 664b57c2d0d7c..3875f9bae5a36 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -997,7 +997,7 @@ DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_SAFEHANDLE, AddToClea DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveViaCleanupList, SM_RefCleanupWorkListElement_Obj_RetVoid) DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) -DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) +DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr) DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid) From eac7e8ac8e7214b5688688aac0c11eb340921800 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 00:04:19 -0700 Subject: [PATCH 08/17] Try again --- src/coreclr/vm/corelib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 3875f9bae5a36..2b26b95771e85 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -997,7 +997,7 @@ DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_SAFEHANDLE, AddToClea DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveViaCleanupList, SM_RefCleanupWorkListElement_Obj_RetVoid) DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) -DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) +DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr) DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid) From a84d1c843226c6044aa17a5b18b43a7802a7239d Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 00:05:41 -0700 Subject: [PATCH 09/17] Spaces are hard --- src/coreclr/vm/corelib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 2b26b95771e85..587abee660f58 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -997,7 +997,7 @@ DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_SAFEHANDLE, AddToClea DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveViaCleanupList, SM_RefCleanupWorkListElement_Obj_RetVoid) DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) -DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) +DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr) DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid) From ebff1d689bf3812eebc21ba9f7512a5be236c917 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 00:06:42 -0700 Subject: [PATCH 10/17] Space --- src/coreclr/vm/corelib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 587abee660f58..34e67702f0acb 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -997,7 +997,7 @@ DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_SAFEHANDLE, AddToClea DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveViaCleanupList, SM_RefCleanupWorkListElement_Obj_RetVoid) DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) -DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) +DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr) DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid) From 1a69f67a99e9b8d844fde3bf9ef61027bea2a2a9 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 00:07:39 -0700 Subject: [PATCH 11/17] space --- src/coreclr/vm/corelib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 34e67702f0acb..f9e0de124108b 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -997,7 +997,7 @@ DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_SAFEHANDLE, AddToClea DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveViaCleanupList, SM_RefCleanupWorkListElement_Obj_RetVoid) DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) -DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) +DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExceptionObject, SM_RetException) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr) DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid) From d224c706facc378b7673be8d80dc6181510ec286 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 09:21:40 -0700 Subject: [PATCH 12/17] Feedback --- src/coreclr/vm/dllimport.cpp | 5 ----- src/coreclr/vm/dllimport.h | 4 ++++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 3e07760f80183..1f7163fc914ce 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -3102,11 +3102,6 @@ HRESULT NDirect::HasNAT_LAttribute(IMDInternalImport *pInternalImport, mdToken t // Either MD or signature & module must be given. -// -// N.B. This method can be called at a time when the associated NDirectMethodDesc -// has not been fully populated. This means the optimized path for this call is to rely -// on the most basic P/Invoke metadata. An example when this can happen is when the JIT -// is compiling a method containing a P/Invoke that is being considered for inlining. /*static*/ BOOL NDirect::MarshalingRequired( _In_opt_ MethodDesc* pMD, diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index 86fea61e8c71a..c55ce9f7f4030 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -75,6 +75,10 @@ class NDirect static HRESULT HasNAT_LAttribute(IMDInternalImport *pInternalImport, mdToken token, DWORD dwMemberAttrs); // Either MD or signature & module must be given. + // Note: This method can be called at a time when the associated NDirectMethodDesc + // has not been fully populated. This means the optimized path for this call is to rely + // on the most basic P/Invoke metadata. An example when this can happen is when the JIT + // is compiling a method containing a P/Invoke that is being considered for inlining. static BOOL MarshalingRequired( _In_opt_ MethodDesc* pMD, _In_opt_ PCCOR_SIGNATURE pSig = NULL, From 2a8754a1dc38cf94b19b3f04671e74840a9908f4 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 09:59:20 -0700 Subject: [PATCH 13/17] Docs. --- .../Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs | 2 +- .../ObjectiveC/ObjectiveCMarshal.PlatformNotSupported.cs | 5 ++--- .../Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.cs | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs index 8616a0f4ac537..02cbd9ebb8076 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs @@ -10,7 +10,7 @@ namespace System.Runtime.InteropServices.ObjectiveC public static partial class ObjectiveCMarshal { /// - /// Sets a pending exception to be thrown the next time the runtime is entered from an overridden msgSend P/Invoke. + /// Sets a pending exception to be thrown the next time the runtime is entered from an Objective-C msgSend P/Invoke. /// /// The exception. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.PlatformNotSupported.cs index c9c94991676ed..fa97f66b2f3f5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.PlatformNotSupported.cs @@ -127,14 +127,13 @@ public enum MessageSendFunction /// The function override. /// Thrown if the msgSend function has already been overridden. /// - /// Providing an override can enable support for Objective-C - /// exception propagation and variadic argument support. + /// Providing an override can enable support for Objective-C variadic argument support. /// public static void SetMessageSendCallback(MessageSendFunction msgSendFunction, IntPtr func) => throw new PlatformNotSupportedException(); /// - /// Sets a pending exception to be thrown the next time the runtime is entered from an overridden msgSend P/Invoke. + /// Sets a pending exception to be thrown the next time the runtime is entered from an Objective-C msgSend P/Invoke. /// /// The exception. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.cs index ddc1ff7327e2f..3f3d55e355742 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.cs @@ -160,8 +160,7 @@ public enum MessageSendFunction /// The function override. /// Thrown if the msgSend function has already been overridden. /// - /// Providing an override can enable support for Objective-C - /// exception propagation and variadic argument support. + /// Providing an override can enable support for Objective-C variadic argument support. /// public static void SetMessageSendCallback(MessageSendFunction msgSendFunction, IntPtr func) { From 143af69e909dd270fff14e1c412b55a04f016e7b Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 10:25:23 -0700 Subject: [PATCH 14/17] Add comment on details of how we are testing the SetMessageSendPendingException API. --- .../InteropServices/ObjectiveC/PendingExceptionTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs index cbb89626c09c1..e0cdbf415e60b 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs @@ -75,6 +75,11 @@ private static void ValidateSetMessageSendPendingExceptionImpl(MessageSendFuncti }; // Override message send function + // + // We are using the overriding mechanism to enabling validating in the Libraries test suite. + // Technically any Objective-C code that is entered via msgSend could call the managed SetMessageSendPendingException() + // and it would be thrown when returning from the P/Invoke. This approach avoids us having to + // create a pure Objective-C library for testing this behavior. ObjectiveCMarshal.SetMessageSendCallback(msgSend, func); // Call message send function through P/Invoke From a36caf9d58305a1c7f6f78ee29ce85ead18706cc Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 18 May 2021 11:41:54 -0700 Subject: [PATCH 15/17] Missed doc. --- .../Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs | 2 +- .../System/Runtime/InteropServices/ObjectiveCMarshal.Mono.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs index e0cdbf415e60b..810f5cad08a81 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs @@ -76,7 +76,7 @@ private static void ValidateSetMessageSendPendingExceptionImpl(MessageSendFuncti // Override message send function // - // We are using the overriding mechanism to enabling validating in the Libraries test suite. + // We are using the overriding mechanism to enable validating in the Libraries test suite. // Technically any Objective-C code that is entered via msgSend could call the managed SetMessageSendPendingException() // and it would be thrown when returning from the P/Invoke. This approach avoids us having to // create a pure Objective-C library for testing this behavior. diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.Mono.cs index d97624ac2a180..ad7f39b64d743 100644 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.Mono.cs @@ -10,7 +10,7 @@ namespace System.Runtime.InteropServices.ObjectiveC public static partial class ObjectiveCMarshal { /// - /// Sets a pending exception to be thrown the next time the runtime is entered from an overridden msgSend P/Invoke. + /// Sets a pending exception to be thrown the next time the runtime is entered from an Objective-C msgSend P/Invoke. /// /// The exception. /// From f9ebbc0716e648a79305b707810b01c48ac28c7a Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Wed, 19 May 2021 09:43:21 -0700 Subject: [PATCH 16/17] ARM64 doesn't support all msgSend* APIs. --- .../Runtime/InteropServices/ObjectiveC/LibObjC.cs | 15 +++++++++++++++ .../ObjectiveC/MessageSendTests.cs | 5 +++++ .../ObjectiveC/PendingExceptionTests.cs | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs index 799efd8c7af0f..771bb9bcc57ea 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs @@ -44,6 +44,21 @@ public struct objc_super public IntPtr super_class; } + public static bool SupportedOnPlatform(MessageSendFunction msgSend) + { + // The objc_msgSend_fpret, objc_msgSend_stret, and objc_msgSendSuper_stret exports + // are not present on the ARM64 platform. + if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64 + && (msgSend == MessageSendFunction.MsgSendFpret + || msgSend == MessageSendFunction.MsgSendStret + || msgSend == MessageSendFunction.MsgSendSuperStret)) + { + return false; + } + + return true; + } + public static IntPtr CallPInvoke(MessageSendFunction msgSend, IntPtr inst, IntPtr sel) { switch (msgSend) diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs index 4877317d592da..8ccf493a3795e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs @@ -104,6 +104,11 @@ private static void SetMessageSendCallbackImpl(MessageSendFunction[] funcsToOver { foreach (var (msgSend, func) in msgSendOverrides) { + if (!LibObjC.SupportedOnPlatform(msgSend)) + { + continue; + } + bool shouldOverride = Array.IndexOf(funcsToOverride, msgSend) >= 0; IntPtr expected; diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs index 810f5cad08a81..c17f2915a8dd3 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs @@ -64,6 +64,11 @@ public void ValidateSetMessageSendPendingException(MessageSendFunction func) private static void ValidateSetMessageSendPendingExceptionImpl(MessageSendFunction msgSend) { + if (!LibObjC.SupportedOnPlatform(msgSend)) + { + return; + } + IntPtr func = msgSend switch { MessageSendFunction.MsgSend => (IntPtr)(delegate* unmanaged)&MsgSend, From 484f5568b05f08f341dbda619b2ae972f6981121 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Wed, 19 May 2021 18:44:43 -0700 Subject: [PATCH 17/17] Disable the crossgen2smoke on OSX ARM64 --- src/tests/issues.targets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index a0c2d9a4ef4f1..008255e24e39e 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -746,6 +746,9 @@ https://github.com/dotnet/runtime/issues/50238 + + https://github.com/dotnet/runtime/issues/49365 +