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.
5 #ifndef __DBG_TARGET_CONTEXT_INCLUDED
6 #define __DBG_TARGET_CONTEXT_INCLUDED
8 #include <dbgportable.h>
10 #include "crosscomp.h"
13 // The right side of the debugger can now be built to target multiple platforms. This means it is no longer
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 now 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.
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.
25 // NOTE: Any changes to the field layout of DT_CONTEXT must be tracked in the associated definition of
29 // For now, the only cross-platform CONTEXTs we support are x86/PAL and ARM/Win. Look in
30 // rotor/pal/inc/rotor_pal.h for the original PAL definitions.
33 // **** NOTE: Keep these in sync with rotor/pal/inc/rotor_pal.h ****
36 // This odd define pattern is needed because in DBI we set _TARGET_ to match the host and
37 // DBG_TARGET to control our targeting. In x-plat DBI DBG_TARGET won't match _TARGET_ and
38 // DBG_TARGET needs to take precedence
39 #if defined(DBG_TARGET_X86)
40 #define DTCONTEXT_IS_X86
41 #elif defined (DBG_TARGET_AMD64)
42 #define DTCONTEXT_IS_AMD64
43 #elif defined (DBG_TARGET_ARM)
44 #define DTCONTEXT_IS_ARM
45 #elif defined (DBG_TARGET_ARM64)
46 #define DTCONTEXT_IS_ARM64
47 #elif defined (_TARGET_X86_)
48 #define DTCONTEXT_IS_X86
49 #elif defined (_TARGET_AMD64_)
50 #define DTCONTEXT_IS_AMD64
51 #elif defined (_TARGET_ARM_)
52 #define DTCONTEXT_IS_ARM
53 #elif defined (_TARGET_ARM64_)
54 #define DTCONTEXT_IS_ARM64
57 #if defined(DTCONTEXT_IS_X86)
59 #define DT_SIZE_OF_80387_REGISTERS 80
61 #define DT_CONTEXT_i386 0x00010000
62 #define DT_CONTEXT_CONTROL (DT_CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP
63 #define DT_CONTEXT_INTEGER (DT_CONTEXT_i386 | 0x00000002L) // AX, BX, CX, DX, SI, DI
64 #define DT_CONTEXT_SEGMENTS (DT_CONTEXT_i386 | 0x00000004L)
65 #define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_i386 | 0x00000008L) // 387 state
66 #define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_i386 | 0x00000010L)
68 #define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_SEGMENTS)
69 #define DT_CONTEXT_EXTENDED_REGISTERS (DT_CONTEXT_i386 | 0x00000020L)
71 #define DT_MAXIMUM_SUPPORTED_EXTENSION 512
81 BYTE RegisterArea[DT_SIZE_OF_80387_REGISTERS];
83 } DT_FLOATING_SAVE_AREA;
95 DT_FLOATING_SAVE_AREA FloatSave;
116 UCHAR ExtendedRegisters[DT_MAXIMUM_SUPPORTED_EXTENSION];
120 // Since the target is little endian in this case we only have to provide a real implementation of
121 // ByteSwapContext if the platform we're building on is big-endian.
123 inline void ByteSwapContext(DT_CONTEXT *pContext)
125 // Our job is simplified since the context has large contiguous ranges with fields of the same size. Keep
126 // the following logic in sync with the definition of DT_CONTEXT above.
127 BYTE *pbContext = (BYTE*)pContext;
129 // The first span consists of 4 byte fields.
130 DWORD cbFields = (offsetof(DT_CONTEXT, FloatSave) + offsetof(DT_FLOATING_SAVE_AREA, RegisterArea)) / 4;
131 for (DWORD i = 0; i < cbFields; i++)
133 ByteSwapPrimitive(pbContext, pbContext, 4);
137 // Then there's a float save area containing 8 byte fields.
138 cbFields = sizeof(pContext->FloatSave.RegisterArea);
139 for (DWORD i = 0; i < cbFields; i++)
141 ByteSwapPrimitive(pbContext, pbContext, 8);
145 // Back to 4 byte fields.
146 cbFields = (offsetof(DT_CONTEXT, ExtendedRegisters) - offsetof(DT_CONTEXT, SegGs)) / 4;
147 for (DWORD i = 0; i < cbFields; i++)
149 ByteSwapPrimitive(pbContext, pbContext, 4);
153 // We don't know the formatting of the extended register area, but the debugger doesn't access this data
154 // on the left side, so just leave it in left-side format for now.
156 // Validate that we converted up to where we think we did as a hedge against DT_CONTEXT layout changes.
157 _PASSERT((pbContext - ((BYTE*)pContext)) == (sizeof(DT_CONTEXT) - sizeof(pContext->ExtendedRegisters)));
160 inline void ByteSwapContext(DT_CONTEXT *pContext)
165 #elif defined(DTCONTEXT_IS_AMD64)
167 #define DT_CONTEXT_AMD64 0x00100000L
169 #define DT_CONTEXT_CONTROL (DT_CONTEXT_AMD64 | 0x00000001L)
170 #define DT_CONTEXT_INTEGER (DT_CONTEXT_AMD64 | 0x00000002L)
171 #define DT_CONTEXT_SEGMENTS (DT_CONTEXT_AMD64 | 0x00000004L)
172 #define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_AMD64 | 0x00000008L)
173 #define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_AMD64 | 0x00000010L)
175 #define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
176 #define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_SEGMENTS | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
197 DT_M128A FloatRegisters[8];
198 DT_M128A XmmRegisters[16];
200 } DT_XMM_SAVE_AREA32;
202 typedef struct DECLSPEC_ALIGN(16) {
249 DT_XMM_SAVE_AREA32 FltSave;
272 DT_M128A VectorRegister[26];
273 DWORD64 VectorControl;
275 DWORD64 DebugControl;
276 DWORD64 LastBranchToRip;
277 DWORD64 LastBranchFromRip;
278 DWORD64 LastExceptionToRip;
279 DWORD64 LastExceptionFromRip;
282 #elif defined(DTCONTEXT_IS_ARM)
284 #define DT_CONTEXT_ARM 0x00200000L
286 #define DT_CONTEXT_CONTROL (DT_CONTEXT_ARM | 0x1L)
287 #define DT_CONTEXT_INTEGER (DT_CONTEXT_ARM | 0x2L)
288 #define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_ARM | 0x4L)
289 #define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_ARM | 0x8L)
291 #define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
292 #define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
294 #define DT_ARM_MAX_BREAKPOINTS 8
295 #define DT_ARM_MAX_WATCHPOINTS 1
302 typedef DECLSPEC_ALIGN(8) struct {
338 // Floating Point/NEON Registers
353 DWORD Bvr[DT_ARM_MAX_BREAKPOINTS];
354 DWORD Bcr[DT_ARM_MAX_BREAKPOINTS];
355 DWORD Wvr[DT_ARM_MAX_WATCHPOINTS];
356 DWORD Wcr[DT_ARM_MAX_WATCHPOINTS];
362 #elif defined(DTCONTEXT_IS_ARM64)
364 #define DT_CONTEXT_ARM64 0x00400000L
366 #define DT_CONTEXT_CONTROL (DT_CONTEXT_ARM64 | 0x1L)
367 #define DT_CONTEXT_INTEGER (DT_CONTEXT_ARM64 | 0x2L)
368 #define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_ARM64 | 0x4L)
369 #define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_ARM64 | 0x8L)
371 #define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
372 #define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
374 #define DT_ARM64_MAX_BREAKPOINTS 8
375 #define DT_ARM64_MAX_WATCHPOINTS 2
382 typedef DECLSPEC_ALIGN(16) struct {
387 /* +0x000 */ DWORD ContextFlags;
393 /* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel
428 /* +0x0f0 */ DWORD64 Fp;
429 /* +0x0f8 */ DWORD64 Lr;
430 /* +0x100 */ DWORD64 Sp;
431 /* +0x108 */ DWORD64 Pc;
434 // Floating Point/NEON Registers
437 /* +0x110 */ DT_NEON128 V[32];
438 /* +0x310 */ DWORD Fpcr;
439 /* +0x314 */ DWORD Fpsr;
445 /* +0x318 */ DWORD Bcr[DT_ARM64_MAX_BREAKPOINTS];
446 /* +0x338 */ DWORD64 Bvr[DT_ARM64_MAX_BREAKPOINTS];
447 /* +0x378 */ DWORD Wcr[DT_ARM64_MAX_WATCHPOINTS];
448 /* +0x380 */ DWORD64 Wvr[DT_ARM64_MAX_WATCHPOINTS];
454 #error Unsupported platform
458 #endif // __DBG_TARGET_CONTEXT_INCLUDED