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 | |