diff options
author | Fadi Hanna <fadim@microsoft.com> | 2017-09-13 01:07:07 +0300 |
---|---|---|
committer | Fadi Hanna <fadim@microsoft.com> | 2017-09-13 01:07:07 +0300 |
commit | 92a6a3b1ae4aff4b3a904fed104d253f7d863a36 (patch) | |
tree | 6933a7db8ebdb1ba0338019137e65b75dfe9a2a0 /src/Native | |
parent | 665c60acc7f188d4a5e81c96f39431de1352b901 (diff) |
These changes provide a way for ProjectX/CoreRT to get the target of custom instantiating unboxing stubs.
The implementation uses a general purpose infrastructure that can associate custom data to methods with unwind info, given the fact that unwind info lookups are very fast.
Similar to GC info and EH info, this implementation now provides a way to associate any custom data to methods, by adding a flag and a reloc to the data in the method's unwind info.
The custom data that can be attached to methods begin with a flag (indicating what data follows), followed by data.
Right now, the only custom data we have for methods are unboxing stub target pointers.
The dependency analysis models this custom data using a new node type: MethodAssociatedDataNode.
The custom data (when it exists) can be be retrieved using a new API on ICodeManager.
The changes also include all the necessary plumbing to link custom data nodes symbols for PX (given that it's UTC that emits the unwind info)
[tfs-changeset: 1673664]
Diffstat (limited to 'src/Native')
-rw-r--r-- | src/Native/Runtime/ICodeManager.h | 11 | ||||
-rw-r--r-- | src/Native/Runtime/MiscHelpers.cpp | 5 | ||||
-rw-r--r-- | src/Native/Runtime/RuntimeInstance.cpp | 18 | ||||
-rw-r--r-- | src/Native/Runtime/RuntimeInstance.h | 1 | ||||
-rw-r--r-- | src/Native/Runtime/module.cpp | 8 | ||||
-rw-r--r-- | src/Native/Runtime/module.h | 2 | ||||
-rw-r--r-- | src/Native/Runtime/unix/UnixNativeCodeManager.cpp | 30 | ||||
-rw-r--r-- | src/Native/Runtime/unix/UnixNativeCodeManager.h | 2 | ||||
-rw-r--r-- | src/Native/Runtime/windows/CoffNativeCodeManager.cpp | 41 | ||||
-rw-r--r-- | src/Native/Runtime/windows/CoffNativeCodeManager.h | 2 | ||||
-rw-r--r-- | src/Native/jitinterface/JITCodeManager.cpp | 7 | ||||
-rw-r--r-- | src/Native/jitinterface/JITCodeManager.h | 4 |
12 files changed, 124 insertions, 7 deletions
diff --git a/src/Native/Runtime/ICodeManager.h b/src/Native/Runtime/ICodeManager.h index 7cbfc1838..3d5af20fd 100644 --- a/src/Native/Runtime/ICodeManager.h +++ b/src/Native/Runtime/ICodeManager.h @@ -80,6 +80,12 @@ enum class ClasslibFunctionId OnFirstChanceException = 6, }; +enum class AssociatedDataFlags : unsigned char +{ + None = 0, + HasUnboxingStubTarget = 1, +}; + class ICodeManager { public: @@ -119,4 +125,9 @@ public: virtual PTR_VOID GetMethodStartAddress(MethodInfo * pMethodInfo) = 0; virtual void * GetClasslibFunction(ClasslibFunctionId functionId) = 0; + + // Returns any custom data attached to the method. Format: + // AssociatedDataFlags // 1 byte. Flags describing the data stored + // Data (stream of bytes) // Variable size (depending on flags). Custom data associated with method + virtual PTR_VOID GetAssociatedData(PTR_VOID ControlPC) = 0; }; diff --git a/src/Native/Runtime/MiscHelpers.cpp b/src/Native/Runtime/MiscHelpers.cpp index eaf55a79a..507ffa608 100644 --- a/src/Native/Runtime/MiscHelpers.cpp +++ b/src/Native/Runtime/MiscHelpers.cpp @@ -332,6 +332,11 @@ COOP_PINVOKE_HELPER(void *, GetClasslibCCtorCheck, (void * pReturnAddress)) return pCallback; } +COOP_PINVOKE_HELPER(void *, RhGetTargetOfUnboxingAndInstantiatingStub, (void * pUnboxStub)) +{ + return GetRuntimeInstance()->GetTargetOfUnboxingAndInstantiatingStub(pUnboxStub); +} + COOP_PINVOKE_HELPER(Boolean, RhpHasDispatchMap, (EEType * pEEType)) { return pEEType->HasDispatchMap(); diff --git a/src/Native/Runtime/RuntimeInstance.cpp b/src/Native/Runtime/RuntimeInstance.cpp index b7254a401..35f22d38c 100644 --- a/src/Native/Runtime/RuntimeInstance.cpp +++ b/src/Native/Runtime/RuntimeInstance.cpp @@ -181,6 +181,24 @@ ICodeManager * RuntimeInstance::FindCodeManagerByAddress(PTR_VOID pvAddress) return NULL; } +PTR_UInt8 RuntimeInstance::GetTargetOfUnboxingAndInstantiatingStub(PTR_VOID ControlPC) +{ + ICodeManager * pCodeManager = FindCodeManagerByAddress(ControlPC); + if (pCodeManager != NULL) + { + PTR_UInt8 pData = (PTR_UInt8)pCodeManager->GetAssociatedData(ControlPC); + if (pData != NULL) + { + UInt8 flags = *pData++; + + if ((flags & (UInt8)AssociatedDataFlags::HasUnboxingStubTarget) != 0) + return *((PTR_PTR_UInt8)pData); + } + } + + return NULL; +} + GPTR_IMPL_INIT(RuntimeInstance, g_pTheRuntimeInstance, NULL); PTR_RuntimeInstance GetRuntimeInstance() diff --git a/src/Native/Runtime/RuntimeInstance.h b/src/Native/Runtime/RuntimeInstance.h index 3d1ab3ed6..bd001fd19 100644 --- a/src/Native/Runtime/RuntimeInstance.h +++ b/src/Native/Runtime/RuntimeInstance.h @@ -174,6 +174,7 @@ public: Module * FindModuleByReadOnlyDataAddress(PTR_VOID Data); Module * FindModuleByOsHandle(HANDLE hOsHandle); PTR_UInt8 FindMethodStartAddress(PTR_VOID ControlPC); + PTR_UInt8 GetTargetOfUnboxingAndInstantiatingStub(PTR_VOID ControlPC); void EnableConservativeStackReporting(); bool IsConservativeStackReportingEnabled() { return m_conservativeStackReportingEnabled; } diff --git a/src/Native/Runtime/module.cpp b/src/Native/Runtime/module.cpp index f17eb2857..a83571cae 100644 --- a/src/Native/Runtime/module.cpp +++ b/src/Native/Runtime/module.cpp @@ -832,6 +832,14 @@ void * Module::GetClasslibFunction(ClasslibFunctionId functionId) return pMethod; } +PTR_VOID Module::GetAssociatedData(PTR_VOID ControlPC) +{ + UNREFERENCED_PARAMETER(ControlPC); + + // Not supported for ProjectN. + return NULL; +} + // Get classlib-defined helper for running deferred static class constructors. Returns NULL if this is not the // classlib module or the classlib doesn't implement this callback. void * Module::GetClasslibCheckStaticClassConstruction() diff --git a/src/Native/Runtime/module.h b/src/Native/Runtime/module.h index a037bc828..f1a48b2a8 100644 --- a/src/Native/Runtime/module.h +++ b/src/Native/Runtime/module.h @@ -113,6 +113,8 @@ public: void * RecoverLoopHijackTarget(UInt32 entryIndex, ModuleHeader * pModuleHeader); + PTR_VOID GetAssociatedData(PTR_VOID ControlPC); + private: Module(ModuleHeader * pModuleHeader); #ifdef FEATURE_CUSTOM_IMPORTS diff --git a/src/Native/Runtime/unix/UnixNativeCodeManager.cpp b/src/Native/Runtime/unix/UnixNativeCodeManager.cpp index e60e60130..445b6e00a 100644 --- a/src/Native/Runtime/unix/UnixNativeCodeManager.cpp +++ b/src/Native/Runtime/unix/UnixNativeCodeManager.cpp @@ -25,9 +25,9 @@ #define UBF_FUNC_KIND_HANDLER 0x01 #define UBF_FUNC_KIND_FILTER 0x02 -#define UBF_FUNC_HAS_EHINFO 0x04 - -#define UBF_FUNC_REVERSE_PINVOKE 0x08 +#define UBF_FUNC_HAS_EHINFO 0x04 +#define UBF_FUNC_REVERSE_PINVOKE 0x08 +#define UBF_FUNC_HAS_ASSOCIATED_DATA 0x10 struct UnixNativeMethodInfo { @@ -130,6 +130,9 @@ void UnixNativeCodeManager::EnumGcRefs(MethodInfo * pMethodInfo, uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0) p += sizeof(int32_t); @@ -176,6 +179,9 @@ bool UnixNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0) { // Reverse PInvoke transition should on the main function body only @@ -265,6 +271,9 @@ bool UnixNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + // return if there is no EH info associated with this method if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) == 0) { @@ -356,6 +365,21 @@ void * UnixNativeCodeManager::GetClasslibFunction(ClasslibFunctionId functionId) return m_pClasslibFunctions[id]; } +PTR_VOID UnixNativeCodeManager::GetAssociatedData(PTR_VOID ControlPC) +{ + UnixNativeMethodInfo methodInfo; + if (!FindMethodInfo(ControlPC, &methodInfo)) + return NULL; + + PTR_UInt8 p = methodInfo.pMainLSDA; + + uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) == 0) + return NULL; + + return dac_cast<PTR_VOID>(p + *dac_cast<PTR_Int32>(p)); +} + extern "C" bool __stdcall RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID pvStartRange, UInt32 cbRange); extern "C" void __stdcall UnregisterCodeManager(ICodeManager * pCodeManager); extern "C" bool __stdcall RegisterUnboxingStubs(PTR_VOID pvStartRange, UInt32 cbRange); diff --git a/src/Native/Runtime/unix/UnixNativeCodeManager.h b/src/Native/Runtime/unix/UnixNativeCodeManager.h index e424a559c..13333ee73 100644 --- a/src/Native/Runtime/unix/UnixNativeCodeManager.h +++ b/src/Native/Runtime/unix/UnixNativeCodeManager.h @@ -58,4 +58,6 @@ public: PTR_VOID GetMethodStartAddress(MethodInfo * pMethodInfo); void * GetClasslibFunction(ClasslibFunctionId functionId); + + PTR_VOID GetAssociatedData(PTR_VOID ControlPC); }; diff --git a/src/Native/Runtime/windows/CoffNativeCodeManager.cpp b/src/Native/Runtime/windows/CoffNativeCodeManager.cpp index 6690ffeb2..fa162aa75 100644 --- a/src/Native/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/Native/Runtime/windows/CoffNativeCodeManager.cpp @@ -25,9 +25,9 @@ #define UBF_FUNC_KIND_HANDLER 0x01 #define UBF_FUNC_KIND_FILTER 0x02 -#define UBF_FUNC_HAS_EHINFO 0x04 - -#define UBF_FUNC_REVERSE_PINVOKE 0x08 +#define UBF_FUNC_HAS_EHINFO 0x04 +#define UBF_FUNC_REVERSE_PINVOKE 0x08 +#define UBF_FUNC_HAS_ASSOCIATED_DATA 0x10 #if defined(_TARGET_AMD64_) @@ -297,6 +297,9 @@ void CoffNativeCodeManager::EnumGcRefs(MethodInfo * pMethodInfo, uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0) p += sizeof(int32_t); @@ -347,6 +350,9 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0) { // Reverse PInvoke transition should on the main function body only @@ -455,6 +461,9 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + // Check whether this is a funclet if ((unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT) return false; @@ -550,6 +559,9 @@ bool CoffNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + // return if there is no EH info associated with this method if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) == 0) { @@ -634,6 +646,29 @@ void * CoffNativeCodeManager::GetClasslibFunction(ClasslibFunctionId functionId) return m_pClasslibFunctions[id]; } +PTR_VOID CoffNativeCodeManager::GetAssociatedData(PTR_VOID ControlPC) +{ + TADDR relativePC = dac_cast<TADDR>(ControlPC) - m_moduleBase; + + int MethodIndex = LookupUnwindInfoForMethod((UInt32)relativePC, m_pRuntimeFunctionTable, 0, m_nRuntimeFunctionTable - 1); + if (MethodIndex < 0) + return NULL; + + PTR_RUNTIME_FUNCTION pRuntimeFunction = m_pRuntimeFunctionTable + MethodIndex; + + size_t unwindDataBlobSize; + PTR_UInt8 pUnwindDataBlob = GetUnwindDataBlob(m_moduleBase, pRuntimeFunction, &unwindDataBlobSize); + + PTR_UInt8 p = dac_cast<PTR_UInt8>(pUnwindDataBlob) + unwindDataBlobSize; + + uint8_t unwindBlockFlags = *p++; + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) == 0) + return NULL; + + UInt32 dataRVA = *(UInt32*)p; + return m_moduleBase + dataRVA; +} + extern "C" bool __stdcall RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID pvStartRange, UInt32 cbRange); extern "C" void __stdcall UnregisterCodeManager(ICodeManager * pCodeManager); extern "C" bool __stdcall RegisterUnboxingStubs(PTR_VOID pvStartRange, UInt32 cbRange); diff --git a/src/Native/Runtime/windows/CoffNativeCodeManager.h b/src/Native/Runtime/windows/CoffNativeCodeManager.h index 09b960386..b0d5390a4 100644 --- a/src/Native/Runtime/windows/CoffNativeCodeManager.h +++ b/src/Native/Runtime/windows/CoffNativeCodeManager.h @@ -94,4 +94,6 @@ public: PTR_VOID GetMethodStartAddress(MethodInfo * pMethodInfo); void * GetClasslibFunction(ClasslibFunctionId functionId); + + PTR_VOID GetAssociatedData(PTR_VOID ControlPC); }; diff --git a/src/Native/jitinterface/JITCodeManager.cpp b/src/Native/jitinterface/JITCodeManager.cpp index fac0f426e..e16da72a9 100644 --- a/src/Native/jitinterface/JITCodeManager.cpp +++ b/src/Native/jitinterface/JITCodeManager.cpp @@ -730,3 +730,10 @@ void * JITCodeManager::GetClasslibFunction(ClasslibFunctionId functionId) assert(false); return false; } + +PTR_VOID JITCodeManager::GetAssociatedData(PTR_VOID ControlPC) +{ + // @TODO: CORERT: GetAssociatedData + assert(false); + return NULL; +} diff --git a/src/Native/jitinterface/JITCodeManager.h b/src/Native/jitinterface/JITCodeManager.h index 294a48016..4b0212943 100644 --- a/src/Native/jitinterface/JITCodeManager.h +++ b/src/Native/jitinterface/JITCodeManager.h @@ -276,4 +276,6 @@ public: PTR_VOID GetMethodStartAddress(MethodInfo * pMethodInfo); void * GetClasslibFunction(ClasslibFunctionId functionId); -};
\ No newline at end of file + + PTR_VOID GetAssociatedData(PTR_VOID ControlPC); +}; |