diff options
Diffstat (limited to 'src/Native/Runtime/windows/CoffNativeCodeManager.cpp')
-rw-r--r-- | src/Native/Runtime/windows/CoffNativeCodeManager.cpp | 109 |
1 files changed, 98 insertions, 11 deletions
diff --git a/src/Native/Runtime/windows/CoffNativeCodeManager.cpp b/src/Native/Runtime/windows/CoffNativeCodeManager.cpp index 22a37bb92..ae8be443f 100644 --- a/src/Native/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/Native/Runtime/windows/CoffNativeCodeManager.cpp @@ -172,9 +172,11 @@ static PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntim CoffNativeCodeManager::CoffNativeCodeManager(TADDR moduleBase, + PTR_VOID pvManagedCodeStartRange, UInt32 cbManagedCodeRange, PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, UInt32 nRuntimeFunctionTable, PTR_PTR_VOID pClasslibFunctions, UInt32 nClasslibFunctions) : m_moduleBase(moduleBase), + m_pvManagedCodeStartRange(pvManagedCodeStartRange), m_cbManagedCodeRange(cbManagedCodeRange), m_pRuntimeFunctionTable(pRuntimeFunctionTable), m_nRuntimeFunctionTable(nRuntimeFunctionTable), m_pClasslibFunctions(pClasslibFunctions), m_nClasslibFunctions(nClasslibFunctions) { @@ -193,8 +195,6 @@ static int LookupUnwindInfoForMethod(UInt32 relativePc, relativePc |= THUMB_CODE; #endif - // Entries are sorted and terminated by sentinel value (DWORD)-1 - // Binary search the RUNTIME_FUNCTION table // Use linear search once we get down to a small number of elements // to avoid Binary search overhead. @@ -213,22 +213,23 @@ static int LookupUnwindInfoForMethod(UInt32 relativePc, } } - for (int i = low; i <= high; ++i) + for (int i = low; i < high; i++) { - // This is safe because of entries are terminated by sentinel value (DWORD)-1 PTR_RUNTIME_FUNCTION pNextFunctionEntry = pRuntimeFunctionTable + (i + 1); - if (relativePc < pNextFunctionEntry->BeginAddress) { - PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + i; - if (relativePc >= pFunctionEntry->BeginAddress) - { - return i; - } + high = i; break; } } + PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + high; + if (relativePc >= pFunctionEntry->BeginAddress) + { + return high; + } + + ASSERT_UNCONDITIONALLY("Invalid code address"); return -1; } @@ -245,6 +246,13 @@ static_assert(sizeof(CoffNativeMethodInfo) <= sizeof(MethodInfo), "CoffNativeMet bool CoffNativeCodeManager::FindMethodInfo(PTR_VOID ControlPC, MethodInfo * pMethodInfoOut) { + // Stackwalker may call this with ControlPC that does not belong to this code manager + if (dac_cast<TADDR>(ControlPC) < dac_cast<TADDR>(m_pvManagedCodeStartRange) || + dac_cast<TADDR>(m_pvManagedCodeStartRange) + m_cbManagedCodeRange <= dac_cast<TADDR>(ControlPC)) + { + return false; + } + CoffNativeMethodInfo * pMethodInfo = (CoffNativeMethodInfo *)pMethodInfoOut; TADDR relativePC = dac_cast<TADDR>(ControlPC) - m_moduleBase; @@ -372,9 +380,81 @@ void CoffNativeCodeManager::EnumGcRefs(MethodInfo * pMethodInfo, UIntNative CoffNativeCodeManager::GetConservativeUpperBoundForOutgoingArgs(MethodInfo * pMethodInfo, REGDISPLAY * pRegisterSet) { - // @TODO: CORERT: GetConservativeUpperBoundForOutgoingArgs +#if defined(_TARGET_AMD64_) + + // Return value + UIntNative upperBound; + CoffNativeMethodInfo* pNativeMethodInfo = (CoffNativeMethodInfo *) pMethodInfo; + + size_t unwindDataBlobSize; + PTR_VOID pUnwindDataBlob = GetUnwindDataBlob(m_moduleBase, pNativeMethodInfo->runtimeFunction, &unwindDataBlobSize); + PTR_UInt8 p = dac_cast<PTR_UInt8>(pUnwindDataBlob) + unwindDataBlobSize; + uint8_t unwindBlockFlags = *p++; + + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + + if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0) + { + TADDR basePointer = dac_cast<TADDR>(pRegisterSet->GetFP()); + + // Get the method's GC info + GcInfoDecoder decoder(GCInfoToken(p), DECODE_REVERSE_PINVOKE_VAR); + UINT32 stackBasedRegister = decoder.GetStackBaseRegister(); + + if (stackBasedRegister == NO_STACK_BASE_REGISTER) + { + basePointer = dac_cast<TADDR>(pRegisterSet->GetSP()); + } + else + { + basePointer = dac_cast<TADDR>(pRegisterSet->GetFP()); + } + // Reverse PInvoke case. The embedded reverse PInvoke frame is guaranteed to reside above + // all outgoing arguments. + INT32 slot = decoder.GetReversePInvokeFrameStackSlot(); + upperBound = (UIntNative) dac_cast<TADDR>(basePointer + slot); + } + else + { + // Check for a pushed RBP value + if (GetFramePointer(pMethodInfo, pRegisterSet) == NULL) + { + // Unwind the current method context to get the caller's stack pointer + // and obtain the upper bound of the callee is the value just below the caller's return address on the stack + SIZE_T EstablisherFrame; + PVOID HandlerData; + CONTEXT context; + context.Rsp = pRegisterSet->GetSP(); + context.Rbp = pRegisterSet->GetFP(); + context.Rip = pRegisterSet->GetIP(); + + RtlVirtualUnwind(NULL, + dac_cast<TADDR>(m_moduleBase), + pRegisterSet->IP, + (PRUNTIME_FUNCTION)pNativeMethodInfo->runtimeFunction, + &context, + &HandlerData, + &EstablisherFrame, + NULL); + + upperBound = dac_cast<TADDR>(context.Rsp - sizeof (PVOID)); + } + else + { + // In amd64, it is guaranteed that if there is a pushed RBP + // value at the top of the frame it resides above all outgoing arguments. Unlike x86, + // the frame pointer generally points to a location that is separated from the pushed RBP + // value by an offset that is recorded in the info header. Recover the address of the + // pushed RBP value by subtracting this offset. + upperBound = (UIntNative) dac_cast<TADDR>(pRegisterSet->GetFP() - ((PTR_UNWIND_INFO) pUnwindDataBlob)->FrameOffset); + } + } + return upperBound; +#else assert(false); return false; +#endif } bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, @@ -705,6 +785,12 @@ void * CoffNativeCodeManager::GetClasslibFunction(ClasslibFunctionId functionId) PTR_VOID CoffNativeCodeManager::GetAssociatedData(PTR_VOID ControlPC) { + if (dac_cast<TADDR>(ControlPC) < dac_cast<TADDR>(m_pvManagedCodeStartRange) || + dac_cast<TADDR>(m_pvManagedCodeStartRange) + m_cbManagedCodeRange <= dac_cast<TADDR>(ControlPC)) + { + return NULL; + } + TADDR relativePC = dac_cast<TADDR>(ControlPC) - m_moduleBase; int MethodIndex = LookupUnwindInfoForMethod((UInt32)relativePC, m_pRuntimeFunctionTable, 0, m_nRuntimeFunctionTable - 1); @@ -742,6 +828,7 @@ bool RhRegisterOSModule(void * pModule, IMAGE_DATA_DIRECTORY * pRuntimeFunctions = &(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]); NewHolder<CoffNativeCodeManager> pCoffNativeCodeManager = new (nothrow) CoffNativeCodeManager((TADDR)pModule, + pvManagedCodeStartRange, cbManagedCodeRange, dac_cast<PTR_RUNTIME_FUNCTION>((TADDR)pModule + pRuntimeFunctions->VirtualAddress), pRuntimeFunctions->Size / sizeof(RUNTIME_FUNCTION), pClasslibFunctions, nClasslibFunctions); |