diff --git a/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs b/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs index 4102beb5a5e..a91aef630f2 100644 --- a/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs +++ b/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs @@ -25,10 +25,10 @@ public static TypeManagerHandle[] Modules } [NativeCallable(EntryPoint = "InitializeModules", CallingConvention = CallingConvention.Cdecl)] - internal static void InitializeModules(IntPtr osModule, IntPtr moduleHeaders, int count) + internal static unsafe void InitializeModules(IntPtr osModule, IntPtr moduleHeaders, int count, IntPtr* pClasslibFunctions, int nClasslibFunctions) { RuntimeImports.RhpRegisterOsModule(osModule); - TypeManagerHandle[] modules = CreateTypeManagers(osModule, moduleHeaders, count); + TypeManagerHandle[] modules = CreateTypeManagers(osModule, moduleHeaders, count, pClasslibFunctions, nClasslibFunctions); for (int i = 0; i < modules.Length; i++) { @@ -48,7 +48,7 @@ internal static void InitializeModules(IntPtr osModule, IntPtr moduleHeaders, in } } - private static unsafe TypeManagerHandle[] CreateTypeManagers(IntPtr osModule, IntPtr moduleHeaders, int count) + private static unsafe TypeManagerHandle[] CreateTypeManagers(IntPtr osModule, IntPtr moduleHeaders, int count, IntPtr* pClasslibFunctions, int nClasslibFunctions) { // Count the number of modules so we can allocate an array to hold the TypeManager objects. // At this stage of startup, complex collection classes will not work. @@ -67,7 +67,7 @@ private static unsafe TypeManagerHandle[] CreateTypeManagers(IntPtr osModule, In for (int i = 0; i < count; i++) { if (((IntPtr*)moduleHeaders)[i] != IntPtr.Zero) - modules[moduleIndex++] = RuntimeImports.RhpCreateTypeManager(osModule, ((IntPtr*)moduleHeaders)[i]); + modules[moduleIndex++] = RuntimeImports.RhpCreateTypeManager(osModule, ((IntPtr*)moduleHeaders)[i], pClasslibFunctions, nClasslibFunctions); } return modules; diff --git a/src/Native/Bootstrap/main.cpp b/src/Native/Bootstrap/main.cpp index a4d77ab9338..232cd8c6d0d 100644 --- a/src/Native/Bootstrap/main.cpp +++ b/src/Native/Bootstrap/main.cpp @@ -211,7 +211,7 @@ extern "C" void RhpUniversalTransition_DebugStepTailCall() } extern "C" void CCWAddRef() { - throw "CCWAddRef"; + throw "CCWAddRef"; } void* RtRHeaderWrapper(); @@ -266,7 +266,7 @@ static const pfn c_classlibFunctions[] = { #endif // !CPPCODEGEN -extern "C" void InitializeModules(void* osModule, void ** modules, int count); +extern "C" void InitializeModules(void* osModule, void ** modules, int count, void ** pClasslibFunctions, int nClasslibFunctions); #if defined(_WIN32) extern "C" int __managed__Main(int argc, wchar_t* argv[]); @@ -308,9 +308,9 @@ int main(int argc, char* argv[]) #endif #ifndef CPPCODEGEN - InitializeModules(osModule, __modules_a, (int)((__modules_z - __modules_a))); + InitializeModules(osModule, __modules_a, (int)((__modules_z - __modules_a)), (void **)&c_classlibFunctions, _countof(c_classlibFunctions)); #else // !CPPCODEGEN - InitializeModules(nullptr, (void**)RtRHeaderWrapper(), 2); + InitializeModules(nullptr, (void**)RtRHeaderWrapper(), 2, nullptr, 0); #endif // !CPPCODEGEN int retval; diff --git a/src/Native/Runtime/EHHelpers.cpp b/src/Native/Runtime/EHHelpers.cpp index 3e0887c648c..64b5f27ce0c 100644 --- a/src/Native/Runtime/EHHelpers.cpp +++ b/src/Native/Runtime/EHHelpers.cpp @@ -25,6 +25,8 @@ #include "threadstore.h" #include "threadstore.inl" #include "stressLog.h" +#include "rhbinder.h" +#include "eetype.h" // Find the code manager containing the given address, which might be a return address from a managed function. The // address may be to another managed function, or it may be to an unmanaged function. The address may also refer to @@ -38,7 +40,6 @@ static ICodeManager * FindCodeManagerForClasslibFunction(void * address) if (pCodeManager != NULL) return pCodeManager; - // @TODO: CORERT: Do we need to make this work for CoreRT? // Less common, we will look for the address in any of the sections of the module. This is slower, but is // necessary for EEType pointers and jump stubs. Module * pModule = pRI->FindModuleByAddress(address); @@ -67,7 +68,7 @@ COOP_PINVOKE_HELPER(Boolean, RhpEHEnumNext, (EHEnum* pEHEnum, EHClause* pEHClaus // Unmanaged helper to locate one of two classlib-provided functions that the runtime needs to // implement throwing of exceptions out of Rtm, and fail-fast. This may return NULL if the classlib // found via the provided address does not have the necessary exports. -COOP_PINVOKE_HELPER(void *, RhpGetClasslibFunction, (void * address, ClasslibFunctionId functionId)) +COOP_PINVOKE_HELPER(void *, RhpGetClasslibFunctionFromCodeAddress, (void * address, ClasslibFunctionId functionId)) { // Find the code manager for the given address, which is an address into some managed module. It could // be code, or it could be an EEType. No matter what, it's an address into a managed module in some non-Rtm @@ -83,6 +84,30 @@ COOP_PINVOKE_HELPER(void *, RhpGetClasslibFunction, (void * address, ClasslibFun return pCodeManager->GetClasslibFunction(functionId); } +// Unmanaged helper to locate one of two classlib-provided functions that the runtime needs to +// implement throwing of exceptions out of Rtm, and fail-fast. This may return NULL if the classlib +// found via the provided address does not have the necessary exports. +COOP_PINVOKE_HELPER(void *, RhpGetClasslibFunctionFromEEtype, (EEType * pEEtype, ClasslibFunctionId functionId)) +{ + if (pEEtype->HasTypeManager()) + { + return pEEtype->GetTypeManagerPtr()->AsTypeManager()->GetClasslibFunction(functionId); + } + else + { + RuntimeInstance * pRI = GetRuntimeInstance(); + Module * pModule = pRI->FindModuleByAddress(pEEtype); + if (pModule != NULL) + { + return pModule->GetClasslibFunction(functionId); + } + else + { + return NULL; + } + } +} + COOP_PINVOKE_HELPER(void, RhpValidateExInfoStack, ()) { Thread * pThisThread = ThreadStore::GetCurrentThread(); diff --git a/src/Native/Runtime/RuntimeInstance.cpp b/src/Native/Runtime/RuntimeInstance.cpp index bb0fff7fd18..665b776366c 100644 --- a/src/Native/Runtime/RuntimeInstance.cpp +++ b/src/Native/Runtime/RuntimeInstance.cpp @@ -429,9 +429,9 @@ bool RuntimeInstance::RegisterTypeManager(TypeManager * pTypeManager) return true; } -COOP_PINVOKE_HELPER(TypeManagerHandle, RhpCreateTypeManager, (HANDLE osModule, void* pModuleHeader)) +COOP_PINVOKE_HELPER(TypeManagerHandle, RhpCreateTypeManager, (HANDLE osModule, void* pModuleHeader, PTR_PTR_VOID pClasslibFunctions, UInt32 nClasslibFunctions)) { - TypeManager * typeManager = TypeManager::Create(osModule, pModuleHeader); + TypeManager * typeManager = TypeManager::Create(osModule, pModuleHeader, pClasslibFunctions, nClasslibFunctions); GetRuntimeInstance()->RegisterTypeManager(typeManager); return TypeManagerHandle::Create(typeManager); } diff --git a/src/Native/Runtime/TypeManager.cpp b/src/Native/Runtime/TypeManager.cpp index b09de7fba0a..2b0da3f140e 100644 --- a/src/Native/Runtime/TypeManager.cpp +++ b/src/Native/Runtime/TypeManager.cpp @@ -24,7 +24,7 @@ #include "TypeManager.h" /* static */ -TypeManager * TypeManager::Create(HANDLE osModule, void * pModuleHeader) +TypeManager * TypeManager::Create(HANDLE osModule, void * pModuleHeader, void** pClasslibFunctions, UInt32 nClasslibFunctions) { ReadyToRunHeader * pReadyToRunHeader = (ReadyToRunHeader *)pModuleHeader; @@ -38,11 +38,12 @@ TypeManager * TypeManager::Create(HANDLE osModule, void * pModuleHeader) if (pReadyToRunHeader->MajorVersion != ReadyToRunHeaderConstants::CurrentMajorVersion) return nullptr; - return new (nothrow) TypeManager(osModule, pReadyToRunHeader); + return new (nothrow) TypeManager(osModule, pReadyToRunHeader, pClasslibFunctions, nClasslibFunctions); } -TypeManager::TypeManager(HANDLE osModule, ReadyToRunHeader * pHeader) - : m_osModule(osModule), m_pHeader(pHeader), m_pDispatchMapTable(nullptr) +TypeManager::TypeManager(HANDLE osModule, ReadyToRunHeader * pHeader, void** pClasslibFunctions, UInt32 nClasslibFunctions) + : m_osModule(osModule), m_pHeader(pHeader), m_pDispatchMapTable(nullptr), + m_pClasslibFunctions(pClasslibFunctions), m_nClasslibFunctions(nClasslibFunctions) { int length; m_pStaticsGCDataSection = (UInt8*)GetModuleSection(ReadyToRunSectionType::GCStaticRegion, &length); @@ -73,6 +74,16 @@ void * TypeManager::GetModuleSection(ReadyToRunSectionType sectionId, int * leng return nullptr; } +void * TypeManager::GetClasslibFunction(ClasslibFunctionId functionId) +{ + uint32_t id = (uint32_t)functionId; + + if (id >= m_nClasslibFunctions) + return nullptr; + + return m_pClasslibFunctions[id]; +} + DispatchMap** TypeManager::GetDispatchMapLookupTable() { if (m_pDispatchMapTable == nullptr) diff --git a/src/Native/Runtime/TypeManager.h b/src/Native/Runtime/TypeManager.h index df095a33695..1a5baa216a0 100644 --- a/src/Native/Runtime/TypeManager.h +++ b/src/Native/Runtime/TypeManager.h @@ -18,15 +18,18 @@ class TypeManager UInt8* m_pStaticsGCDataSection; UInt8* m_pThreadStaticsDataSection; UInt32* m_pTlsIndex; // Pointer to TLS index if this module uses thread statics + void** m_pClasslibFunctions; + UInt32 m_nClasslibFunctions; - TypeManager(HANDLE osModule, ReadyToRunHeader * pHeader); + TypeManager(HANDLE osModule, ReadyToRunHeader * pHeader, void** pClasslibFunctions, UInt32 nClasslibFunctions); public: - static TypeManager * Create(HANDLE osModule, void * pModuleHeader); + static TypeManager * Create(HANDLE osModule, void * pModuleHeader, void** pClasslibFunctions, UInt32 nClasslibFunctions); void * GetModuleSection(ReadyToRunSectionType sectionId, int * length); DispatchMap ** GetDispatchMapLookupTable(); void EnumStaticGCRefs(void * pfnCallback, void * pvCallbackData); HANDLE GetOsModuleHandle(); + void* GetClasslibFunction(ClasslibFunctionId functionId); private: diff --git a/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs b/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs index 4463ed6b85e..b517cb77f78 100644 --- a/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs +++ b/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs @@ -50,7 +50,7 @@ internal Exception GetClasslibException(ExceptionIDs id) return RelatedParameterType->GetClasslibException(id); } - return EH.GetClasslibException(id, GetAssociatedModuleAddress()); + return EH.GetClasslibExceptionFromEEType(id, GetAssociatedModuleAddress()); #endif } diff --git a/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs index 48eb0c950ab..c4f7b07c3c6 100644 --- a/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs +++ b/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs @@ -162,7 +162,7 @@ internal static void FailFastViaClasslib(RhFailFastReason reason, object unhandl { // Find the classlib function that will fail fast. This is a RuntimeExport function from the // classlib module, and is therefore managed-callable. - IntPtr pFailFastFunction = (IntPtr)InternalCalls.RhpGetClasslibFunction(classlibAddress, + IntPtr pFailFastFunction = (IntPtr)InternalCalls.RhpGetClasslibFunctionFromCodeAddress(classlibAddress, ClassLibFunctionId.FailFast); if (pFailFastFunction == IntPtr.Zero) @@ -214,7 +214,7 @@ internal static unsafe void UnhandledExceptionFailFastViaClasslib( RhFailFastReason reason, object unhandledException, IntPtr classlibAddress, ref ExInfo exInfo) { IntPtr pFailFastFunction = - (IntPtr)InternalCalls.RhpGetClasslibFunction(classlibAddress, ClassLibFunctionId.FailFast); + (IntPtr)InternalCalls.RhpGetClasslibFunctionFromCodeAddress(classlibAddress, ClassLibFunctionId.FailFast); if (pFailFastFunction == IntPtr.Zero) { @@ -253,7 +253,7 @@ private enum RhEHFrameType private static void AppendExceptionStackFrameViaClasslib(object exception, IntPtr IP, ref bool isFirstRethrowFrame, ref bool isFirstFrame) { - IntPtr pAppendStackFrame = (IntPtr)InternalCalls.RhpGetClasslibFunction(IP, + IntPtr pAppendStackFrame = (IntPtr)InternalCalls.RhpGetClasslibFunctionFromCodeAddress(IP, ClassLibFunctionId.AppendExceptionStackFrame); if (pAppendStackFrame != IntPtr.Zero) @@ -284,7 +284,7 @@ internal static Exception GetClasslibException(ExceptionIDs id, IntPtr address) // Find the classlib function that will give us the exception object we want to throw. This // is a RuntimeExport function from the classlib module, and is therefore managed-callable. IntPtr pGetRuntimeExceptionFunction = - (IntPtr)InternalCalls.RhpGetClasslibFunction(address, ClassLibFunctionId.GetRuntimeException); + (IntPtr)InternalCalls.RhpGetClasslibFunctionFromCodeAddress(address, ClassLibFunctionId.GetRuntimeException); // Return the exception object we get from the classlib. Exception e = null; @@ -309,6 +309,42 @@ internal static Exception GetClasslibException(ExceptionIDs id, IntPtr address) return e; } + // Given an ExceptionID and an EEtype address, get an exception object of a type that the module containing + // the given address will understand. This finds the classlib-defined GetRuntimeException function and asks + // it for the exception object. + internal static Exception GetClasslibExceptionFromEEType(ExceptionIDs id, IntPtr pEEType) + { + // Find the classlib function that will give us the exception object we want to throw. This + // is a RuntimeExport function from the classlib module, and is therefore managed-callable. + IntPtr pGetRuntimeExceptionFunction = IntPtr.Zero; + if (pEEType != IntPtr.Zero) + { + pGetRuntimeExceptionFunction = (IntPtr)InternalCalls.RhpGetClasslibFunctionFromEEtype(pEEType, ClassLibFunctionId.GetRuntimeException); + } + + // Return the exception object we get from the classlib. + Exception e = null; + try + { + e = CalliIntrinsics.Call(pGetRuntimeExceptionFunction, id); + } + catch + { + // disallow all exceptions leaking out of callbacks + } + + // If the helper fails to yield an object, then we fail-fast. + if (e == null) + { + FailFastViaClasslib( + RhFailFastReason.ClassLibDidNotTranslateExceptionID, + null, + pEEType); + } + + return e; + } + // RhExceptionHandling_ functions are used to throw exceptions out of our asm helpers. We tail-call from // the asm helpers to these functions, which performs the throw. The tail-call is important: it ensures that // the stack is crawlable from within these functions. diff --git a/src/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/Runtime.Base/src/System/Runtime/InternalCalls.cs index 3d420ef7a49..26bc3336ef3 100644 --- a/src/Runtime.Base/src/System/Runtime/InternalCalls.cs +++ b/src/Runtime.Base/src/System/Runtime/InternalCalls.cs @@ -224,10 +224,15 @@ internal static Int32 RhEndNoGCRegion() [ManuallyManaged(GcPollPolicy.Never)] internal extern static unsafe IntPtr RhpUpdateDispatchCellCache(IntPtr pCell, IntPtr pTargetCode, EEType* pInstanceType, ref DispatchCellInfo newCellInfo); - [RuntimeImport(Redhawk.BaseName, "RhpGetClasslibFunction")] + [RuntimeImport(Redhawk.BaseName, "RhpGetClasslibFunctionFromCodeAddress")] [MethodImpl(MethodImplOptions.InternalCall)] [ManuallyManaged(GcPollPolicy.Never)] - internal extern static unsafe void* RhpGetClasslibFunction(IntPtr address, EH.ClassLibFunctionId id); + internal extern static unsafe void* RhpGetClasslibFunctionFromCodeAddress(IntPtr address, EH.ClassLibFunctionId id); + + [RuntimeImport(Redhawk.BaseName, "RhpGetClasslibFunctionFromEEtype")] + [MethodImpl(MethodImplOptions.InternalCall)] + [ManuallyManaged(GcPollPolicy.Never)] + internal extern static unsafe void* RhpGetClasslibFunctionFromEEtype(IntPtr pEEType, EH.ClassLibFunctionId id); // // StackFrameIterator diff --git a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 52c62b5981d..1df7edb1692 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -468,7 +468,7 @@ internal static unsafe bool RhFindBlob(TypeManagerHandle typeManagerHandle, uint [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhpCreateTypeManager")] - internal static extern unsafe TypeManagerHandle RhpCreateTypeManager(IntPtr osModule, IntPtr moduleHeader); + internal static extern unsafe TypeManagerHandle RhpCreateTypeManager(IntPtr osModule, IntPtr moduleHeader, IntPtr* pClasslibFunctions, int nClasslibFunctions); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhpRegisterOsModule")] diff --git a/src/Test.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/Test.CoreLib/src/System/Runtime/RuntimeImports.cs index 1c8c1e35f39..ecdda3bdc07 100644 --- a/src/Test.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/Test.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -56,7 +56,7 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhpCreateTypeManager")] - internal static extern unsafe TypeManagerHandle RhpCreateTypeManager(IntPtr osModule, IntPtr moduleHeader); + internal static extern unsafe TypeManagerHandle RhpCreateTypeManager(IntPtr osModule, IntPtr moduleHeader, IntPtr* pClasslibFunctions, int nClasslibFunctions); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhpRegisterOsModule")]