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//
20void 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
82void 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)
113void 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