From 2bbc0dce126b38922682fe7f5f46d805029d438f Mon Sep 17 00:00:00 2001 From: dotnet-bot Date: Fri, 7 Apr 2017 09:15:14 -0700 Subject: [PATCH] ProjectX: Hook up class lib functions with type manager The class lib functions are already hooked up to code manager. However, there are cases where we look for class lib functions from EEtype, such as GetClasslibException on an eeype. This change attaches the class lib function array to every type manager and sets up a runtime helper to get to the class lib function GetRuntimeException from an EEtype. [tfs-changeset: 1653592] --- .../CompilerHelpers/StartupCodeHelpers.cs | 8 ++-- src/Native/Bootstrap/main.cpp | 8 ++-- src/Native/Runtime/EHHelpers.cpp | 29 +++++++++++- src/Native/Runtime/RuntimeInstance.cpp | 4 +- src/Native/Runtime/TypeManager.cpp | 19 ++++++-- src/Native/Runtime/TypeManager.h | 7 ++- .../src/System/Runtime/EEType.Runtime.cs | 2 +- .../src/System/Runtime/ExceptionHandling.cs | 44 +++++++++++++++++-- .../src/System/Runtime/InternalCalls.cs | 9 +++- .../src/System/Runtime/RuntimeImports.cs | 2 +- .../src/System/Runtime/RuntimeImports.cs | 2 +- 11 files changed, 107 insertions(+), 27 deletions(-) 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")]