From 28d687a3618feb16525218550ca57fb5076d2116 Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Tue, 16 Jul 2019 10:06:52 -0400 Subject: [PATCH] Add missing Arm64 specific diagnostic code (dotnet/coreclr#25695) * Arm64 ICorDebugRegisterSet float support * Arm64 ICorDebugRegisterSet2 implementation * Add arm64 VLT_REG_FP case * Arm64 add funceval GetRegister SetRegister support Commit migrated from https://github.com/dotnet/coreclr/commit/f5b1b889a0480eecf7068db4a17e8dd35a7ed878 --- .../src/debug/di/arm64/cordbregisterset.cpp | 138 +++++++++++++++++-- src/coreclr/src/debug/di/rsthread.cpp | 8 +- src/coreclr/src/debug/ee/funceval.cpp | 152 ++++++++++++++++++++- src/coreclr/src/vm/arm64/cgencpu.h | 15 ++ 4 files changed, 301 insertions(+), 12 deletions(-) diff --git a/src/coreclr/src/debug/di/arm64/cordbregisterset.cpp b/src/coreclr/src/debug/di/arm64/cordbregisterset.cpp index eab5ba4..7921bcf 100644 --- a/src/coreclr/src/debug/di/arm64/cordbregisterset.cpp +++ b/src/coreclr/src/debug/di/arm64/cordbregisterset.cpp @@ -47,7 +47,38 @@ HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG64* pAvailable) | SETBITULONG64(REGISTER_ARM64_X27) | SETBITULONG64(REGISTER_ARM64_X28) | SETBITULONG64(REGISTER_ARM64_FP) - | SETBITULONG64(REGISTER_ARM64_LR); + | SETBITULONG64(REGISTER_ARM64_LR) + | SETBITULONG64(REGISTER_ARM64_V0) + | SETBITULONG64(REGISTER_ARM64_V1) + | SETBITULONG64(REGISTER_ARM64_V2) + | SETBITULONG64(REGISTER_ARM64_V3) + | SETBITULONG64(REGISTER_ARM64_V4) + | SETBITULONG64(REGISTER_ARM64_V5) + | SETBITULONG64(REGISTER_ARM64_V6) + | SETBITULONG64(REGISTER_ARM64_V7) + | SETBITULONG64(REGISTER_ARM64_V8) + | SETBITULONG64(REGISTER_ARM64_V9) + | SETBITULONG64(REGISTER_ARM64_V10) + | SETBITULONG64(REGISTER_ARM64_V11) + | SETBITULONG64(REGISTER_ARM64_V12) + | SETBITULONG64(REGISTER_ARM64_V13) + | SETBITULONG64(REGISTER_ARM64_V14) + | SETBITULONG64(REGISTER_ARM64_V15) + | SETBITULONG64(REGISTER_ARM64_V16) + | SETBITULONG64(REGISTER_ARM64_V17) + | SETBITULONG64(REGISTER_ARM64_V18) + | SETBITULONG64(REGISTER_ARM64_V19) + | SETBITULONG64(REGISTER_ARM64_V20) + | SETBITULONG64(REGISTER_ARM64_V21) + | SETBITULONG64(REGISTER_ARM64_V22) + | SETBITULONG64(REGISTER_ARM64_V23) + | SETBITULONG64(REGISTER_ARM64_V24) + | SETBITULONG64(REGISTER_ARM64_V25) + | SETBITULONG64(REGISTER_ARM64_V26) + | SETBITULONG64(REGISTER_ARM64_V27) + | SETBITULONG64(REGISTER_ARM64_V28) + | SETBITULONG64(REGISTER_ARM64_V29) + | SETBITULONG64(REGISTER_ARM64_V30); return S_OK; } @@ -63,20 +94,43 @@ HRESULT CordbRegisterSet::GetRegisters(ULONG64 mask, ULONG32 regCount, VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER, regCount, true, true); - // @ARM64TODO: floating point support - for (int i = REGISTER_ARM64_PC; - i <= REGISTER_ARM64_LR && iRegister < regCount; + i <= REGISTER_ARM64_V30 && iRegister < regCount; i++) { if (mask & SETBITULONG64(i)) { + _ASSERTE (iRegister < regCount); + if ((i >= REGISTER_ARM64_X0) && (i <= REGISTER_ARM64_X28)) { regBuffer[iRegister++] = m_rd->X[i - REGISTER_ARM64_X0]; continue; } + if ((i >= REGISTER_ARM64_V0) && (i <= REGISTER_ARM64_V30)) + { + if (!m_thread->m_fFloatStateValid) + { + HRESULT hr = S_OK; + EX_TRY + { + m_thread->LoadFloatState(); + } + EX_CATCH_HRESULT(hr); + + if ( !SUCCEEDED(hr) ) + { + return hr; + } + LOG( ( LF_CORDB, LL_INFO1000, "CRS::GR: Loaded float state\n" ) ); + } + + regBuffer[iRegister++] = *(CORDB_REGISTER*) + &(m_thread->m_floatValues[(i - REGISTER_ARM64_V0)]); + continue; + } + switch (i) { case REGISTER_ARM64_PC: @@ -104,8 +158,19 @@ HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG32 regCount, FAIL_IF_NEUTERED(this); VALIDATE_POINTER_TO_OBJECT_ARRAY(pAvailable, CORDB_REGISTER, regCount, true, true); - // Defer to adapter for v1.0 interface - return GetRegistersAvailableAdapter(regCount, pAvailable); + for (int i = 0 ; i < (int)regCount ; ++i) + { + if (i * 8 <= REGISTER_ARM64_V31) + { + pAvailable[i] = (i * 8 == REGISTER_ARM64_V31) ? BYTE(0x1) : BYTE(0xff); + } + else + { + pAvailable[i] = 0; + } + } + + return S_OK; } @@ -115,8 +180,65 @@ HRESULT CordbRegisterSet::GetRegisters(ULONG32 maskCount, BYTE mask[], FAIL_IF_NEUTERED(this); VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER, regCount, true, true); - // Defer to adapter for v1.0 interface - return GetRegistersAdapter(maskCount, mask, regCount, regBuffer); + UINT iRegister = 0; + + for (int m = 0 ; m < (int)maskCount ; ++m) + { + for (int bit = 0 ; bit < 8 ; ++bit) + { + if (mask[m] & SETBITULONG64(bit)) + { + _ASSERTE (iRegister < regCount); + + int i = m * 8 + bit; + + if ((i >= REGISTER_ARM64_X0) && (i <= REGISTER_ARM64_X28)) + { + regBuffer[iRegister++] = m_rd->X[i - REGISTER_ARM64_X0]; + continue; + } + + if ((i >= REGISTER_ARM64_V0) && (i <= REGISTER_ARM64_V31)) + { + if (!m_thread->m_fFloatStateValid) + { + HRESULT hr = S_OK; + EX_TRY + { + m_thread->LoadFloatState(); + } + EX_CATCH_HRESULT(hr); + + if ( !SUCCEEDED(hr) ) + { + return hr; + } + LOG( ( LF_CORDB, LL_INFO1000, "CRS::GR: Loaded float state\n" ) ); + } + + regBuffer[iRegister++] = *(CORDB_REGISTER*) + &(m_thread->m_floatValues[(i - REGISTER_ARM64_V0)]); + continue; + } + + switch (i) + { + case REGISTER_ARM64_PC: + regBuffer[iRegister++] = m_rd->PC; break; + case REGISTER_ARM64_SP: + regBuffer[iRegister++] = m_rd->SP; break; + case REGISTER_ARM64_FP: + regBuffer[iRegister++] = m_rd->FP; break; + case REGISTER_ARM64_LR: + regBuffer[iRegister++] = m_rd->LR; break; + default: + _ASSERTE(false); break; + } + } + } + } + + return S_OK; } diff --git a/src/coreclr/src/debug/di/rsthread.cpp b/src/coreclr/src/debug/di/rsthread.cpp index a9113a4..6ddaaf8 100644 --- a/src/coreclr/src/debug/di/rsthread.cpp +++ b/src/coreclr/src/debug/di/rsthread.cpp @@ -8386,10 +8386,14 @@ HRESULT CordbJITILFrame::GetNativeVariable(CordbType *type, case ICorDebugInfo::VLT_REG_FP: #if defined(DBG_TARGET_ARM) // @ARMTODO hr = E_NOTIMPL; -#else // DBG_TARGET_ARM @ARMTODO +#elif defined(DBG_TARGET_AMD64) hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_AMD64_XMM0, type, ppValue); - +#elif defined(DBG_TARGET_ARM64) + hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_ARM64_V0, + type, ppValue); +#else +#error Platform not implemented #endif // DBG_TARGET_ARM @ARMTODO break; #endif // DBG_TARGET_WIN64 || DBG_TARGET_ARM diff --git a/src/coreclr/src/debug/ee/funceval.cpp b/src/coreclr/src/debug/ee/funceval.cpp index 8c6ed88..47f5a28 100644 --- a/src/coreclr/src/debug/ee/funceval.cpp +++ b/src/coreclr/src/debug/ee/funceval.cpp @@ -388,7 +388,81 @@ static SIZE_T GetRegisterValue(DebuggerEval *pDE, CorDebugRegister reg, void *re ret = FPSpillToR8(&(pDE->m_context.Xmm0) + (reg - REGISTER_AMD64_XMM0)); break; -#endif // !_TARGET_X86_ && !_TARGET_AMD64_ +#elif defined(_TARGET_ARM64_) + // fall through + case REGISTER_ARM64_X0: + case REGISTER_ARM64_X1: + case REGISTER_ARM64_X2: + case REGISTER_ARM64_X3: + case REGISTER_ARM64_X4: + case REGISTER_ARM64_X5: + case REGISTER_ARM64_X6: + case REGISTER_ARM64_X7: + case REGISTER_ARM64_X8: + case REGISTER_ARM64_X9: + case REGISTER_ARM64_X10: + case REGISTER_ARM64_X11: + case REGISTER_ARM64_X12: + case REGISTER_ARM64_X13: + case REGISTER_ARM64_X14: + case REGISTER_ARM64_X15: + case REGISTER_ARM64_X16: + case REGISTER_ARM64_X17: + case REGISTER_ARM64_X18: + case REGISTER_ARM64_X19: + case REGISTER_ARM64_X20: + case REGISTER_ARM64_X21: + case REGISTER_ARM64_X22: + case REGISTER_ARM64_X23: + case REGISTER_ARM64_X24: + case REGISTER_ARM64_X25: + case REGISTER_ARM64_X26: + case REGISTER_ARM64_X27: + case REGISTER_ARM64_X28: + ret = pDE->m_context.X[reg - REGISTER_ARM64_X0]; + break; + + case REGISTER_ARM64_LR: + ret = pDE->m_context.Lr; + break; + + + case REGISTER_ARM64_V0: + case REGISTER_ARM64_V1: + case REGISTER_ARM64_V2: + case REGISTER_ARM64_V3: + case REGISTER_ARM64_V4: + case REGISTER_ARM64_V5: + case REGISTER_ARM64_V6: + case REGISTER_ARM64_V7: + case REGISTER_ARM64_V8: + case REGISTER_ARM64_V9: + case REGISTER_ARM64_V10: + case REGISTER_ARM64_V11: + case REGISTER_ARM64_V12: + case REGISTER_ARM64_V13: + case REGISTER_ARM64_V14: + case REGISTER_ARM64_V15: + case REGISTER_ARM64_V16: + case REGISTER_ARM64_V17: + case REGISTER_ARM64_V18: + case REGISTER_ARM64_V19: + case REGISTER_ARM64_V20: + case REGISTER_ARM64_V21: + case REGISTER_ARM64_V22: + case REGISTER_ARM64_V23: + case REGISTER_ARM64_V24: + case REGISTER_ARM64_V25: + case REGISTER_ARM64_V26: + case REGISTER_ARM64_V27: + case REGISTER_ARM64_V28: + case REGISTER_ARM64_V29: + case REGISTER_ARM64_V30: + case REGISTER_ARM64_V31: + ret = FPSpillToR8(&pDE->m_context.V[reg - REGISTER_ARM64_V0]); + break; + +#endif // !_TARGET_X86_ && !_TARGET_AMD64_ && !_TARGET_ARM64_ default: _ASSERT(!"Invalid register number!"); @@ -530,7 +604,81 @@ static void SetRegisterValue(DebuggerEval *pDE, CorDebugRegister reg, void *regA R8ToFPSpill(&(pDE->m_context.Xmm0) + (reg - REGISTER_AMD64_XMM0), newValue); break; -#endif // !_TARGET_X86_ && !_TARGET_AMD64_ +#elif defined(_TARGET_ARM64_) + // fall through + case REGISTER_ARM64_X0: + case REGISTER_ARM64_X1: + case REGISTER_ARM64_X2: + case REGISTER_ARM64_X3: + case REGISTER_ARM64_X4: + case REGISTER_ARM64_X5: + case REGISTER_ARM64_X6: + case REGISTER_ARM64_X7: + case REGISTER_ARM64_X8: + case REGISTER_ARM64_X9: + case REGISTER_ARM64_X10: + case REGISTER_ARM64_X11: + case REGISTER_ARM64_X12: + case REGISTER_ARM64_X13: + case REGISTER_ARM64_X14: + case REGISTER_ARM64_X15: + case REGISTER_ARM64_X16: + case REGISTER_ARM64_X17: + case REGISTER_ARM64_X18: + case REGISTER_ARM64_X19: + case REGISTER_ARM64_X20: + case REGISTER_ARM64_X21: + case REGISTER_ARM64_X22: + case REGISTER_ARM64_X23: + case REGISTER_ARM64_X24: + case REGISTER_ARM64_X25: + case REGISTER_ARM64_X26: + case REGISTER_ARM64_X27: + case REGISTER_ARM64_X28: + pDE->m_context.X[reg - REGISTER_ARM64_X0] = newValue; + break; + + case REGISTER_ARM64_LR: + pDE->m_context.Lr = newValue; + break; + + + case REGISTER_ARM64_V0: + case REGISTER_ARM64_V1: + case REGISTER_ARM64_V2: + case REGISTER_ARM64_V3: + case REGISTER_ARM64_V4: + case REGISTER_ARM64_V5: + case REGISTER_ARM64_V6: + case REGISTER_ARM64_V7: + case REGISTER_ARM64_V8: + case REGISTER_ARM64_V9: + case REGISTER_ARM64_V10: + case REGISTER_ARM64_V11: + case REGISTER_ARM64_V12: + case REGISTER_ARM64_V13: + case REGISTER_ARM64_V14: + case REGISTER_ARM64_V15: + case REGISTER_ARM64_V16: + case REGISTER_ARM64_V17: + case REGISTER_ARM64_V18: + case REGISTER_ARM64_V19: + case REGISTER_ARM64_V20: + case REGISTER_ARM64_V21: + case REGISTER_ARM64_V22: + case REGISTER_ARM64_V23: + case REGISTER_ARM64_V24: + case REGISTER_ARM64_V25: + case REGISTER_ARM64_V26: + case REGISTER_ARM64_V27: + case REGISTER_ARM64_V28: + case REGISTER_ARM64_V29: + case REGISTER_ARM64_V30: + case REGISTER_ARM64_V31: + R8ToFPSpill(&pDE->m_context.V[reg - REGISTER_ARM64_V0], newValue); + break; + +#endif // !_TARGET_X86_ && !_TARGET_AMD64_ && !_TARGET_ARM64_ default: _ASSERT(!"Invalid register number!"); diff --git a/src/coreclr/src/vm/arm64/cgencpu.h b/src/coreclr/src/vm/arm64/cgencpu.h index 997ad7d..9a5fc84 100644 --- a/src/coreclr/src/vm/arm64/cgencpu.h +++ b/src/coreclr/src/vm/arm64/cgencpu.h @@ -71,6 +71,21 @@ extern PCODE GetPreStubEntryPoint(); //======================================================================= #define MAXFIELDMARSHALERSIZE 40 +inline +ARG_SLOT FPSpillToR8(void* pSpillSlot) +{ + LIMITED_METHOD_CONTRACT; + return *(SIZE_T*)pSpillSlot; +} + +inline +void R8ToFPSpill(void* pSpillSlot, SIZE_T srcDoubleAsSIZE_T) +{ + LIMITED_METHOD_CONTRACT; + *(SIZE_T*)pSpillSlot = srcDoubleAsSIZE_T; + *((SIZE_T*)pSpillSlot + 1) = 0; +} + //********************************************************************** // Parameter size //********************************************************************** -- 2.7.4