diff options
author | Mike McLaughlin <mikem@microsoft.com> | 2016-08-31 12:27:12 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-08-31 12:27:12 -0700 |
commit | 97448547841a58e3b74459d35a48c2b7978d97bc (patch) | |
tree | d14b30a9cd17e2c54fbabb4ebb8cd1bd778096d2 /src/debug | |
parent | b73fad38425cd52008d830f7207f81873415e1a5 (diff) | |
download | coreclr-97448547841a58e3b74459d35a48c2b7978d97bc.tar.gz coreclr-97448547841a58e3b74459d35a48c2b7978d97bc.tar.bz2 coreclr-97448547841a58e3b74459d35a48c2b7978d97bc.zip |
Fix funceval of a function returning 16 byte value type. (#6997)
On Linux and OS X, structs less or equal to 16 bytes (instead of 8 bytes
on Windows) are enregistered. Only 8 bytes is being passed back to
debugger during a funceval of a property or method that returns a 16
byte value type.
To fix this, the 16 byte return value (which is only used for enregistered
structures of that size on xplat) needed to be plumbed from CallTargetWorker
through the MethodDescCallSite macros to the func eval code.
The func eval code needed to also deal with 16 byte results.
NUMBER_RETURNVALUE_SLOTS is the number of ARG_SLOTs that will contain the
maximum enregistered return value.
CordbEval:m_result is now ARG_SLOT[NUMBER_RETURNVALUE_SLOTS].
CallTargetWorker is now passed a pointer and the count of bytes to/of the
return value buffer.
Minor fix to SOS SymbolReader function.
Diffstat (limited to 'src/debug')
-rw-r--r-- | src/debug/ee/debugger.cpp | 15 | ||||
-rw-r--r-- | src/debug/ee/debugger.h | 2 | ||||
-rw-r--r-- | src/debug/ee/funceval.cpp | 38 |
3 files changed, 27 insertions, 28 deletions
diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp index a9876abc35..a06811c817 100644 --- a/src/debug/ee/debugger.cpp +++ b/src/debug/ee/debugger.cpp @@ -1463,7 +1463,7 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval m_genericArgsNodeCount = pEvalInfo->genericArgsNodeCount; m_successful = false; m_argData = NULL; - m_result = 0; + memset(m_result, 0, sizeof(m_result)); m_md = NULL; m_resultType = TypeHandle(); m_aborting = FE_ABORT_NONE; @@ -1519,7 +1519,7 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, Thread * pThread, Thread::ThreadA m_successful = false; m_argData = NULL; m_targetCodeAddr = NULL; - m_result = 0; + memset(m_result, 0, sizeof(m_result)); m_md = NULL; m_resultType = TypeHandle(); m_aborting = FE_ABORT_NONE; @@ -10353,7 +10353,7 @@ void Debugger::FuncEvalComplete(Thread* pThread, DebuggerEval *pDE) if (CORDBUnrecoverableError(this)) return; - LOG((LF_CORDB, LL_INFO10000, "D::FEC: func eval complete pDE:%08x evalType:%d %s %s\n", + LOG((LF_CORDB, LL_INFO1000, "D::FEC: func eval complete pDE:%p evalType:%d %s %s\n", pDE, pDE->m_evalType, pDE->m_successful ? "Success" : "Fail", pDE->m_aborted ? "Abort" : "Completed")); @@ -10386,11 +10386,11 @@ void Debugger::FuncEvalComplete(Thread* pThread, DebuggerEval *pDE) ipce->FuncEvalComplete.funcEvalKey = pDE->m_funcEvalKey; ipce->FuncEvalComplete.successful = pDE->m_successful; ipce->FuncEvalComplete.aborted = pDE->m_aborted; - ipce->FuncEvalComplete.resultAddr = &(pDE->m_result); + ipce->FuncEvalComplete.resultAddr = pDE->m_result; ipce->FuncEvalComplete.vmAppDomain.SetRawPtr(pResultDomain); ipce->FuncEvalComplete.vmObjectHandle = pDE->m_vmObjectHandle; - LOG((LF_CORDB, LL_INFO10000, "D::FEC: TypeHandle is :%08x\n", pDE->m_resultType.AsPtr())); + LOG((LF_CORDB, LL_INFO1000, "D::FEC: TypeHandle is %p\n", pDE->m_resultType.AsPtr())); Debugger::TypeHandleToExpandedTypeInfo(pDE->m_retValueBoxing, // whether return values get boxed or not depends on the particular FuncEval we're doing... pResultDomain, @@ -10399,12 +10399,13 @@ void Debugger::FuncEvalComplete(Thread* pThread, DebuggerEval *pDE) _ASSERTE(ipce->FuncEvalComplete.resultType.elementType != ELEMENT_TYPE_VALUETYPE); - LOG((LF_CORDB, LL_INFO10000, "D::FEC: returned from call\n")); - // We must adjust the result address to point to the right place ipce->FuncEvalComplete.resultAddr = ArgSlotEndianessFixup((ARG_SLOT*)ipce->FuncEvalComplete.resultAddr, GetSizeForCorElementType(ipce->FuncEvalComplete.resultType.elementType)); + LOG((LF_CORDB, LL_INFO1000, "D::FEC: returned el %04x resultAddr %p\n", + ipce->FuncEvalComplete.resultType.elementType, ipce->FuncEvalComplete.resultAddr)); + m_pRCThread->SendIPCEvent(); #endif diff --git a/src/debug/ee/debugger.h b/src/debug/ee/debugger.h index 4558468182..6368647946 100644 --- a/src/debug/ee/debugger.h +++ b/src/debug/ee/debugger.h @@ -3431,7 +3431,7 @@ public: BYTE *m_argData; MethodDesc *m_md; PCODE m_targetCodeAddr; - INT64 m_result; + ARG_SLOT m_result[NUMBER_RETURNVALUE_SLOTS]; TypeHandle m_resultType; SIZE_T m_arrayRank; FUNC_EVAL_ABORT_TYPE m_aborting; // Has an abort been requested, and what type. diff --git a/src/debug/ee/funceval.cpp b/src/debug/ee/funceval.cpp index d2e5576855..eb8950deab 100644 --- a/src/debug/ee/funceval.cpp +++ b/src/debug/ee/funceval.cpp @@ -2775,7 +2775,7 @@ void UnpackFuncEvalResult(DebuggerEval *pDE, { // We purposely do not morph nullables to be boxed Ts here because debugger EE's otherwise // have no way of creating true nullables that they need for their own purposes. - pDE->m_result = ObjToArgSlot(newObj); + pDE->m_result[0] = ObjToArgSlot(newObj); pDE->m_retValueBoxing = Debugger::AllBoxed; } else if (!RetValueType.IsNull()) @@ -2803,12 +2803,12 @@ void UnpackFuncEvalResult(DebuggerEval *pDE, { // box the primitive returned, retObject is a true nullable for nullabes, It will be Normalized later CopyValueClass(retObject->GetData(), - &(pDE->m_result), + pDE->m_result, RetValueType.GetMethodTable(), retObject->GetAppDomain()); } - pDE->m_result = ObjToArgSlot(retObject); + pDE->m_result[0] = ObjToArgSlot(retObject); pDE->m_retValueBoxing = Debugger::AllBoxed; } else @@ -2833,8 +2833,8 @@ void UnpackFuncEvalResult(DebuggerEval *pDE, IsElementTypeSpecial(retClassET)) { LOG((LF_CORDB, LL_EVERYTHING, "Creating strong handle for boxed DoNormalFuncEval result.\n")); - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result)); - pDE->m_result = (INT64)(LONG_PTR)oh; + OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result[0])); + pDE->m_result[0] = (INT64)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); } } @@ -2930,13 +2930,13 @@ void UnpackFuncEvalArguments(DebuggerEval *pDE, * None. * */ -void FuncEvalWrapper(MethodDescCallSite* pMDCS, DebuggerEval *pDE, ARG_SLOT *pArguments, BYTE *pCatcherStackAddr) +void FuncEvalWrapper(MethodDescCallSite* pMDCS, DebuggerEval *pDE, const ARG_SLOT *pArguments, BYTE *pCatcherStackAddr) { struct Param : NotifyOfCHFFilterWrapperParam { MethodDescCallSite* pMDCS; DebuggerEval *pDE; - ARG_SLOT *pArguments; + const ARG_SLOT *pArguments; }; Param param; @@ -2947,7 +2947,7 @@ void FuncEvalWrapper(MethodDescCallSite* pMDCS, DebuggerEval *pDE, ARG_SLOT *pAr PAL_TRY(Param *, pParam, ¶m) { - pParam->pDE->m_result = pParam->pMDCS->CallWithValueTypes_RetArgSlot(pParam->pArguments); + pParam->pMDCS->CallWithValueTypes_RetArgSlot(pParam->pArguments, pParam->pDE->m_result, sizeof(pParam->pDE->m_result)); } PAL_EXCEPT_FILTER(NotifyOfCHFFilterWrapper) { @@ -3003,13 +3003,12 @@ static void RecordFuncEvalException(DebuggerEval *pDE, // // This is the abort we sent down. // - pDE->m_result = NULL; + memset(pDE->m_result, 0, sizeof(pDE->m_result)); pDE->m_resultType = TypeHandle(); pDE->m_aborted = true; pDE->m_retValueBoxing = Debugger::NoValueTypeBoxing; LOG((LF_CORDB, LL_EVERYTHING, "D::FEHW - funceval abort exception.\n")); - } else { @@ -3022,11 +3021,11 @@ static void RecordFuncEvalException(DebuggerEval *pDE, // // The result is the exception object. // - pDE->m_result = ObjToArgSlot(ppException); + pDE->m_result[0] = ObjToArgSlot(ppException); pDE->m_resultType = ppException->GetTypeHandle(); - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result)); - pDE->m_result = (INT64)PTR_TO_CORDB_ADDRESS(oh); + OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result[0])); + pDE->m_result[0] = (ARG_SLOT)PTR_TO_CORDB_ADDRESS(oh); pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); pDE->m_retValueBoxing = Debugger::NoValueTypeBoxing; @@ -3035,15 +3034,14 @@ static void RecordFuncEvalException(DebuggerEval *pDE, } else { - // // The result is the exception object. // - pDE->m_result = ObjToArgSlot(ppException); + pDE->m_result[0] = ObjToArgSlot(ppException); pDE->m_resultType = ppException->GetTypeHandle(); - OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result)); - pDE->m_result = (INT64)(LONG_PTR)oh; + OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(ArgSlotToObj(pDE->m_result[0])); + pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); pDE->m_retValueBoxing = Debugger::NoValueTypeBoxing; @@ -3597,7 +3595,7 @@ void FuncEvalHijackRealWorker(DebuggerEval *pDE, Thread* pThread, FuncEvalFrame* // Make a strong handle for the result. OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(newObj); - pDE->m_result = (INT64)(LONG_PTR)oh; + pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); break; @@ -3627,7 +3625,7 @@ void FuncEvalHijackRealWorker(DebuggerEval *pDE, Thread* pThread, FuncEvalFrame* // Place the result in a strong handle to protect it from a collection. OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(newObj); - pDE->m_result = (INT64)(LONG_PTR)oh; + pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); break; @@ -3673,7 +3671,7 @@ void FuncEvalHijackRealWorker(DebuggerEval *pDE, Thread* pThread, FuncEvalFrame* // Place the result in a strong handle to protect it from a collection. OBJECTHANDLE oh = pDE->m_thread->GetDomain()->CreateStrongHandle(newObj); - pDE->m_result = (INT64)(LONG_PTR)oh; + pDE->m_result[0] = (ARG_SLOT)(LONG_PTR)oh; pDE->m_vmObjectHandle = VMPTR_OBJECTHANDLE::MakePtr(oh); break; |