diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 3e9046d96dbe3f..c572772f1473e8 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -118,6 +118,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs new file mode 100644 index 00000000000000..648cfd0671ad68 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace System +{ + public static partial class AppContext + { + [UnmanagedCallersOnly] + private static unsafe void OnProcessExit(Exception* pException) + { + try + { + OnProcessExit(); + } + catch (Exception ex) + { + *pException = ex; + } + } + + [UnmanagedCallersOnly] + private static unsafe void OnUnhandledException(object* pUnhandledException, Exception* _) + { + try + { + OnUnhandledException(*pUnhandledException); + } + catch + { + // The VM does not expect exceptions to propagate out of this callback + } + } + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs index 2da108edc00c47..199e3875ae6f7c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs @@ -338,5 +338,19 @@ internal static unsafe void GetHelpContextBstr(Exception* obj, IntPtr* bstr, uin } } #endif + + [UnmanagedCallersOnly] + internal static unsafe void CreateTargetInvocationException(Exception* pInnerException, object* pResult, Exception* pException) + { + try + { + Exception? inner = pInnerException is not null ? *pInnerException : null; + *pResult = new System.Reflection.TargetInvocationException(inner); + } + catch (Exception ex) + { + *pException = ex; + } + } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 2c0929bd2a9254..1431284bc69136 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -416,13 +416,18 @@ internal string GetFullyQualifiedName() public override string FullyQualifiedName => GetFullyQualifiedName(); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeModule_GetTypes")] - private static partial void GetTypes(QCallModule module, ObjectHandleOnStack retTypes); + private static partial void GetTypes(QCallModule module, ObjectHandleOnStack retTypes, ObjectHandleOnStack retExceptions); internal RuntimeType[] GetDefinedTypes() { RuntimeType[]? types = null; + Exception[]? exceptions = null; RuntimeModule thisAsLocal = this; - GetTypes(new QCallModule(ref thisAsLocal), ObjectHandleOnStack.Create(ref types)); + GetTypes(new QCallModule(ref thisAsLocal), ObjectHandleOnStack.Create(ref types), ObjectHandleOnStack.Create(ref exceptions)); + + if (exceptions is not null) + throw new ReflectionTypeLoadException(types, exceptions, SR.ReflectionTypeLoad_LoadFailed); + return types!; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.cs index 46e937bd52adc7..c265f91064a843 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.cs @@ -6,16 +6,25 @@ using System.Diagnostics.Tracing; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; using System.Runtime.Loader; namespace System { internal static partial class StartupHookProvider { - private static unsafe void ManagedStartup(char* pDiagnosticStartupHooks) + [UnmanagedCallersOnly] + private static unsafe void ManagedStartup(char* pDiagnosticStartupHooks, Exception* pException) { - if (IsSupported) - ProcessStartupHooks(new string(pDiagnosticStartupHooks)); + try + { + if (IsSupported) + ProcessStartupHooks(new string(pDiagnosticStartupHooks)); + } + catch (Exception ex) + { + *pException = ex; + } } } } diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 7c7cf6764a3b1e..88d6b1642b0f24 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -3396,12 +3396,8 @@ void AppDomain::OnUnhandledException(OBJECTREF* pThrowable) EX_TRY { - MethodDescCallSite raiseEvent(METHOD__APPCONTEXT__ON_UNHANDLED_EXCEPTION); - ARG_SLOT args[] = - { - ObjToArgSlot(*pThrowable) - }; - raiseEvent.Call(args); + UnmanagedCallersOnlyCaller raiseEvent(METHOD__APPCONTEXT__ON_UNHANDLED_EXCEPTION); + raiseEvent.InvokeThrowing(pThrowable); } EX_CATCH { @@ -3423,8 +3419,8 @@ void AppDomain::RaiseExitProcessEvent() _ASSERTE (GetThread()->PreemptiveGCDisabled()); - MethodDescCallSite onProcessExit(METHOD__APPCONTEXT__ON_PROCESS_EXIT); - onProcessExit.Call(NULL); + UnmanagedCallersOnlyCaller onProcessExit(METHOD__APPCONTEXT__ON_PROCESS_EXIT); + onProcessExit.InvokeThrowing(); } DefaultAssemblyBinder *AppDomain::CreateDefaultBinder() diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 7be8cd639d5a53..d54cc0784fdb49 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -1331,12 +1331,8 @@ void RunManagedStartup() } CONTRACTL_END; - MethodDescCallSite managedStartup(METHOD__STARTUP_HOOK_PROVIDER__MANAGED_STARTUP); - - ARG_SLOT args[1]; - args[0] = PtrToArgSlot(s_wszDiagnosticStartupHookPaths); - - managedStartup.Call(args); + UnmanagedCallersOnlyCaller managedStartup(METHOD__STARTUP_HOOK_PROVIDER__MANAGED_STARTUP); + managedStartup.InvokeThrowing(s_wszDiagnosticStartupHookPaths); } INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads) diff --git a/src/coreclr/vm/commodule.cpp b/src/coreclr/vm/commodule.cpp index 933a4d15bb8d8e..d5e8ef9539f6f5 100644 --- a/src/coreclr/vm/commodule.cpp +++ b/src/coreclr/vm/commodule.cpp @@ -678,7 +678,7 @@ extern "C" HINSTANCE QCALLTYPE MarshalNative_GetHINSTANCE(QCall::ModuleHandle pM // Get class will return an array contain all of the classes // that are defined within this Module. -extern "C" void QCALLTYPE RuntimeModule_GetTypes(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retTypes) +extern "C" void QCALLTYPE RuntimeModule_GetTypes(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retTypes, QCall::ObjectHandleOnStack retExceptions) { QCALL_CONTRACT; @@ -751,19 +751,20 @@ extern "C" void QCALLTYPE RuntimeModule_GetTypes(QCall::ModuleHandle pModule, QC gc.refArrClasses->SetAt(curPos++, refCurClass); } - // check if there were exceptions thrown - if (cXcept > 0) { - + // Return exceptions to managed side for throwing + if (cXcept > 0) + { gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass); for (DWORD i=0;iSetAt(i, gc.xcept->GetAt(i)); } - OBJECTREF except = InvokeUtil::CreateClassLoadExcept((OBJECTREF*) &gc.refArrClasses,(OBJECTREF*) &gc.xceptRet); - COMPlusThrow(except); + retExceptions.Set(gc.xceptRet); + } + else + { + // We should have filled the array exactly. + _ASSERTE(curPos == dwNumTypeDefs); } - - // We should have filled the array exactly. - _ASSERTE(curPos == dwNumTypeDefs); // Assign the return value to the CLR array retTypes.Set(gc.refArrClasses); diff --git a/src/coreclr/vm/commodule.h b/src/coreclr/vm/commodule.h index 88c3f4e3ee673e..bc94cf9e546cb1 100644 --- a/src/coreclr/vm/commodule.h +++ b/src/coreclr/vm/commodule.h @@ -71,7 +71,7 @@ extern "C" void QCALLTYPE RuntimeModule_GetScopeName(QCall::ModuleHandle pModule extern "C" void QCALLTYPE RuntimeModule_GetFullyQualifiedName(QCall::ModuleHandle pModule, QCall::StringHandleOnStack retString); // GetTypes will return an array containing all of the types that are defined within this Module. -extern "C" void QCALLTYPE RuntimeModule_GetTypes(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retTypes); +extern "C" void QCALLTYPE RuntimeModule_GetTypes(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retTypes, QCall::ObjectHandleOnStack retExceptions); extern "C" HINSTANCE QCALLTYPE MarshalNative_GetHINSTANCE(QCall::ModuleHandle pModule); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index e97a7926fc9b81..428d27439cfe71 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -98,8 +98,8 @@ DEFINE_FIELD(ACCESS_VIOLATION_EXCEPTION, ACCESSTYPE, _accessType) DEFINE_CLASS(APPCONTEXT, System, AppContext) DEFINE_METHOD(APPCONTEXT, SETUP, Setup, SM_PtrPtrChar_PtrPtrChar_Int_PtrException_RetVoid) -DEFINE_METHOD(APPCONTEXT, ON_PROCESS_EXIT, OnProcessExit, SM_RetVoid) -DEFINE_METHOD(APPCONTEXT, ON_UNHANDLED_EXCEPTION, OnUnhandledException, SM_Obj_RetVoid) +DEFINE_METHOD(APPCONTEXT, ON_PROCESS_EXIT, OnProcessExit, SM_PtrException_RetVoid) +DEFINE_METHOD(APPCONTEXT, ON_UNHANDLED_EXCEPTION, OnUnhandledException, SM_PtrObj_PtrException_RetVoid) DEFINE_FIELD(APPCONTEXT, FIRST_CHANCE_EXCEPTION, FirstChanceException) DEFINE_CLASS(ARG_ITERATOR, System, ArgIterator) @@ -306,6 +306,7 @@ DEFINE_METHOD(EXCEPTION, GET_DESCRIPTION_BSTR, GetDescriptionBstr, DEFINE_METHOD(EXCEPTION, GET_SOURCE_BSTR, GetSourceBstr, SM_PtrException_PtrException_RetIntPtr) DEFINE_METHOD(EXCEPTION, GET_HELP_CONTEXT_BSTR, GetHelpContextBstr, SM_PtrException_PtrIntPtr_PtrUInt_PtrException_RetVoid) #endif // FEATURE_COMINTEROP +DEFINE_METHOD(EXCEPTION, CREATE_TARGET_INVOCATION_EXCEPTION, CreateTargetInvocationException, SM_PtrException_PtrObj_PtrException_RetVoid) DEFINE_CLASS(SYSTEM_EXCEPTION, System, SystemException) @@ -890,7 +891,7 @@ DEFINE_CLASS(EVENT_SOURCE, Tracing, EventSource) DEFINE_METHOD(EVENT_SOURCE, INITIALIZE_DEFAULT_EVENT_SOURCES, InitializeDefaultEventSources, SM_PtrException_RetVoid) DEFINE_CLASS(STARTUP_HOOK_PROVIDER, System, StartupHookProvider) -DEFINE_METHOD(STARTUP_HOOK_PROVIDER, MANAGED_STARTUP, ManagedStartup, SM_PtrChar_RetVoid) +DEFINE_METHOD(STARTUP_HOOK_PROVIDER, MANAGED_STARTUP, ManagedStartup, SM_PtrChar_PtrException_RetVoid) DEFINE_METHOD(STARTUP_HOOK_PROVIDER, CALL_STARTUP_HOOK, CallStartupHook, SM_PtrChar_PtrException_RetVoid) DEFINE_CLASS(STREAM, IO, Stream) diff --git a/src/coreclr/vm/exceptionhandlingqcalls.h b/src/coreclr/vm/exceptionhandlingqcalls.h index 7cc00295fbf3f3..ca0a25826c15d8 100644 --- a/src/coreclr/vm/exceptionhandlingqcalls.h +++ b/src/coreclr/vm/exceptionhandlingqcalls.h @@ -17,4 +17,5 @@ extern "C" CLR_BOOL QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStack extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, unsigned int* uExCollideClauseIdx, CLR_BOOL* fUnwoundReversePInvoke, CLR_BOOL* pIsExceptionIntercepted); #endif // DACCESS_COMPILE -#endif // EXCEPTION_HANDLING_QCALLS_H \ No newline at end of file +#endif // EXCEPTION_HANDLING_QCALLS_H + diff --git a/src/coreclr/vm/invokeutil.cpp b/src/coreclr/vm/invokeutil.cpp index c58710e1de1b17..ea289619bcf902 100644 --- a/src/coreclr/vm/invokeutil.cpp +++ b/src/coreclr/vm/invokeutil.cpp @@ -584,67 +584,6 @@ OBJECTREF InvokeUtil::CreateObjectAfterInvoke(TypeHandle th, void * pValue) { return obj; } -// This is a special purpose Exception creation function. It -// creates the ReflectionTypeLoadException placing the passed -// classes array and exception array into it. -OBJECTREF InvokeUtil::CreateClassLoadExcept(OBJECTREF* classes, OBJECTREF* except) { - CONTRACT(OBJECTREF) { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(CheckPointer(classes)); - PRECONDITION(CheckPointer(except)); - PRECONDITION(IsProtectedByGCFrame (classes)); - PRECONDITION(IsProtectedByGCFrame (except)); - - POSTCONDITION(RETVAL != NULL); - - INJECT_FAULT(COMPlusThrowOM()); - } - CONTRACT_END; - - OBJECTREF oRet = 0; - - struct { - OBJECTREF o; - STRINGREF str; - } gc; - gc.o = NULL; - gc.str = NULL; - - MethodTable *pVMClassLoadExcept = CoreLibBinder::GetException(kReflectionTypeLoadException); - gc.o = AllocateObject(pVMClassLoadExcept); - GCPROTECT_BEGIN(gc); - ARG_SLOT args[4]; - - // Retrieve the resource string. - ResMgrGetString(W("ReflectionTypeLoad_LoadFailed"), &gc.str); - - MethodDesc* pMD = MemberLoader::FindMethod(gc.o->GetMethodTable(), - COR_CTOR_METHOD_NAME, &gsig_IM_ArrType_ArrException_Str_RetVoid); - - if (!pMD) - { - MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME); - COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName); - } - - MethodDescCallSite ctor(pMD); - - // Call the constructor - args[0] = ObjToArgSlot(gc.o); - args[1] = ObjToArgSlot(*classes); - args[2] = ObjToArgSlot(*except); - args[3] = ObjToArgSlot((OBJECTREF)gc.str); - - ctor.Call(args); - - oRet = gc.o; - - GCPROTECT_END(); - RETURN oRet; -} - OBJECTREF InvokeUtil::CreateTargetExcept(OBJECTREF* except) { CONTRACT(OBJECTREF) { THROWS; @@ -659,45 +598,27 @@ OBJECTREF InvokeUtil::CreateTargetExcept(OBJECTREF* except) { } CONTRACT_END; - OBJECTREF o; - OBJECTREF oRet = 0; - - MethodTable *pVMTargetExcept = CoreLibBinder::GetException(kTargetInvocationException); - o = AllocateObject(pVMTargetExcept); - GCPROTECT_BEGIN(o); - ARG_SLOT args[2]; - - MethodDesc* pMD = MemberLoader::FindMethod(o->GetMethodTable(), - COR_CTOR_METHOD_NAME, &gsig_IM_Exception_RetVoid); - - if (!pMD) + struct { - MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME); - COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName); - } + OBJECTREF oRet; + OBJECTREF innerEx; + } gc; + gc.oRet = NULL; + gc.innerEx = NULL; + GCPROTECT_BEGIN(gc); - MethodDescCallSite ctor(pMD); + UnmanagedCallersOnlyCaller createTargetExcept(METHOD__EXCEPTION__CREATE_TARGET_INVOCATION_EXCEPTION); - // Call the constructor - args[0] = ObjToArgSlot(o); // for security, don't allow a non-exception object to be spoofed as an exception object. We cast later and // don't check and this could cause us grief. _ASSERTE(!except || IsException((*except)->GetMethodTable())); // how do we get non-exceptions? - if (except && IsException((*except)->GetMethodTable())) - { - args[1] = ObjToArgSlot(*except); - } - else - { - args[1] = 0; - } - ctor.Call(args); + gc.innerEx = (except && IsException((*except)->GetMethodTable())) ? *except : NULL; - oRet = o; + createTargetExcept.InvokeThrowing(&gc.innerEx, &gc.oRet); GCPROTECT_END(); - RETURN oRet; + RETURN gc.oRet; } // Ensure that the field is declared on the type or subtype of the type to which the typed reference refers. diff --git a/src/coreclr/vm/invokeutil.h b/src/coreclr/vm/invokeutil.h index ba8fe071ee449e..2d13dbac87e7ee 100644 --- a/src/coreclr/vm/invokeutil.h +++ b/src/coreclr/vm/invokeutil.h @@ -63,11 +63,6 @@ class InvokeUtil // exception into it. static OBJECTREF CreateTargetExcept(OBJECTREF* except); - // This is a special purpose Exception creation function. It - // creates the ReflectionClassLoadException placing the passed - // classes array and exception array into it. - static OBJECTREF CreateClassLoadExcept(OBJECTREF* classes,OBJECTREF* except); - // Validate that the field can be widened for Set static void ValidField(TypeHandle th, OBJECTREF* value); diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index c4909a0ef2c6a8..60fa576d319f59 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -390,7 +390,6 @@ DEFINE_METASIG_T(IM(BindingFlags_RetArrMethodInfo, g(BINDING_FLAGS), a(C(METHOD_ DEFINE_METASIG_T(IM(BindingFlags_RetArrPropertyInfo, g(BINDING_FLAGS), a(C(PROPERTY_INFO)))) DEFINE_METASIG(IM(ArrChar_RetVoid, a(u), v)) DEFINE_METASIG(IM(ArrChar_Int_Int_RetVoid, a(u) i i, v)) -DEFINE_METASIG_T(IM(ArrType_ArrException_Str_RetVoid, a(C(TYPE)) a(C(EXCEPTION)) s, v)) DEFINE_METASIG(IM(RefInt_RefInt_RefInt_RetArrByte, r(i) r(i) r(i), a(b))) DEFINE_METASIG_T(IM(RefInt_RetRuntimeType, r(i) , C(CLASS))) DEFINE_METASIG_T(SM(IntPtr_RetRuntimeType, I , C(CLASS))) @@ -420,9 +419,11 @@ DEFINE_METASIG_T(SM(PtrAssembly_PtrByte_PtrAssembly_PtrException_RetVoid, P(C(AS DEFINE_METASIG_T(SM(PtrAssembly_PtrChar_PtrAssembly_PtrException_RetVoid, P(C(ASSEMBLY)) P(u) P(C(ASSEMBLY)) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(IntPtr_PtrAssemblyName_PtrAssemblyBase_PtrException_RetVoid, I P(C(ASSEMBLY_NAME)) P(C(ASSEMBLYBASE)) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(PtrException_RetVoid, P(C(EXCEPTION)), v)) +DEFINE_METASIG_T(SM(PtrObj_PtrException_RetVoid, P(j) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(PtrChar_PtrException_RetVoid, P(u) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(Int_PtrObj_PtrException_RetVoid, i P(j) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(PtrObj_PtrInt_PtrException_RetVoid, P(j) P(i) P(C(EXCEPTION)), v)) +DEFINE_METASIG_T(SM(PtrException_PtrObj_PtrException_RetVoid, P(C(EXCEPTION)) P(j) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(PtrResolver_PtrInt_PtrClass_PtrException_RetVoid, P(C(RESOLVER)) P(i) P(C(CLASS)) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(PtrResolver_PtrInt_PtrInt_PtrInt_PtrArrByte_PtrException_RetVoid, P(C(RESOLVER)) P(i) P(i) P(i) P(a(b)) P(C(EXCEPTION)), v)) DEFINE_METASIG_T(SM(PtrResolver_PtrArrByte_PtrException_RetVoid, P(C(RESOLVER)) P(a(b)) P(C(EXCEPTION)), v)) diff --git a/src/coreclr/vm/wasm/entrypoints.h b/src/coreclr/vm/wasm/entrypoints.h index d53de7e63df3d1..69a3e0df64f7dd 100644 --- a/src/coreclr/vm/wasm/entrypoints.h +++ b/src/coreclr/vm/wasm/entrypoints.h @@ -8,7 +8,6 @@ #include #ifdef TARGET_BROWSER -extern "C" void SystemJS_MarkAsyncMain(); extern "C" void SystemJS_ResolveMainPromise(int exitCode); extern "C" void SystemJS_RejectMainPromise(const char16_t *message, int messageLength, const char16_t *stackTrace, int stackTraceLength); extern "C" void SystemJS_ScheduleTimer(int shortestDueTimeMs);