| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | //***************************************************************************** |
| 5 | // File: primitives.cpp |
| 6 | // |
| 7 | |
| 8 | // |
| 9 | // Platform-specific debugger primitives |
| 10 | // |
| 11 | //***************************************************************************** |
| 12 | |
| 13 | #include "primitives.h" |
| 14 | |
| 15 | |
| 16 | // |
| 17 | // CopyThreadContext() does an intelligent copy from pSrc to pDst, |
| 18 | // respecting the ContextFlags of both contexts. |
| 19 | // |
| 20 | void CORDbgCopyThreadContext(DT_CONTEXT* pDst, const DT_CONTEXT* pSrc) |
| 21 | { |
| 22 | ULONG dstFlags = pDst->ContextFlags; |
| 23 | ULONG srcFlags = pSrc->ContextFlags; |
| 24 | LOG((LF_CORDB, LL_INFO1000000, |
| 25 | "CP::CTC: pDst=0x%p dstFlags=0x%x, pSrc=0x%px srcFlags=0x%x\n" , |
| 26 | pDst, dstFlags, pSrc, srcFlags)); |
| 27 | |
| 28 | // Unlike on X86 the AMD64 CONTEXT struct isn't nicely defined |
| 29 | // to facilitate copying sections based on the CONTEXT flags. |
| 30 | if ((dstFlags & srcFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) |
| 31 | { |
| 32 | // SegCs |
| 33 | CopyContextChunk(&(pDst->SegCs), &(pSrc->SegCs), &(pDst->SegDs), |
| 34 | CONTEXT_CONTROL); |
| 35 | // SegSs, EFlags |
| 36 | CopyContextChunk(&(pDst->SegSs), &(pSrc->SegSs), &(pDst->Dr0), |
| 37 | CONTEXT_CONTROL); |
| 38 | // Rsp |
| 39 | CopyContextChunk(&(pDst->Rsp), &(pSrc->Rsp), &(pDst->Rbp), |
| 40 | CONTEXT_CONTROL); |
| 41 | // Rip |
| 42 | CopyContextChunk(&(pDst->Rip), &(pSrc->Rip), &(pDst->Xmm0), |
| 43 | CONTEXT_CONTROL); |
| 44 | } |
| 45 | |
| 46 | if ((dstFlags & srcFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) |
| 47 | { |
| 48 | // Rax, Rcx, Rdx, Rbx |
| 49 | CopyContextChunk(&(pDst->Rax), &(pSrc->Rax), &(pDst->Rsp), |
| 50 | CONTEXT_INTEGER); |
| 51 | // Rbp, Rsi, Rdi, R8-R15 |
| 52 | CopyContextChunk(&(pDst->Rbp), &(pSrc->Rbp), &(pDst->Rip), |
| 53 | CONTEXT_INTEGET); |
| 54 | } |
| 55 | |
| 56 | if ((dstFlags & srcFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) |
| 57 | { |
| 58 | // SegDs, SegEs, SegFs, SegGs |
| 59 | CopyContextChunk(&(pDst->SegDs), &(pSrc->SegDs), &(pDst->SegSs), |
| 60 | CONTEXT_SEGMENTS); |
| 61 | } |
| 62 | |
| 63 | if ((dstFlags & srcFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) |
| 64 | { |
| 65 | // Xmm0-Xmm15 |
| 66 | CopyContextChunk(&(pDst->Xmm0), &(pSrc->Xmm0), &(pDst->Xmm15) + 1, |
| 67 | CONTEXT_FLOATING_POINT); |
| 68 | |
| 69 | // MxCsr |
| 70 | CopyContextChunk(&(pDst->MxCsr), &(pSrc->MxCsr), &(pDst->SegCs), |
| 71 | CONTEXT_FLOATING_POINT); |
| 72 | } |
| 73 | |
| 74 | if ((dstFlags & srcFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) |
| 75 | { |
| 76 | // Dr0-Dr3, Dr6-Dr7 |
| 77 | CopyContextChunk(&(pDst->Dr0), &(pSrc->Dr0), &(pDst->Rax), |
| 78 | CONTEXT_DEBUG_REGISTERS); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | void CORDbgSetDebuggerREGDISPLAYFromContext(DebuggerREGDISPLAY* pDRD, |
| 83 | DT_CONTEXT* pContext) |
| 84 | { |
| 85 | DWORD flags = pContext->ContextFlags; |
| 86 | if ((flags & DT_CONTEXT_CONTROL) == DT_CONTEXT_CONTROL) |
| 87 | { |
| 88 | pDRD->PC = (SIZE_T)CORDbgGetIP(pContext); |
| 89 | pDRD->SP = (SIZE_T)CORDbgGetSP(pContext); |
| 90 | } |
| 91 | |
| 92 | if ((flags & DT_CONTEXT_INTEGER) == DT_CONTEXT_INTEGER) |
| 93 | { |
| 94 | pDRD->Rax = pContext->Rax; |
| 95 | pDRD->Rcx = pContext->Rcx; |
| 96 | pDRD->Rdx = pContext->Rdx; |
| 97 | pDRD->Rbx = pContext->Rbx; |
| 98 | pDRD->Rbp = pContext->Rbp; |
| 99 | pDRD->Rsi = pContext->Rsi; |
| 100 | pDRD->Rdi = pContext->Rdi; |
| 101 | pDRD->R8 = pContext->R8; |
| 102 | pDRD->R9 = pContext->R9; |
| 103 | pDRD->R10 = pContext->R10; |
| 104 | pDRD->R11 = pContext->R11; |
| 105 | pDRD->R12 = pContext->R12; |
| 106 | pDRD->R13 = pContext->R13; |
| 107 | pDRD->R14 = pContext->R14; |
| 108 | pDRD->R15 = pContext->R15; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | #if defined(ALLOW_VMPTR_ACCESS) || !defined(RIGHT_SIDE_COMPILE) |
| 113 | void SetDebuggerREGDISPLAYFromREGDISPLAY(DebuggerREGDISPLAY* pDRD, REGDISPLAY* pRD) |
| 114 | { |
| 115 | SUPPORTS_DAC_HOST_ONLY; |
| 116 | // CORDbgSetDebuggerREGDISPLAYFromContext() checks the context flags. In cases where we don't have a filter |
| 117 | // context from the thread, we initialize a CONTEXT on the stack and use that to do our stack walking. We never |
| 118 | // initialize the context flags in such cases. Since this function is called from the stackwalker, we can |
| 119 | // guarantee that the integer, control, and floating point sections are valid. So we set the flags here and |
| 120 | // restore them afterwards. |
| 121 | DWORD contextFlags = pRD->pCurrentContext->ContextFlags; |
| 122 | pRD->pCurrentContext->ContextFlags = CONTEXT_FULL; |
| 123 | // This doesn't set the pointers, only the values |
| 124 | CORDbgSetDebuggerREGDISPLAYFromContext(pDRD, reinterpret_cast<DT_CONTEXT *>(pRD->pCurrentContext)); // MACTODO: KLUDGE UNDO Microsoft |
| 125 | pRD->pCurrentContext->ContextFlags = contextFlags; |
| 126 | |
| 127 | // These pointers are always valid so we don't need to test them using PushedRegAddr |
| 128 | #if defined(USE_REMOTE_REGISTER_ADDRESS) |
| 129 | pDRD->pRax = pRD->pCurrentContextPointers->Integer.Register.Rax; |
| 130 | pDRD->pRcx = pRD->pCurrentContextPointers->Integer.Register.Rcx; |
| 131 | pDRD->pRdx = pRD->pCurrentContextPointers->Integer.Register.Rdx; |
| 132 | pDRD->pRbx = pRD->pCurrentContextPointers->Integer.Register.Rbx; |
| 133 | pDRD->pRbp = pRD->pCurrentContextPointers->Integer.Register.Rbp; |
| 134 | pDRD->pRsi = pRD->pCurrentContextPointers->Integer.Register.Rsi; |
| 135 | pDRD->pRdi = pRD->pCurrentContextPointers->Integer.Register.Rdi; |
| 136 | pDRD->pR8 = pRD->pCurrentContextPointers->Integer.Register.R8; |
| 137 | pDRD->pR9 = pRD->pCurrentContextPointers->Integer.Register.R9; |
| 138 | pDRD->pR10 = pRD->pCurrentContextPointers->Integer.Register.R10; |
| 139 | pDRD->pR11 = pRD->pCurrentContextPointers->Integer.Register.R11; |
| 140 | pDRD->pR12 = pRD->pCurrentContextPointers->Integer.Register.R12; |
| 141 | pDRD->pR13 = pRD->pCurrentContextPointers->Integer.Register.R13; |
| 142 | pDRD->pR14 = pRD->pCurrentContextPointers->Integer.Register.R14; |
| 143 | pDRD->pR15 = pRD->pCurrentContextPointers->Integer.Register.R15; |
| 144 | #else // !USE_REMOTE_REGISTER_ADDRESS |
| 145 | pDRD->pRax = NULL; |
| 146 | pDRD->pRcx = NULL; |
| 147 | pDRD->pRdx = NULL; |
| 148 | pDRD->pRbx = NULL; |
| 149 | pDRD->pRbp = NULL; |
| 150 | pDRD->pRsi = NULL; |
| 151 | pDRD->pRdi = NULL; |
| 152 | pDRD->pR8 = NULL; |
| 153 | pDRD->pR9 = NULL; |
| 154 | pDRD->pR10 = NULL; |
| 155 | pDRD->pR11 = NULL; |
| 156 | pDRD->pR12 = NULL; |
| 157 | pDRD->pR13 = NULL; |
| 158 | pDRD->pR14 = NULL; |
| 159 | pDRD->pR15 = NULL; |
| 160 | #endif // USE_REMOTE_REGISTER_ADDRESS |
| 161 | |
| 162 | pDRD->PC = pRD->ControlPC; |
| 163 | pDRD->SP = pRD->SP; |
| 164 | |
| 165 | // Please leave RSP, RIP at the front so I don't have to scroll |
| 166 | // left to see the most important registers. Thanks! |
| 167 | LOG( (LF_CORDB, LL_INFO1000, "SDRFR:Registers:" |
| 168 | "Rsp = %p Rip = %p Rbp = %p Rdi = %p " |
| 169 | "Rsi = %p Rbx = %p Rdx = %p Rcx = %p Rax = %p" |
| 170 | "R8 = %p R9 = %p R10 = %p R11 = %p" |
| 171 | "R12 = %p R13 = %p R14 = %p R15 = %p\n" , |
| 172 | pDRD->SP, pDRD->PC, pDRD->Rbp, pDRD->Rdi, |
| 173 | pDRD->Rsi, pDRD->Rbx, pDRD->Rdx, pDRD->Rcx, pDRD->Rax, |
| 174 | pDRD->R8, pDRD->R9, pDRD->R10, pDRD->R11, pDRD->R12, |
| 175 | pDRD->R13, pDRD->R14, pDRD->R15) ); |
| 176 | |
| 177 | } |
| 178 | #endif // ALLOW_VMPTR_ACCESS || !RIGHT_SIDE_COMPILE |
| 179 | |