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#ifndef __DBG_TARGET_CONTEXT_INCLUDED
6#define __DBG_TARGET_CONTEXT_INCLUDED
7
8#include <dbgportable.h>
9#include <stddef.h>
10#include "crosscomp.h"
11
12//
13// The right side of the debugger can be built to target multiple platforms. This means it is not
14// safe to use the CONTEXT structure directly: the context of the platform we're building for might not match
15// that of the one the debugger is targetting. So all right side code will use the DT_CONTEXT abstraction
16// instead. When the debugger target is the local platform this will just resolve back into CONTEXT, but cross
17// platform we'll provide a hand-rolled version.
18//
19
20//
21// For cross platform cases we also need to provide a helper function for byte-swapping a context structure
22// should the endian-ness of the debugger and debuggee platforms differ. This is called ByteSwapContext and is
23// obviously a no-op for those cases where the left and right sides agree on storage format.
24//
25// NOTE: Any changes to the field layout of DT_CONTEXT must be tracked in the associated definition of
26// ByteSwapContext.
27//
28
29//
30// **** NOTE: Keep these in sync with pal/inc/pal.h ****
31//
32
33// This odd define pattern is needed because in DBI we set _TARGET_ to match the host and
34// DBG_TARGET to control our targeting. In x-plat DBI DBG_TARGET won't match _TARGET_ and
35// DBG_TARGET needs to take precedence
36#if defined(DBG_TARGET_X86)
37#define DTCONTEXT_IS_X86
38#elif defined (DBG_TARGET_AMD64)
39#define DTCONTEXT_IS_AMD64
40#elif defined (DBG_TARGET_ARM)
41#define DTCONTEXT_IS_ARM
42#elif defined (DBG_TARGET_ARM64)
43#define DTCONTEXT_IS_ARM64
44#elif defined (_TARGET_X86_)
45#define DTCONTEXT_IS_X86
46#elif defined (_TARGET_AMD64_)
47#define DTCONTEXT_IS_AMD64
48#elif defined (_TARGET_ARM_)
49#define DTCONTEXT_IS_ARM
50#elif defined (_TARGET_ARM64_)
51#define DTCONTEXT_IS_ARM64
52#endif
53
54#if defined(DTCONTEXT_IS_X86)
55
56#define DT_SIZE_OF_80387_REGISTERS 80
57
58#define DT_CONTEXT_i386 0x00010000
59#define DT_CONTEXT_CONTROL (DT_CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP
60#define DT_CONTEXT_INTEGER (DT_CONTEXT_i386 | 0x00000002L) // AX, BX, CX, DX, SI, DI
61#define DT_CONTEXT_SEGMENTS (DT_CONTEXT_i386 | 0x00000004L)
62#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_i386 | 0x00000008L) // 387 state
63#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_i386 | 0x00000010L)
64
65#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_SEGMENTS)
66#define DT_CONTEXT_EXTENDED_REGISTERS (DT_CONTEXT_i386 | 0x00000020L)
67
68#define DT_MAXIMUM_SUPPORTED_EXTENSION 512
69
70typedef struct {
71 DWORD ControlWord;
72 DWORD StatusWord;
73 DWORD TagWord;
74 DWORD ErrorOffset;
75 DWORD ErrorSelector;
76 DWORD DataOffset;
77 DWORD DataSelector;
78 BYTE RegisterArea[DT_SIZE_OF_80387_REGISTERS];
79 DWORD Cr0NpxState;
80} DT_FLOATING_SAVE_AREA;
81
82typedef struct {
83 ULONG ContextFlags;
84
85 ULONG Dr0;
86 ULONG Dr1;
87 ULONG Dr2;
88 ULONG Dr3;
89 ULONG Dr6;
90 ULONG Dr7;
91
92 DT_FLOATING_SAVE_AREA FloatSave;
93
94 ULONG SegGs;
95 ULONG SegFs;
96 ULONG SegEs;
97 ULONG SegDs;
98
99 ULONG Edi;
100 ULONG Esi;
101 ULONG Ebx;
102 ULONG Edx;
103 ULONG Ecx;
104 ULONG Eax;
105
106 ULONG Ebp;
107 ULONG Eip;
108 ULONG SegCs;
109 ULONG EFlags;
110 ULONG Esp;
111 ULONG SegSs;
112
113 UCHAR ExtendedRegisters[DT_MAXIMUM_SUPPORTED_EXTENSION];
114
115} DT_CONTEXT;
116
117// Since the target is little endian in this case we only have to provide a real implementation of
118// ByteSwapContext if the platform we're building on is big-endian.
119#ifdef BIGENDIAN
120inline void ByteSwapContext(DT_CONTEXT *pContext)
121{
122 // Our job is simplified since the context has large contiguous ranges with fields of the same size. Keep
123 // the following logic in sync with the definition of DT_CONTEXT above.
124 BYTE *pbContext = (BYTE*)pContext;
125
126 // The first span consists of 4 byte fields.
127 DWORD cbFields = (offsetof(DT_CONTEXT, FloatSave) + offsetof(DT_FLOATING_SAVE_AREA, RegisterArea)) / 4;
128 for (DWORD i = 0; i < cbFields; i++)
129 {
130 ByteSwapPrimitive(pbContext, pbContext, 4);
131 pbContext += 4;
132 }
133
134 // Then there's a float save area containing 8 byte fields.
135 cbFields = sizeof(pContext->FloatSave.RegisterArea);
136 for (DWORD i = 0; i < cbFields; i++)
137 {
138 ByteSwapPrimitive(pbContext, pbContext, 8);
139 pbContext += 8;
140 }
141
142 // Back to 4 byte fields.
143 cbFields = (offsetof(DT_CONTEXT, ExtendedRegisters) - offsetof(DT_CONTEXT, SegGs)) / 4;
144 for (DWORD i = 0; i < cbFields; i++)
145 {
146 ByteSwapPrimitive(pbContext, pbContext, 4);
147 pbContext += 4;
148 }
149
150 // We don't know the formatting of the extended register area, but the debugger doesn't access this data
151 // on the left side, so just leave it in left-side format for now.
152
153 // Validate that we converted up to where we think we did as a hedge against DT_CONTEXT layout changes.
154 _PASSERT((pbContext - ((BYTE*)pContext)) == (sizeof(DT_CONTEXT) - sizeof(pContext->ExtendedRegisters)));
155}
156#else // BIGENDIAN
157inline void ByteSwapContext(DT_CONTEXT *pContext)
158{
159}
160#endif // BIGENDIAN
161
162#elif defined(DTCONTEXT_IS_AMD64)
163
164#define DT_CONTEXT_AMD64 0x00100000L
165
166#define DT_CONTEXT_CONTROL (DT_CONTEXT_AMD64 | 0x00000001L)
167#define DT_CONTEXT_INTEGER (DT_CONTEXT_AMD64 | 0x00000002L)
168#define DT_CONTEXT_SEGMENTS (DT_CONTEXT_AMD64 | 0x00000004L)
169#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_AMD64 | 0x00000008L)
170#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_AMD64 | 0x00000010L)
171
172#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
173#define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_SEGMENTS | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
174
175typedef struct {
176 ULONGLONG Low;
177 LONGLONG High;
178} DT_M128A;
179
180typedef struct {
181 WORD ControlWord;
182 WORD StatusWord;
183 BYTE TagWord;
184 BYTE Reserved1;
185 WORD ErrorOpcode;
186 DWORD ErrorOffset;
187 WORD ErrorSelector;
188 WORD Reserved2;
189 DWORD DataOffset;
190 WORD DataSelector;
191 WORD Reserved3;
192 DWORD MxCsr;
193 DWORD MxCsr_Mask;
194 DT_M128A FloatRegisters[8];
195 DT_M128A XmmRegisters[16];
196 BYTE Reserved4[96];
197} DT_XMM_SAVE_AREA32;
198
199typedef struct DECLSPEC_ALIGN(16) {
200
201 DWORD64 P1Home;
202 DWORD64 P2Home;
203 DWORD64 P3Home;
204 DWORD64 P4Home;
205 DWORD64 P5Home;
206 DWORD64 P6Home;
207
208 DWORD ContextFlags;
209 DWORD MxCsr;
210
211 WORD SegCs;
212 WORD SegDs;
213 WORD SegEs;
214 WORD SegFs;
215 WORD SegGs;
216 WORD SegSs;
217 DWORD EFlags;
218
219 DWORD64 Dr0;
220 DWORD64 Dr1;
221 DWORD64 Dr2;
222 DWORD64 Dr3;
223 DWORD64 Dr6;
224 DWORD64 Dr7;
225
226 DWORD64 Rax;
227 DWORD64 Rcx;
228 DWORD64 Rdx;
229 DWORD64 Rbx;
230 DWORD64 Rsp;
231 DWORD64 Rbp;
232 DWORD64 Rsi;
233 DWORD64 Rdi;
234 DWORD64 R8;
235 DWORD64 R9;
236 DWORD64 R10;
237 DWORD64 R11;
238 DWORD64 R12;
239 DWORD64 R13;
240 DWORD64 R14;
241 DWORD64 R15;
242
243 DWORD64 Rip;
244
245 union {
246 DT_XMM_SAVE_AREA32 FltSave;
247 struct {
248 DT_M128A Header[2];
249 DT_M128A Legacy[8];
250 DT_M128A Xmm0;
251 DT_M128A Xmm1;
252 DT_M128A Xmm2;
253 DT_M128A Xmm3;
254 DT_M128A Xmm4;
255 DT_M128A Xmm5;
256 DT_M128A Xmm6;
257 DT_M128A Xmm7;
258 DT_M128A Xmm8;
259 DT_M128A Xmm9;
260 DT_M128A Xmm10;
261 DT_M128A Xmm11;
262 DT_M128A Xmm12;
263 DT_M128A Xmm13;
264 DT_M128A Xmm14;
265 DT_M128A Xmm15;
266 };
267 };
268
269 DT_M128A VectorRegister[26];
270 DWORD64 VectorControl;
271
272 DWORD64 DebugControl;
273 DWORD64 LastBranchToRip;
274 DWORD64 LastBranchFromRip;
275 DWORD64 LastExceptionToRip;
276 DWORD64 LastExceptionFromRip;
277} DT_CONTEXT;
278
279#elif defined(DTCONTEXT_IS_ARM)
280
281#define DT_CONTEXT_ARM 0x00200000L
282
283#define DT_CONTEXT_CONTROL (DT_CONTEXT_ARM | 0x1L)
284#define DT_CONTEXT_INTEGER (DT_CONTEXT_ARM | 0x2L)
285#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_ARM | 0x4L)
286#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_ARM | 0x8L)
287
288#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
289#define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
290
291#define DT_ARM_MAX_BREAKPOINTS 8
292#define DT_ARM_MAX_WATCHPOINTS 1
293
294typedef struct {
295 ULONGLONG Low;
296 LONGLONG High;
297} DT_NEON128;
298
299typedef DECLSPEC_ALIGN(8) struct {
300
301 //
302 // Control flags.
303 //
304
305 DWORD ContextFlags;
306
307 //
308 // Integer registers
309 //
310
311 DWORD R0;
312 DWORD R1;
313 DWORD R2;
314 DWORD R3;
315 DWORD R4;
316 DWORD R5;
317 DWORD R6;
318 DWORD R7;
319 DWORD R8;
320 DWORD R9;
321 DWORD R10;
322 DWORD R11;
323 DWORD R12;
324
325 //
326 // Control Registers
327 //
328
329 DWORD Sp;
330 DWORD Lr;
331 DWORD Pc;
332 DWORD Cpsr;
333
334 //
335 // Floating Point/NEON Registers
336 //
337
338 DWORD Fpscr;
339 DWORD Padding;
340 union {
341 DT_NEON128 Q[16];
342 ULONGLONG D[32];
343 DWORD S[32];
344 };
345
346 //
347 // Debug registers
348 //
349
350 DWORD Bvr[DT_ARM_MAX_BREAKPOINTS];
351 DWORD Bcr[DT_ARM_MAX_BREAKPOINTS];
352 DWORD Wvr[DT_ARM_MAX_WATCHPOINTS];
353 DWORD Wcr[DT_ARM_MAX_WATCHPOINTS];
354
355 DWORD Padding2[2];
356
357} DT_CONTEXT;
358
359#elif defined(DTCONTEXT_IS_ARM64)
360
361#define DT_CONTEXT_ARM64 0x00400000L
362
363#define DT_CONTEXT_CONTROL (DT_CONTEXT_ARM64 | 0x1L)
364#define DT_CONTEXT_INTEGER (DT_CONTEXT_ARM64 | 0x2L)
365#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_ARM64 | 0x4L)
366#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_ARM64 | 0x8L)
367
368#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
369#define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
370
371#define DT_ARM64_MAX_BREAKPOINTS 8
372#define DT_ARM64_MAX_WATCHPOINTS 2
373
374typedef struct {
375 ULONGLONG Low;
376 LONGLONG High;
377} DT_NEON128;
378
379typedef DECLSPEC_ALIGN(16) struct {
380 //
381 // Control flags.
382 //
383
384 /* +0x000 */ DWORD ContextFlags;
385
386 //
387 // Integer registers
388 //
389
390 /* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel
391 /* +0x008 */ union {
392 struct {
393 DWORD64 X0;
394 DWORD64 X1;
395 DWORD64 X2;
396 DWORD64 X3;
397 DWORD64 X4;
398 DWORD64 X5;
399 DWORD64 X6;
400 DWORD64 X7;
401 DWORD64 X8;
402 DWORD64 X9;
403 DWORD64 X10;
404 DWORD64 X11;
405 DWORD64 X12;
406 DWORD64 X13;
407 DWORD64 X14;
408 DWORD64 X15;
409 DWORD64 X16;
410 DWORD64 X17;
411 DWORD64 X18;
412 DWORD64 X19;
413 DWORD64 X20;
414 DWORD64 X21;
415 DWORD64 X22;
416 DWORD64 X23;
417 DWORD64 X24;
418 DWORD64 X25;
419 DWORD64 X26;
420 DWORD64 X27;
421 DWORD64 X28;
422 };
423 DWORD64 X[29];
424 };
425 /* +0x0f0 */ DWORD64 Fp;
426 /* +0x0f8 */ DWORD64 Lr;
427 /* +0x100 */ DWORD64 Sp;
428 /* +0x108 */ DWORD64 Pc;
429
430 //
431 // Floating Point/NEON Registers
432 //
433
434 /* +0x110 */ DT_NEON128 V[32];
435 /* +0x310 */ DWORD Fpcr;
436 /* +0x314 */ DWORD Fpsr;
437
438 //
439 // Debug registers
440 //
441
442 /* +0x318 */ DWORD Bcr[DT_ARM64_MAX_BREAKPOINTS];
443 /* +0x338 */ DWORD64 Bvr[DT_ARM64_MAX_BREAKPOINTS];
444 /* +0x378 */ DWORD Wcr[DT_ARM64_MAX_WATCHPOINTS];
445 /* +0x380 */ DWORD64 Wvr[DT_ARM64_MAX_WATCHPOINTS];
446 /* +0x390 */
447
448} DT_CONTEXT;
449
450#else
451#error Unsupported platform
452#endif
453
454
455#endif // __DBG_TARGET_CONTEXT_INCLUDED
456