diff options
Diffstat (limited to 'src/debug/shared/amd64/primitives.cpp')
-rw-r--r-- | src/debug/shared/amd64/primitives.cpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/debug/shared/amd64/primitives.cpp b/src/debug/shared/amd64/primitives.cpp new file mode 100644 index 0000000000..fb5d95b0d6 --- /dev/null +++ b/src/debug/shared/amd64/primitives.cpp @@ -0,0 +1,178 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// File: primitives.cpp +// + +// +// Platform-specific debugger primitives +// +//***************************************************************************** + +#include "primitives.h" + + +// +// CopyThreadContext() does an intelligent copy from pSrc to pDst, +// respecting the ContextFlags of both contexts. +// +void CORDbgCopyThreadContext(DT_CONTEXT* pDst, const DT_CONTEXT* pSrc) +{ + ULONG dstFlags = pDst->ContextFlags; + ULONG srcFlags = pSrc->ContextFlags; + LOG((LF_CORDB, LL_INFO1000000, + "CP::CTC: pDst=0x%p dstFlags=0x%x, pSrc=0x%px srcFlags=0x%x\n", + pDst, dstFlags, pSrc, srcFlags)); + + // Unlike on X86 the AMD64 CONTEXT struct isn't nicely defined + // to facilitate copying sections based on the CONTEXT flags. + if ((dstFlags & srcFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) + { + // SegCs + CopyContextChunk(&(pDst->SegCs), &(pSrc->SegCs), &(pDst->SegDs), + CONTEXT_CONTROL); + // SegSs, EFlags + CopyContextChunk(&(pDst->SegSs), &(pSrc->SegSs), &(pDst->Dr0), + CONTEXT_CONTROL); + // Rsp + CopyContextChunk(&(pDst->Rsp), &(pSrc->Rsp), &(pDst->Rbp), + CONTEXT_CONTROL); + // Rip + CopyContextChunk(&(pDst->Rip), &(pSrc->Rip), &(pDst->Xmm0), + CONTEXT_CONTROL); + } + + if ((dstFlags & srcFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) + { + // Rax, Rcx, Rdx, Rbx + CopyContextChunk(&(pDst->Rax), &(pSrc->Rax), &(pDst->Rsp), + CONTEXT_INTEGER); + // Rbp, Rsi, Rdi, R8-R15 + CopyContextChunk(&(pDst->Rbp), &(pSrc->Rbp), &(pDst->Rip), + CONTEXT_INTEGET); + } + + if ((dstFlags & srcFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) + { + // SegDs, SegEs, SegFs, SegGs + CopyContextChunk(&(pDst->SegDs), &(pSrc->SegDs), &(pDst->SegSs), + CONTEXT_SEGMENTS); + } + + if ((dstFlags & srcFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) + { + // Xmm0-Xmm15 + CopyContextChunk(&(pDst->Xmm0), &(pSrc->Xmm0), &(pDst->Xmm15) + sizeof(M128A), + CONTEXT_FLOATING_POINT); + + // MxCsr + CopyContextChunk(&(pDst->MxCsr), &(pSrc->MxCsr), &(pDst->SegCs), + CONTEXT_FLOATING_POINT); + } + + if ((dstFlags & srcFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) + { + // Dr0-Dr3, Dr6-Dr7 + CopyContextChunk(&(pDst->Dr0), &(pSrc->Dr0), &(pDst->Rax), + CONTEXT_DEBUG_REGISTERS); + } +} + +void CORDbgSetDebuggerREGDISPLAYFromContext(DebuggerREGDISPLAY* pDRD, + DT_CONTEXT* pContext) +{ + DWORD flags = pContext->ContextFlags; + if ((flags & DT_CONTEXT_CONTROL) == DT_CONTEXT_CONTROL) + { + pDRD->PC = (SIZE_T)CORDbgGetIP(pContext); + pDRD->SP = (SIZE_T)CORDbgGetSP(pContext); + } + + if ((flags & DT_CONTEXT_INTEGER) == DT_CONTEXT_INTEGER) + { + pDRD->Rax = pContext->Rax; + pDRD->Rcx = pContext->Rcx; + pDRD->Rdx = pContext->Rdx; + pDRD->Rbx = pContext->Rbx; + pDRD->Rbp = pContext->Rbp; + pDRD->Rsi = pContext->Rsi; + pDRD->Rdi = pContext->Rdi; + pDRD->R8 = pContext->R8; + pDRD->R9 = pContext->R9; + pDRD->R10 = pContext->R10; + pDRD->R11 = pContext->R11; + pDRD->R12 = pContext->R12; + pDRD->R13 = pContext->R13; + pDRD->R14 = pContext->R14; + pDRD->R15 = pContext->R15; + } +} + +#if defined(ALLOW_VMPTR_ACCESS) || !defined(RIGHT_SIDE_COMPILE) +void SetDebuggerREGDISPLAYFromREGDISPLAY(DebuggerREGDISPLAY* pDRD, REGDISPLAY* pRD) +{ + SUPPORTS_DAC_HOST_ONLY; + // CORDbgSetDebuggerREGDISPLAYFromContext() checks the context flags. In cases where we don't have a filter + // context from the thread, we initialize a CONTEXT on the stack and use that to do our stack walking. We never + // initialize the context flags in such cases. Since this function is called from the stackwalker, we can + // guarantee that the integer, control, and floating point sections are valid. So we set the flags here and + // restore them afterwards. + DWORD contextFlags = pRD->pCurrentContext->ContextFlags; + pRD->pCurrentContext->ContextFlags = CONTEXT_FULL; + // This doesn't set the pointers, only the values + CORDbgSetDebuggerREGDISPLAYFromContext(pDRD, reinterpret_cast<DT_CONTEXT *>(pRD->pCurrentContext)); // MACTODO: KLUDGE UNDO Microsoft + pRD->pCurrentContext->ContextFlags = contextFlags; + + // These pointers are always valid so we don't need to test them using PushedRegAddr +#if defined(USE_REMOTE_REGISTER_ADDRESS) + pDRD->pRax = pRD->pCurrentContextPointers->Integer.Register.Rax; + pDRD->pRcx = pRD->pCurrentContextPointers->Integer.Register.Rcx; + pDRD->pRdx = pRD->pCurrentContextPointers->Integer.Register.Rdx; + pDRD->pRbx = pRD->pCurrentContextPointers->Integer.Register.Rbx; + pDRD->pRbp = pRD->pCurrentContextPointers->Integer.Register.Rbp; + pDRD->pRsi = pRD->pCurrentContextPointers->Integer.Register.Rsi; + pDRD->pRdi = pRD->pCurrentContextPointers->Integer.Register.Rdi; + pDRD->pR8 = pRD->pCurrentContextPointers->Integer.Register.R8; + pDRD->pR9 = pRD->pCurrentContextPointers->Integer.Register.R9; + pDRD->pR10 = pRD->pCurrentContextPointers->Integer.Register.R10; + pDRD->pR11 = pRD->pCurrentContextPointers->Integer.Register.R11; + pDRD->pR12 = pRD->pCurrentContextPointers->Integer.Register.R12; + pDRD->pR13 = pRD->pCurrentContextPointers->Integer.Register.R13; + pDRD->pR14 = pRD->pCurrentContextPointers->Integer.Register.R14; + pDRD->pR15 = pRD->pCurrentContextPointers->Integer.Register.R15; +#else // !USE_REMOTE_REGISTER_ADDRESS + pDRD->pRax = NULL; + pDRD->pRcx = NULL; + pDRD->pRdx = NULL; + pDRD->pRbx = NULL; + pDRD->pRbp = NULL; + pDRD->pRsi = NULL; + pDRD->pRdi = NULL; + pDRD->pR8 = NULL; + pDRD->pR9 = NULL; + pDRD->pR10 = NULL; + pDRD->pR11 = NULL; + pDRD->pR12 = NULL; + pDRD->pR13 = NULL; + pDRD->pR14 = NULL; + pDRD->pR15 = NULL; +#endif // USE_REMOTE_REGISTER_ADDRESS + + pDRD->PC = pRD->ControlPC; + pDRD->SP = pRD->SP; + + // Please leave RSP, RIP at the front so I don't have to scroll + // left to see the most important registers. Thanks! + LOG( (LF_CORDB, LL_INFO1000, "SDRFR:Registers:" + "Rsp = %p Rip = %p Rbp = %p Rdi = %p " + "Rsi = %p Rbx = %p Rdx = %p Rcx = %p Rax = %p" + "R8 = %p R9 = %p R10 = %p R11 = %p" + "R12 = %p R13 = %p R14 = %p R15 = %p\n", + pDRD->SP, pDRD->PC, pDRD->Rbp, pDRD->Rdi, + pDRD->Rsi, pDRD->Rbx, pDRD->Rdx, pDRD->Rcx, pDRD->Rax, + pDRD->R8, pDRD->R9, pDRD->R10, pDRD->R11, pDRD->R12, + pDRD->R13, pDRD->R14, pDRD->R15) ); + +} +#endif // ALLOW_VMPTR_ACCESS || !RIGHT_SIDE_COMPILE |