VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCRemoteKd.cpp@ 86148

Last change on this file since 86148 was 86148, checked in by vboxsync, 4 years ago

Debugger/DBGCRemoteKd: Some basic register writing code, not fully functional it looks like (register values are not seen even though the write succeeds

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 116.9 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 86148 2020-09-17 11:22:13Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Windows Kd Remote Stub.
4 */
5
6/*
7 * Copyright (C) 2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <VBox/dbg.h>
23#include <VBox/vmm/dbgf.h>
24#include <VBox/vmm/vmapi.h> /* VMR3GetVM() */
25#include <VBox/vmm/hm.h> /* HMR3IsEnabled */
26#include <VBox/vmm/nem.h> /* NEMR3IsEnabled */
27#include <iprt/assertcompile.h>
28#include <iprt/cdefs.h>
29#include <iprt/err.h>
30#include <iprt/list.h>
31#include <iprt/mem.h>
32#include <iprt/sg.h>
33#include <iprt/string.h>
34#include <iprt/time.h>
35#include <iprt/x86.h>
36#include <iprt/formats/pecoff.h>
37#include <iprt/formats/mz.h>
38
39#include <stdlib.h>
40
41#include "DBGCInternal.h"
42
43
44/*********************************************************************************************************************************
45* Defined Constants And Macros *
46*********************************************************************************************************************************/
47
48/** Number of milliseconds we wait for new data to arrive when a new packet was detected. */
49#define DBGC_KD_RECV_TIMEOUT_MS UINT32_C(1000)
50
51/** NT status code - Success. */
52#define NTSTATUS_SUCCESS 0
53/** NT status code - operation unsuccesful. */
54#define NTSTATUS_UNSUCCESSFUL UINT32_C(0xc0000001)
55/** NT status code - operation not implemented. */
56#define NTSTATUS_NOT_IMPLEMENTED UINT32_C(0xc0000002)
57
58
59/*********************************************************************************************************************************
60* Structures and Typedefs *
61*********************************************************************************************************************************/
62
63/**
64 * KD packet header as sent over the wire.
65 */
66typedef struct KDPACKETHDR
67{
68 /** Packet signature (leader) - defines the type of packet. */
69 uint32_t u32Signature;
70 /** Packet (sub) type. */
71 uint16_t u16SubType;
72 /** Size of the packet body in bytes.*/
73 uint16_t cbBody;
74 /** Packet ID. */
75 uint32_t idPacket;
76 /** Checksum of the packet body. */
77 uint32_t u32ChkSum;
78} KDPACKETHDR;
79AssertCompileSize(KDPACKETHDR, 16);
80/** Pointer to a packet header. */
81typedef KDPACKETHDR *PKDPACKETHDR;
82/** Pointer to a const packet header. */
83typedef const KDPACKETHDR *PCKDPACKETHDR;
84
85/** Signature for a data packet. */
86#define KD_PACKET_HDR_SIGNATURE_DATA UINT32_C(0x30303030)
87/** First byte for a data packet header. */
88#define KD_PACKET_HDR_SIGNATURE_DATA_BYTE 0x30
89/** Signature for a control packet. */
90#define KD_PACKET_HDR_SIGNATURE_CONTROL UINT32_C(0x69696969)
91/** First byte for a control packet header. */
92#define KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE 0x69
93/** Signature for a breakin packet. */
94#define KD_PACKET_HDR_SIGNATURE_BREAKIN UINT32_C(0x62626262)
95/** First byte for a breakin packet header. */
96#define KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE 0x62
97
98/** @name Packet sub types.
99 * @{ */
100#define KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32 UINT16_C(1)
101#define KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE UINT16_C(2)
102#define KD_PACKET_HDR_SUB_TYPE_DEBUG_IO UINT16_C(3)
103#define KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE UINT16_C(4)
104#define KD_PACKET_HDR_SUB_TYPE_RESEND UINT16_C(5)
105#define KD_PACKET_HDR_SUB_TYPE_RESET UINT16_C(6)
106#define KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64 UINT16_C(7)
107#define KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN UINT16_C(8)
108#define KD_PACKET_HDR_SUB_TYPE_TRACE_IO UINT16_C(9)
109#define KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST UINT16_C(10)
110#define KD_PACKET_HDR_SUB_TYPE_FILE_IO UINT16_C(11)
111#define KD_PACKET_HDR_SUB_TYPE_MAX UINT16_C(12)
112/** @} */
113
114/** Initial packet ID value. */
115#define KD_PACKET_HDR_ID_INITIAL UINT32_C(0x80800800)
116/** Packet ID value after a resync. */
117#define KD_PACKET_HDR_ID_RESET UINT32_C(0x80800000)
118
119/** Trailing byte of a packet. */
120#define KD_PACKET_TRAILING_BYTE 0xaa
121
122
123/** Maximum number of parameters in the exception record. */
124#define KDPACKETEXCP_PARMS_MAX 15
125
126/**
127 * 64bit exception record.
128 */
129typedef struct KDPACKETEXCP64
130{
131 /** The exception code identifying the excpetion. */
132 uint32_t u32ExcpCode;
133 /** Flags associated with the exception. */
134 uint32_t u32ExcpFlags;
135 /** Pointer to a chained exception record. */
136 uint64_t u64PtrExcpRecNested;
137 /** Address where the exception occurred. */
138 uint64_t u64PtrExcpAddr;
139 /** Number of parameters in the exception information array. */
140 uint32_t cExcpParms;
141 /** Alignment. */
142 uint32_t u32Alignment;
143 /** Exception parameters array. */
144 uint64_t au64ExcpParms[KDPACKETEXCP_PARMS_MAX];
145} KDPACKETEXCP64;
146AssertCompileSize(KDPACKETEXCP64, 152);
147/** Pointer to an exception record. */
148typedef KDPACKETEXCP64 *PKDPACKETEXCP64;
149/** Pointer to a const exception record. */
150typedef const KDPACKETEXCP64 *PCKDPACKETEXCP64;
151
152
153/**
154 * amd64 NT context structure.
155 */
156typedef struct NTCONTEXT64
157{
158 /** The P[1-6]Home members. */
159 uint64_t au64PHome[6];
160 /** Context flags indicating the valid bits, see NTCONTEXT_F_XXX. */
161 uint32_t fContext;
162 /** MXCSR register. */
163 uint32_t u32RegMxCsr;
164 /** CS selector. */
165 uint16_t u16SegCs;
166 /** DS selector. */
167 uint16_t u16SegDs;
168 /** ES selector. */
169 uint16_t u16SegEs;
170 /** FS selector. */
171 uint16_t u16SegFs;
172 /** GS selector. */
173 uint16_t u16SegGs;
174 /** SS selector. */
175 uint16_t u16SegSs;
176 /** EFlags register. */
177 uint32_t u32RegEflags;
178 /** DR0 register. */
179 uint64_t u64RegDr0;
180 /** DR1 register. */
181 uint64_t u64RegDr1;
182 /** DR2 register. */
183 uint64_t u64RegDr2;
184 /** DR3 register. */
185 uint64_t u64RegDr3;
186 /** DR6 register. */
187 uint64_t u64RegDr6;
188 /** DR7 register. */
189 uint64_t u64RegDr7;
190 /** RAX register. */
191 uint64_t u64RegRax;
192 /** RCX register. */
193 uint64_t u64RegRcx;
194 /** RDX register. */
195 uint64_t u64RegRdx;
196 /** RBX register. */
197 uint64_t u64RegRbx;
198 /** RSP register. */
199 uint64_t u64RegRsp;
200 /** RBP register. */
201 uint64_t u64RegRbp;
202 /** RSI register. */
203 uint64_t u64RegRsi;
204 /** RDI register. */
205 uint64_t u64RegRdi;
206 /** R8 register. */
207 uint64_t u64RegR8;
208 /** R9 register. */
209 uint64_t u64RegR9;
210 /** R10 register. */
211 uint64_t u64RegR10;
212 /** R11 register. */
213 uint64_t u64RegR11;
214 /** R12 register. */
215 uint64_t u64RegR12;
216 /** R13 register. */
217 uint64_t u64RegR13;
218 /** R14 register. */
219 uint64_t u64RegR14;
220 /** R15 register. */
221 uint64_t u64RegR15;
222 /** RIP register. */
223 uint64_t u64RegRip;
224 /** Extended floating point save area. */
225 X86FXSTATE FxSave;
226 /** AVX(?) vector registers. */
227 RTUINT128U aRegsVec[26];
228 /** Vector control register. */
229 uint64_t u64RegVecCtrl;
230 /** Debug control. */
231 uint64_t u64DbgCtrl;
232 /** @todo */
233 uint64_t u64LastBrToRip;
234 uint64_t u64LastBrFromRip;
235 uint64_t u64LastExcpToRip;
236 uint64_t u64LastExcpFromRip;
237} NTCONTEXT64;
238AssertCompileSize(NTCONTEXT64, 1232);
239AssertCompileMemberOffset(NTCONTEXT64, FxSave, 0x100);
240AssertCompileMemberOffset(NTCONTEXT64, aRegsVec, 0x300);
241/** Pointer to an amd64 NT context. */
242typedef NTCONTEXT64 *PNTCONTEXT64;
243/** Pointer to a const amd64 NT context. */
244typedef const NTCONTEXT64 *PCNTCONTEXT64;
245
246
247/**
248 * [GI]DT descriptor.
249 */
250typedef struct NTKCONTEXTDESC64
251{
252 /** Alignment. */
253 uint16_t au16Alignment[3];
254 /** Limit. */
255 uint16_t u16Limit;
256 /** Base address. */
257 uint64_t u64PtrBase;
258} NTKCONTEXTDESC64;
259AssertCompileSize(NTKCONTEXTDESC64, 2 * 8);
260/** Pointer to an amd64 NT context. */
261typedef NTKCONTEXTDESC64 *PNTKCONTEXTDESC64;
262/** Pointer to a const amd64 NT context. */
263typedef const NTKCONTEXTDESC64 *PCNTKCONTEXTDESC64;
264
265
266/**
267 * Kernel context as queried by KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE
268 */
269typedef struct NTKCONTEXT64
270{
271 /** CR0 register. */
272 uint64_t u64RegCr0;
273 /** CR2 register. */
274 uint64_t u64RegCr2;
275 /** CR3 register. */
276 uint64_t u64RegCr3;
277 /** CR4 register. */
278 uint64_t u64RegCr4;
279 /** DR0 register. */
280 uint64_t u64RegDr0;
281 /** DR1 register. */
282 uint64_t u64RegDr1;
283 /** DR2 register. */
284 uint64_t u64RegDr2;
285 /** DR3 register. */
286 uint64_t u64RegDr3;
287 /** DR6 register. */
288 uint64_t u64RegDr6;
289 /** DR7 register. */
290 uint64_t u64RegDr7;
291 /** GDTR. */
292 NTKCONTEXTDESC64 Gdtr;
293 /** IDTR. */
294 NTKCONTEXTDESC64 Idtr;
295 /** TR register. */
296 uint16_t u16RegTr;
297 /** LDTR register. */
298 uint16_t u16RegLdtr;
299 /** MXCSR register. */
300 uint32_t u32RegMxCsr;
301 /** Debug control. */
302 uint64_t u64DbgCtrl;
303 /** @todo */
304 uint64_t u64LastBrToRip;
305 uint64_t u64LastBrFromRip;
306 uint64_t u64LastExcpToRip;
307 uint64_t u64LastExcpFromRip;
308 /** CR8 register. */
309 uint64_t u64RegCr8;
310 /** GS base MSR register. */
311 uint64_t u64MsrGsBase;
312 /** Kernel GS base MSR register. */
313 uint64_t u64MsrKernelGsBase;
314 /** STAR MSR register. */
315 uint64_t u64MsrStar;
316 /** LSTAR MSR register. */
317 uint64_t u64MsrLstar;
318 /** CSTAR MSR register. */
319 uint64_t u64MsrCstar;
320 /** SFMASK MSR register. */
321 uint64_t u64MsrSfMask;
322 /** XCR0 register. */
323 uint64_t u64RegXcr0;
324 /** Standard context. */
325 NTCONTEXT64 Ctx;
326} NTKCONTEXT64;
327AssertCompileMemberOffset(NTKCONTEXT64, Ctx, 224);
328/** Pointer to an amd64 NT context. */
329typedef NTKCONTEXT64 *PNTKCONTEXT64;
330/** Pointer to a const amd64 NT context. */
331typedef const NTKCONTEXT64 *PCNTKCONTEXT64;
332
333
334/** x86 context. */
335#define NTCONTEXT_F_X86 UINT32_C(0x00010000)
336/** AMD64 context. */
337#define NTCONTEXT_F_AMD64 UINT32_C(0x00100000)
338/** Control registers valid (CS, (R)SP, (R)IP, FLAGS and BP). */
339#define NTCONTEXT_F_CONTROL RT_BIT_32(0)
340/** Integer registers valid. */
341#define NTCONTEXT_F_INTEGER RT_BIT_32(1)
342/** Segment registers valid. */
343#define NTCONTEXT_F_SEGMENTS RT_BIT_32(2)
344/** Floating point registers valid. */
345#define NTCONTEXT_F_FLOATING_POINT RT_BIT_32(3)
346/** Debug registers valid. */
347#define NTCONTEXT_F_DEBUG RT_BIT_32(4)
348/** Extended registers valid (x86 only). */
349#define NTCONTEXT_F_EXTENDED RT_BIT_32(5)
350/** Full x86 context valid. */
351#define NTCONTEXT32_F_FULL (NTCONTEXT_F_X86 | NTCONTEXT_F_CONTROL | NTCONTEXT_F_INTEGER | NTCONTEXT_F_SEGMENTS)
352/** Full amd64 context valid. */
353#define NTCONTEXT64_F_FULL (NTCONTEXT_F_AMD64 | NTCONTEXT_F_CONTROL | NTCONTEXT_F_INTEGER | NTCONTEXT_F_SEGMENTS)
354
355
356/**
357 * 32bit exception record.
358 */
359typedef struct KDPACKETEXCP32
360{
361 /** The exception code identifying the excpetion. */
362 uint32_t u32ExcpCode;
363 /** Flags associated with the exception. */
364 uint32_t u32ExcpFlags;
365 /** Pointer to a chained exception record. */
366 uint32_t u32PtrExcpRecNested;
367 /** Address where the exception occurred. */
368 uint32_t u32PtrExcpAddr;
369 /** Number of parameters in the exception information array. */
370 uint32_t cExcpParms;
371 /** Exception parameters array. */
372 uint32_t au32ExcpParms[KDPACKETEXCP_PARMS_MAX];
373} KDPACKETEXCP32;
374AssertCompileSize(KDPACKETEXCP32, 80);
375/** Pointer to an exception record. */
376typedef KDPACKETEXCP32 *PKDPACKETEXCP32;
377/** Pointer to a const exception record. */
378typedef const KDPACKETEXCP32 *PCKDPACKETEXCP32;
379
380
381/** @name Exception codes.
382 * @{ */
383/** A breakpoint was hit. */
384#define KD_PACKET_EXCP_CODE_BKPT UINT32_C(0x80000003)
385/** An instruction was single stepped. */
386#define KD_PACKET_EXCP_CODE_SINGLE_STEP UINT32_C(0x80000004)
387/** @} */
388
389
390/** Maximum number of bytes in the instruction stream. */
391#define KD_PACKET_CTRL_REPORT_INSN_STREAM_MAX 16
392
393/**
394 * 64bit control report record.
395 */
396typedef struct KDPACKETCTRLREPORT64
397{
398 /** Value of DR6. */
399 uint64_t u64RegDr6;
400 /** Value of DR7. */
401 uint64_t u64RegDr7;
402 /** EFLAGS. */
403 uint32_t u32RegEflags;
404 /** Number of instruction bytes in the instruction stream. */
405 uint16_t cbInsnStream;
406 /** Report flags. */
407 uint16_t fFlags;
408 /** The instruction stream. */
409 uint8_t abInsn[KD_PACKET_CTRL_REPORT_INSN_STREAM_MAX];
410 /** CS selector. */
411 uint16_t u16SegCs;
412 /** DS selector. */
413 uint16_t u16SegDs;
414 /** ES selector. */
415 uint16_t u16SegEs;
416 /** FS selector. */
417 uint16_t u16SegFs;
418} KDPACKETCTRLREPORT64;
419AssertCompileSize(KDPACKETCTRLREPORT64, 2 * 8 + 4 + 2 * 2 + 16 + 4 * 2);
420/** Pointer to a control report record. */
421typedef KDPACKETCTRLREPORT64 *PKDPACKETCTRLREPORT64;
422/** Pointer to a const control report record. */
423typedef const KDPACKETCTRLREPORT64 *PCKDPACKETCTRLREPORT64;
424
425
426/**
427 * 64bit state change packet body.
428 */
429typedef struct KDPACKETSTATECHANGE64
430{
431 /** The new state. */
432 uint32_t u32StateNew;
433 /** The processor level. */
434 uint16_t u16CpuLvl;
435 /** The processor ID generating the state change. */
436 uint16_t idCpu;
437 /** Number of processors in the system. */
438 uint32_t cCpus;
439 /** Alignment. */
440 uint32_t u32Alignment;
441 /** The thread ID currently executing when the state change occurred. */
442 uint64_t idThread;
443 /** Program counter of the thread. */
444 uint64_t u64RipThread;
445 /** Data based on the state. */
446 union
447 {
448 /** Exception occurred data. */
449 struct
450 {
451 /** The exception record. */
452 KDPACKETEXCP64 ExcpRec;
453 /** First chance(?). */
454 uint32_t u32FirstChance;
455 } Exception;
456 } u;
457 /** The control report */
458 union
459 {
460 /** AMD64 control report. */
461 KDPACKETCTRLREPORT64 Amd64;
462 } uCtrlReport;
463} KDPACKETSTATECHANGE64;
464//AssertCompileSize(KDPACKETSTATECHANGE64, 4 + 2 * 2 + 2 * 4 + 2 * 8 + sizeof(KDPACKETEXCP64) + 4 + sizeof(KDPACKETCTRLREPORT64));
465/** Pointer to a 64bit state change packet body. */
466typedef KDPACKETSTATECHANGE64 *PKDPACKETSTATECHANGE64;
467/** Pointer to a const 64bit state change packet body. */
468typedef const KDPACKETSTATECHANGE64 *PCKDPACKETSTATECHANGE64;
469
470
471/** @name State change state types.
472 * @{ */
473/** Minimum state change type. */
474#define KD_PACKET_STATE_CHANGE_MIN UINT32_C(0x00003030)
475/** An exception occured. */
476#define KD_PACKET_STATE_CHANGE_EXCEPTION KD_PACKET_STATE_CHANGE_MIN
477/** Symbols were loaded(?). */
478#define KD_PACKET_STATE_CHANGE_LOAD_SYMBOLS UINT32_C(0x00003031)
479/** Command string (custom command was executed?). */
480#define KD_PACKET_STATE_CHANGE_CMD_STRING UINT32_C(0x00003032)
481/** Maximum state change type (exclusive). */
482#define KD_PACKET_STATE_CHANGE_MAX UINT32_C(0x00003033)
483/** @} */
484
485
486/**
487 * 64bit get version manipulate payload.
488 */
489typedef struct KDPACKETMANIPULATE_GETVERSION64
490{
491 /** Major version. */
492 uint16_t u16VersMaj;
493 /** Minor version. */
494 uint16_t u16VersMin;
495 /** Protocol version. */
496 uint8_t u8VersProtocol;
497 /** KD secondary version. */
498 uint8_t u8VersKdSecondary;
499 /** Flags. */
500 uint16_t fFlags;
501 /** Machine type. */
502 uint16_t u16MachineType;
503 /** Maximum packet type. */
504 uint8_t u8MaxPktType;
505 /** Maximum state change */
506 uint8_t u8MaxStateChange;
507 /** Maximum manipulate request ID. */
508 uint8_t u8MaxManipulate;
509 /** Some simulation flag. */
510 uint8_t u8Simulation;
511 /** Padding. */
512 uint16_t u16Padding;
513 /** Kernel base. */
514 uint64_t u64PtrKernBase;
515 /** Pointer of the loaded module list head. */
516 uint64_t u64PtrPsLoadedModuleList;
517 /** Pointer of the debugger data list. */
518 uint64_t u64PtrDebuggerDataList;
519} KDPACKETMANIPULATE_GETVERSION64;
520AssertCompileSize(KDPACKETMANIPULATE_GETVERSION64, 40);
521/** Pointer to a 64bit get version manipulate payload. */
522typedef KDPACKETMANIPULATE_GETVERSION64 *PKDPACKETMANIPULATE_GETVERSION64;
523/** Pointer to a const 64bit get version manipulate payload. */
524typedef const KDPACKETMANIPULATE_GETVERSION64 *PCKDPACKETMANIPULATE_GETVERSION64;
525
526
527/**
528 * 64bit memory transfer manipulate payload.
529 */
530typedef struct KDPACKETMANIPULATE_XFERMEM64
531{
532 /** Target base address. */
533 uint64_t u64PtrTarget;
534 /** Requested number of bytes to transfer*/
535 uint32_t cbXferReq;
536 /** Number of bytes actually transferred (response). */
537 uint32_t cbXfered;
538 /** Some padding?. */
539 uint64_t au64Pad[3];
540} KDPACKETMANIPULATE_XFERMEM64;
541AssertCompileSize(KDPACKETMANIPULATE_XFERMEM64, 40);
542/** Pointer to a 64bit memory transfer manipulate payload. */
543typedef KDPACKETMANIPULATE_XFERMEM64 *PKDPACKETMANIPULATE_XFERMEM64;
544/** Pointer to a const 64bit memory transfer manipulate payload. */
545typedef const KDPACKETMANIPULATE_XFERMEM64 *PCKDPACKETMANIPULATE_XFERMEM64;
546
547
548/**
549 * 64bit control space transfer manipulate payload.
550 *
551 * @note Same layout as the memory transfer but the pointer has a different meaning so
552 * we moved it into a separate request structure.
553 */
554typedef struct KDPACKETMANIPULATE_XFERCTRLSPACE64
555{
556 /** Identifier of the item to transfer in the control space. */
557 uint64_t u64IdXfer;
558 /** Requested number of bytes to transfer*/
559 uint32_t cbXferReq;
560 /** Number of bytes actually transferred (response). */
561 uint32_t cbXfered;
562 /** Some padding?. */
563 uint64_t au64Pad[3];
564} KDPACKETMANIPULATE_XFERCTRLSPACE64;
565AssertCompileSize(KDPACKETMANIPULATE_XFERCTRLSPACE64, 40);
566/** Pointer to a 64bit memory transfer manipulate payload. */
567typedef KDPACKETMANIPULATE_XFERCTRLSPACE64 *PKDPACKETMANIPULATE_XFERCTRLSPACE64;
568/** Pointer to a const 64bit memory transfer manipulate payload. */
569typedef const KDPACKETMANIPULATE_XFERCTRLSPACE64 *PCKDPACKETMANIPULATE_XFERCTRLSPACE64;
570
571
572/** @name Known control space identifiers.
573 * @{ */
574/** Read/Write KPCR address. */
575#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR UINT64_C(0)
576/** Read/Write KPCRB address. */
577#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB UINT64_C(1)
578/** Read/Write Kernel context. */
579#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX UINT64_C(2)
580/** Read/Write current kernel thread. */
581#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD UINT64_C(3)
582/** @} */
583
584
585/**
586 * 64bit restore breakpoint manipulate payload.
587 */
588typedef struct KDPACKETMANIPULATE_RESTOREBKPT64
589{
590 /** The breakpoint handle to restore. */
591 uint32_t u32HndBkpt;
592 /** Blows up the request to the required size. */
593 uint8_t abPad[36];
594} KDPACKETMANIPULATE_RESTOREBKPT64;
595AssertCompileSize(KDPACKETMANIPULATE_RESTOREBKPT64, 40);
596/** Pointer to a 64bit restore breakpoint manipulate payload. */
597typedef KDPACKETMANIPULATE_RESTOREBKPT64 *PKDPACKETMANIPULATE_RESTOREBKPT64;
598/** Pointer to a const 64bit restore breakpoint manipulate payload. */
599typedef const KDPACKETMANIPULATE_RESTOREBKPT64 *PCKDPACKETMANIPULATE_RESTOREBKPT64;
600
601
602/**
603 * 64bit write breakpoint manipulate payload.
604 */
605typedef struct KDPACKETMANIPULATE_WRITEBKPT64
606{
607 /** Where to write the breakpoint. */
608 uint64_t u64PtrBkpt;
609 /** The breakpoint handle returned in the response. */
610 uint32_t u32HndBkpt;
611 /** Blows up the request to the required size. */
612 uint8_t abPad[28];
613} KDPACKETMANIPULATE_WRITEBKPT64;
614AssertCompileSize(KDPACKETMANIPULATE_WRITEBKPT64, 40);
615/** Pointer to a 64bit write breakpoint manipulate payload. */
616typedef KDPACKETMANIPULATE_WRITEBKPT64 *PKDPACKETMANIPULATE_WRITEBKPT64;
617/** Pointer to a const 64bit write breakpoint manipulate payload. */
618typedef const KDPACKETMANIPULATE_WRITEBKPT64 *PCKDPACKETMANIPULATE_WRITEBKPT64;
619
620
621/**
622 * Context extended manipulate payload.
623 */
624typedef struct KDPACKETMANIPULATE_CONTEXTEX
625{
626 /** Where to start copying the context. */
627 uint32_t offStart;
628 /** Number of bytes to transfer. */
629 uint32_t cbXfer;
630 /** Number of bytes actually transfered. */
631 uint32_t cbXfered;
632 /** Blows up the request to the required size. */
633 uint8_t abPad[28];
634} KDPACKETMANIPULATE_CONTEXTEX;
635AssertCompileSize(KDPACKETMANIPULATE_CONTEXTEX, 40);
636/** Pointer to a context extended manipulate payload. */
637typedef KDPACKETMANIPULATE_CONTEXTEX *PKDPACKETMANIPULATE_CONTEXTEX;
638/** Pointer to a const context extended manipulate payload. */
639typedef const KDPACKETMANIPULATE_CONTEXTEX *PCKDPACKETMANIPULATE_CONTEXTEX;
640
641
642/**
643 * Continue manipulate payload.
644 */
645typedef struct KDPACKETMANIPULATE_CONTINUE
646{
647 /** Continue (status?). */
648 uint32_t u32NtContSts;
649 /** Blows up the request to the required size. */
650 uint8_t abPad[36];
651} KDPACKETMANIPULATE_CONTINUE;
652AssertCompileSize(KDPACKETMANIPULATE_CONTINUE, 40);
653/** Pointer to a continue manipulate payload. */
654typedef KDPACKETMANIPULATE_CONTINUE *PKDPACKETMANIPULATE_CONTINUE;
655/** Pointer to a const continue manipulate payload. */
656typedef const KDPACKETMANIPULATE_CONTINUE *PCKDPACKETMANIPULATE_CONTINUE;
657
658
659/**
660 * Continue 2 manipulate payload.
661 */
662typedef struct KDPACKETMANIPULATE_CONTINUE2
663{
664 /** Continue (status?). */
665 uint32_t u32NtContSts;
666 /** Trace flag. */
667 uint32_t fTrace;
668 /** Bitsize dependent data. */
669 union
670 {
671 /** 32bit. */
672 struct
673 {
674 /** DR7 value to continue with. */
675 uint32_t u32RegDr7;
676 /** @todo (?) */
677 uint32_t u32SymCurStart;
678 uint32_t u32SymCurEnd;
679 } x86;
680 /** 64bit. */
681 struct
682 {
683 /** DR7 value to continue with. */
684 uint64_t u64RegDr7;
685 /** @todo (?) */
686 uint64_t u64SymCurStart;
687 uint64_t u64SymCurEnd;
688 } amd64;
689 } u;
690 /** Blows up the request to the required size. */
691 uint8_t abPad[8];
692} KDPACKETMANIPULATE_CONTINUE2;
693AssertCompileSize(KDPACKETMANIPULATE_CONTINUE2, 40);
694/** Pointer to a continue 2 manipulate payload. */
695typedef KDPACKETMANIPULATE_CONTINUE2 *PKDPACKETMANIPULATE_CONTINUE2;
696/** Pointer to a const continue 2 manipulate payload. */
697typedef const KDPACKETMANIPULATE_CONTINUE2 *PCKDPACKETMANIPULATE_CONTINUE2;
698
699
700/**
701 * Set context manipulate payload.
702 */
703typedef struct KDPACKETMANIPULATE_SETCONTEXT
704{
705 /** Continue (status?). */
706 uint32_t u32CtxFlags;
707 /** Blows up the request to the required size. */
708 uint8_t abPad[36];
709} KDPACKETMANIPULATE_SETCONTEXT;
710AssertCompileSize(KDPACKETMANIPULATE_SETCONTEXT, 40);
711/** Pointer to a set context manipulate payload. */
712typedef KDPACKETMANIPULATE_SETCONTEXT *PKDPACKETMANIPULATE_SETCONTEXT;
713/** Pointer to a const set context manipulate payload. */
714typedef const KDPACKETMANIPULATE_SETCONTEXT *PCKDPACKETMANIPULATE_SETCONTEXT;
715
716
717/**
718 * Manipulate request packet header (Same for 32bit and 64bit).
719 */
720typedef struct KDPACKETMANIPULATEHDR
721{
722 /** The request to execute. */
723 uint32_t idReq;
724 /** The processor level to execute the request on. */
725 uint16_t u16CpuLvl;
726 /** The processor ID to execute the request on. */
727 uint16_t idCpu;
728 /** Return status code. */
729 uint32_t u32NtStatus;
730 /** Alignment. */
731 uint32_t u32Alignment;
732} KDPACKETMANIPULATEHDR;
733AssertCompileSize(KDPACKETMANIPULATEHDR, 3 * 4 + 2 * 2);
734/** Pointer to a manipulate request packet header. */
735typedef KDPACKETMANIPULATEHDR *PKDPACKETMANIPULATEHDR;
736/** Pointer to a const manipulate request packet header. */
737typedef const KDPACKETMANIPULATEHDR *PCPKDPACKETMANIPULATEHDR;
738
739
740/**
741 * 64bit manipulate state request packet.
742 */
743typedef struct KDPACKETMANIPULATE64
744{
745 /** Header. */
746 KDPACKETMANIPULATEHDR Hdr;
747 /** Request payloads. */
748 union
749 {
750 /** Get Version. */
751 KDPACKETMANIPULATE_GETVERSION64 GetVersion;
752 /** Read/Write memory. */
753 KDPACKETMANIPULATE_XFERMEM64 XferMem;
754 /** Continue. */
755 KDPACKETMANIPULATE_CONTINUE Continue;
756 /** Continue2. */
757 KDPACKETMANIPULATE_CONTINUE2 Continue2;
758 /** Set context. */
759 KDPACKETMANIPULATE_SETCONTEXT SetContext;
760 /** Read/Write control space. */
761 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace;
762 /** Restore breakpoint. */
763 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt;
764 /** Write breakpoint. */
765 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt;
766 /** Context extended. */
767 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
768 } u;
769} KDPACKETMANIPULATE64;
770AssertCompileSize(KDPACKETMANIPULATE64, 16 + 40);
771/** Pointer to a 64bit manipulate state request packet. */
772typedef KDPACKETMANIPULATE64 *PKDPACKETMANIPULATE64;
773/** Pointer to a const 64bit manipulate state request packet. */
774typedef const KDPACKETMANIPULATE64 *PCKDPACKETMANIPULATE64;
775
776/** @name Manipulate requests.
777 * @{ */
778/** Minimum available request. */
779#define KD_PACKET_MANIPULATE_REQ_MIN UINT32_C(0x00003130)
780/** Read virtual memory request. */
781#define KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM KD_PACKET_MANIPULATE_REQ_MIN
782/** Write virtual memory request. */
783#define KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM UINT32_C(0x00003131)
784/** Get context request. */
785#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT UINT32_C(0x00003132)
786/** Set context request. */
787#define KD_PACKET_MANIPULATE_REQ_SET_CONTEXT UINT32_C(0x00003133)
788/** Write breakpoint request. */
789#define KD_PACKET_MANIPULATE_REQ_WRITE_BKPT UINT32_C(0x00003134)
790/** Restore breakpoint request. */
791#define KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT UINT32_C(0x00003135)
792/** Continue request. */
793#define KD_PACKET_MANIPULATE_REQ_CONTINUE UINT32_C(0x00003136)
794/** Read control space request. */
795#define KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE UINT32_C(0x00003137)
796/** Write control space request. */
797#define KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE UINT32_C(0x00003138)
798/** Read I/O space request. */
799#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE UINT32_C(0x00003139)
800/** Write I/O space request. */
801#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE UINT32_C(0x0000313a)
802/** Reboot request. */
803#define KD_PACKET_MANIPULATE_REQ_REBOOT UINT32_C(0x0000313b)
804/** continue 2nd version request. */
805#define KD_PACKET_MANIPULATE_REQ_CONTINUE2 UINT32_C(0x0000313c)
806/** Read physical memory request. */
807#define KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM UINT32_C(0x0000313d)
808/** Write physical memory request. */
809#define KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM UINT32_C(0x0000313e)
810/** Query special calls request. */
811#define KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS UINT32_C(0x0000313f)
812/** Set special calls request. */
813#define KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS UINT32_C(0x00003140)
814/** Clear special calls request. */
815#define KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS UINT32_C(0x00003141)
816/** Set internal breakpoint request. */
817#define KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT UINT32_C(0x00003142)
818/** Get internal breakpoint request. */
819#define KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT UINT32_C(0x00003143)
820/** Read I/O space extended request. */
821#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX UINT32_C(0x00003144)
822/** Write I/O space extended request. */
823#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX UINT32_C(0x00003145)
824/** Get version request. */
825#define KD_PACKET_MANIPULATE_REQ_GET_VERSION UINT32_C(0x00003146)
826/** @todo */
827/** Clear all internal breakpoints request. */
828#define KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT UINT32_C(0x0000315a)
829/** @todo */
830/** Get context extended request. */
831#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX UINT32_C(0x0000315f)
832/** @todo */
833/** Maximum available request (exclusive). */
834#define KD_PACKET_MANIPULATE_REQ_MAX UINT32_C(0x00003161)
835/** @} */
836
837/**
838 * KD stub receive state.
839 */
840typedef enum KDRECVSTATE
841{
842 /** Invalid state. */
843 KDRECVSTATE_INVALID = 0,
844 /** Receiving the first byte of the packet header. */
845 KDRECVSTATE_PACKET_HDR_FIRST_BYTE,
846 /** Receiving the second byte of the packet header. */
847 KDRECVSTATE_PACKET_HDR_SECOND_BYTE,
848 /** Receiving the header. */
849 KDRECVSTATE_PACKET_HDR,
850 /** Receiving the packet body. */
851 KDRECVSTATE_PACKET_BODY,
852 /** Receiving the trailing byte. */
853 KDRECVSTATE_PACKET_TRAILER,
854 /** Blow up the enum to 32bits for easier alignment of members in structs. */
855 KDRECVSTATE_32BIT_HACK = 0x7fffffff
856} KDRECVSTATE;
857
858
859/**
860 * KD context data.
861 */
862typedef struct KDCTX
863{
864 /** Internal debugger console data. */
865 DBGC Dbgc;
866 /** Number of bytes received left for the current state. */
867 size_t cbRecvLeft;
868 /** Pointer where to write the next received data. */
869 uint8_t *pbRecv;
870 /** The current state when receiving a new packet. */
871 KDRECVSTATE enmState;
872 /** The timeout waiting for new data. */
873 RTMSINTERVAL msRecvTimeout;
874 /** Timestamp when we last received data from the remote end. */
875 uint64_t tsRecvLast;
876 /** Packet header being received. */
877 union
878 {
879 KDPACKETHDR Fields;
880 uint8_t ab[16];
881 } PktHdr;
882 /** The next packet ID to send. */
883 uint32_t idPktNext;
884 /** Offset into the body receive buffer. */
885 size_t offBodyRecv;
886 /** Body data. */
887 uint8_t abBody[_4K];
888 /** The trailer byte storage. */
889 uint8_t bTrailer;
890 /** Flag whether a breakin packet was received since the last time it was reset. */
891 bool fBreakinRecv;
892
893 /** Pointer to the OS digger WinNt interface if a matching guest was detected. */
894 PDBGFOSIWINNT pIfWinNt;
895} KDCTX;
896/** Pointer to the KD context data. */
897typedef KDCTX *PKDCTX;
898/** Pointer to const KD context data. */
899typedef const KDCTX *PCKDCTX;
900/** Pointer to a KD context data pointer. */
901typedef PKDCTX *PPKDCTX;
902
903
904/*********************************************************************************************************************************
905* Internal Functions *
906*********************************************************************************************************************************/
907
908
909#ifdef LOG_ENABLED
910/**
911 * Returns a human readable string of the given packet sub type.
912 *
913 * @returns Pointer to sub type string.
914 * @param u16SubType The sub type to convert to a string.
915 */
916static const char *dbgcKdPktDumpSubTypeToStr(uint16_t u16SubType)
917{
918 switch (u16SubType)
919 {
920 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32: return "StateChange32";
921 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE: return "Manipulate";
922 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO: return "DebugIo";
923 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE: return "Ack";
924 case KD_PACKET_HDR_SUB_TYPE_RESEND: return "Resend";
925 case KD_PACKET_HDR_SUB_TYPE_RESET: return "Reset";
926 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64: return "StateChange64";
927 case KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN: return "PollBreakin";
928 case KD_PACKET_HDR_SUB_TYPE_TRACE_IO: return "TraceIo";
929 case KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST: return "ControlRequest";
930 case KD_PACKET_HDR_SUB_TYPE_FILE_IO: return "FileIo";
931 default: break;
932 }
933
934 return "<UNKNOWN>";
935}
936
937
938/**
939 * Returns a human readable string of the given manipulate request ID.
940 *
941 * @returns nothing.
942 * @param idReq Request ID (API number in KD speak).
943 */
944static const char *dbgcKdPktDumpManipulateReqToStr(uint32_t idReq)
945{
946 switch (idReq)
947 {
948 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM: return "ReadVirtMem";
949 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM: return "WriteVirtMem";
950 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT: return "GetContext";
951 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT: return "SetContext";
952 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT: return "WriteBkpt";
953 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT: return "RestoreBkpt";
954 case KD_PACKET_MANIPULATE_REQ_CONTINUE: return "Continue";
955 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE: return "ReadCtrlSpace";
956 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE: return "WriteCtrlSpace";
957 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE: return "ReadIoSpace";
958 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE: return "WriteIoSpace";
959 case KD_PACKET_MANIPULATE_REQ_REBOOT: return "Reboot";
960 case KD_PACKET_MANIPULATE_REQ_CONTINUE2: return "Continue2";
961 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM: return "ReadPhysMem";
962 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM: return "WritePhysMem";
963 case KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS: return "QuerySpecCalls";
964 case KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS: return "SetSpecCalls";
965 case KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS: return "ClrSpecCalls";
966 case KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT: return "SetIntBkpt";
967 case KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT: return "GetIntBkpt";
968 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX: return "ReadIoSpaceEx";
969 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX: return "WriteIoSpaceEx";
970 case KD_PACKET_MANIPULATE_REQ_GET_VERSION: return "GetVersion";
971 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT: return "ClrAllIntBkpt";
972 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX: return "GetContextEx";
973 default: break;
974 }
975
976 return "<UNKNOWN>";
977}
978
979
980/**
981 * Dumps the content of a manipulate packet.
982 *
983 * @returns nothing.
984 * @param pSgBuf S/G buffer containing the manipulate packet payload.
985 */
986static void dbgcKdPktDumpManipulate(PRTSGBUF pSgBuf)
987{
988 KDPACKETMANIPULATEHDR Hdr;
989 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, &Hdr, sizeof(Hdr));
990
991 if (cbCopied == sizeof(Hdr))
992 {
993 const char *pszReq = dbgcKdPktDumpManipulateReqToStr(Hdr.idReq);
994
995 Log3((" MANIPULATE(%#x (%s), %#x, %u, %#x)\n",
996 Hdr.idReq, pszReq, Hdr.u16CpuLvl, Hdr.idCpu, Hdr.u32NtStatus));
997
998 switch (Hdr.idReq)
999 {
1000 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
1001 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
1002 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
1003 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
1004 {
1005 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1006 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferMem64, sizeof(XferMem64));
1007 if (cbCopied == sizeof(XferMem64))
1008 {
1009 Log3((" u64PtrTarget: %RX64\n"
1010 " cbXferReq: %RX32\n"
1011 " cbXfered: %RX32\n",
1012 XferMem64.u64PtrTarget, XferMem64.cbXferReq, XferMem64.cbXfered));
1013 }
1014 else
1015 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferMem64), cbCopied));
1016 break;
1017 }
1018 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
1019 {
1020 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
1021 cbCopied = RTSgBufCopyToBuf(pSgBuf, &RestoreBkpt64, sizeof(RestoreBkpt64));
1022 if (cbCopied == sizeof(RestoreBkpt64))
1023 Log3((" u32HndBkpt: %RX32\n", RestoreBkpt64.u32HndBkpt));
1024 else
1025 Log3((" Payload to small, expected %u, got %zu\n", sizeof(RestoreBkpt64), cbCopied));
1026 break;
1027 }
1028 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
1029 {
1030 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
1031 cbCopied = RTSgBufCopyToBuf(pSgBuf, &WriteBkpt64, sizeof(WriteBkpt64));
1032 if (cbCopied == sizeof(WriteBkpt64))
1033 Log3((" u64PtrBkpt: %RX64\n"
1034 " u32HndBkpt: %RX32\n",
1035 WriteBkpt64.u64PtrBkpt, WriteBkpt64.u32HndBkpt));
1036 else
1037 Log3((" Payload to small, expected %u, got %zu\n", sizeof(WriteBkpt64), cbCopied));
1038 break;
1039 }
1040 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
1041 {
1042 KDPACKETMANIPULATE_CONTINUE Continue;
1043 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1044 if (cbCopied == sizeof(Continue))
1045 Log3((" u32NtContSts: %RX32\n", Continue.u32NtContSts));
1046 else
1047 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1048 break;
1049 }
1050 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
1051 {
1052 KDPACKETMANIPULATE_CONTINUE2 Continue;
1053 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1054 if (cbCopied == sizeof(Continue))
1055 Log3((" u32NtContSts: %RX32\n"
1056 " fTrace: %RX32\n",
1057 Continue.u32NtContSts, Continue.fTrace));
1058 else
1059 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1060 break;
1061 }
1062 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
1063 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
1064 {
1065 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
1066 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferCtrlSpace64, sizeof(XferCtrlSpace64));
1067 if (cbCopied == sizeof(XferCtrlSpace64))
1068 {
1069 Log3((" u64IdXfer: %RX64\n"
1070 " cbXferReq: %RX32\n"
1071 " cbXfered: %RX32\n",
1072 XferCtrlSpace64.u64IdXfer, XferCtrlSpace64.cbXferReq, XferCtrlSpace64.cbXfered));
1073 }
1074 else
1075 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferCtrlSpace64), cbCopied));
1076 break;
1077 }
1078 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
1079 {
1080 KDPACKETMANIPULATE_CONTEXTEX GetContextEx;
1081 cbCopied = RTSgBufCopyToBuf(pSgBuf, &GetContextEx, sizeof(GetContextEx));
1082 if (cbCopied == sizeof(GetContextEx))
1083 {
1084 Log3((" offStart: %RX32\n"
1085 " cbXferReq: %RX32\n"
1086 " cbXfered: %RX32\n",
1087 GetContextEx.offStart, GetContextEx.cbXfer, GetContextEx.cbXfered));
1088 }
1089 else
1090 Log3((" Payload to small, expected %u, got %zu\n", sizeof(GetContextEx), cbCopied));
1091 break;
1092 }
1093 default:
1094 break;
1095 }
1096 }
1097 else
1098 Log3((" MANIPULATE(Header too small, expected %u, got %zu)\n", sizeof(Hdr), cbCopied));
1099}
1100
1101
1102/**
1103 * Dumps the received packet to the debug log.
1104 *
1105 * @returns VBox status code.
1106 * @param pPktHdr The packet header to dump.
1107 * @param fRx Flag whether the packet was received (false indicates an outgoing packet).
1108 */
1109static void dbgcKdPktDump(PCKDPACKETHDR pPktHdr, PCRTSGSEG paSegs, uint32_t cSegs, bool fRx)
1110{
1111 RTSGBUF SgBuf;
1112
1113 RTSgBufInit(&SgBuf, paSegs, cSegs);
1114
1115 Log3(("%s KDPKTHDR(%#x, %#x (%s), %u, %#x, %#x)\n",
1116 fRx ? "=>" : "<=",
1117 pPktHdr->u32Signature, pPktHdr->u16SubType, dbgcKdPktDumpSubTypeToStr(pPktHdr->u16SubType),
1118 pPktHdr->cbBody, pPktHdr->idPacket, pPktHdr->u32ChkSum));
1119 switch (pPktHdr->u16SubType)
1120 {
1121 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
1122 dbgcKdPktDumpManipulate(&SgBuf);
1123 break;
1124 default:
1125 break;
1126 }
1127}
1128#endif
1129
1130
1131/**
1132 * Wrapper for the I/O interface write callback.
1133 *
1134 * @returns Status code.
1135 * @param pThis The KD context.
1136 * @param pvPkt The packet data to send.
1137 * @param cbPkt Size of the packet in bytes.
1138 */
1139DECLINLINE(int) dbgcKdCtxWrite(PKDCTX pThis, const void *pvPkt, size_t cbPkt)
1140{
1141 return pThis->Dbgc.pBack->pfnWrite(pThis->Dbgc.pBack, pvPkt, cbPkt, NULL /*pcbWritten*/);
1142}
1143
1144
1145/**
1146 * Fills in the given 64bit NT context structure with the requested values.
1147 *
1148 * @returns VBox status code.
1149 * @param pThis The KD context.
1150 * @param idCpu The CPU to query the context for.
1151 * @param pNtCtx The NT context structure to fill in.
1152 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1153 */
1154static int dbgcKdCtxQueryNtCtx64(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1155{
1156 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1157
1158 pNtCtx->fContext = NTCONTEXT_F_AMD64;
1159 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pNtCtx->u32RegMxCsr);
1160
1161 if ( RT_SUCCESS(rc)
1162 && fCtxFlags & NTCONTEXT_F_CONTROL)
1163 {
1164 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u16SegCs);
1165 if (RT_SUCCESS(rc))
1166 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u16SegSs);
1167 if (RT_SUCCESS(rc))
1168 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RIP, &pNtCtx->u64RegRip);
1169 if (RT_SUCCESS(rc))
1170 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSP, &pNtCtx->u64RegRsp);
1171 if (RT_SUCCESS(rc))
1172 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBP, &pNtCtx->u64RegRbp);
1173 if (RT_SUCCESS(rc))
1174 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1175 if (RT_SUCCESS(rc))
1176 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1177 }
1178
1179 if ( RT_SUCCESS(rc)
1180 && fCtxFlags & NTCONTEXT_F_INTEGER)
1181 {
1182 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RAX, &pNtCtx->u64RegRax);
1183 if (RT_SUCCESS(rc))
1184 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RCX, &pNtCtx->u64RegRcx);
1185 if (RT_SUCCESS(rc))
1186 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDX, &pNtCtx->u64RegRdx);
1187 if (RT_SUCCESS(rc))
1188 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBX, &pNtCtx->u64RegRbx);
1189 if (RT_SUCCESS(rc))
1190 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSI, &pNtCtx->u64RegRsi);
1191 if (RT_SUCCESS(rc))
1192 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDI, &pNtCtx->u64RegRdi);
1193 if (RT_SUCCESS(rc))
1194 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R8, &pNtCtx->u64RegR8);
1195 if (RT_SUCCESS(rc))
1196 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R9, &pNtCtx->u64RegR9);
1197 if (RT_SUCCESS(rc))
1198 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R10, &pNtCtx->u64RegR10);
1199 if (RT_SUCCESS(rc))
1200 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R11, &pNtCtx->u64RegR11);
1201 if (RT_SUCCESS(rc))
1202 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R12, &pNtCtx->u64RegR12);
1203 if (RT_SUCCESS(rc))
1204 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R13, &pNtCtx->u64RegR13);
1205 if (RT_SUCCESS(rc))
1206 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R14, &pNtCtx->u64RegR14);
1207 if (RT_SUCCESS(rc))
1208 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R15, &pNtCtx->u64RegR15);
1209 if (RT_SUCCESS(rc))
1210 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1211 }
1212
1213 if ( RT_SUCCESS(rc)
1214 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1215 {
1216 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u16SegDs);
1217 if (RT_SUCCESS(rc))
1218 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u16SegEs);
1219 if (RT_SUCCESS(rc))
1220 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u16SegFs);
1221 if (RT_SUCCESS(rc))
1222 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u16SegGs);
1223 if (RT_SUCCESS(rc))
1224 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1225 }
1226
1227 if ( RT_SUCCESS(rc)
1228 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1229 {
1230 /** @todo. */
1231 }
1232
1233 if ( RT_SUCCESS(rc)
1234 && fCtxFlags & NTCONTEXT_F_DEBUG)
1235 {
1236 /** @todo. */
1237 }
1238
1239 return rc;
1240}
1241
1242
1243#define KD_REG_INIT(a_pszName, a_enmType, a_ValMember, a_Val) \
1244 do \
1245 { \
1246 aRegsSet[idxReg].pszName = a_pszName; \
1247 aRegsSet[idxReg].enmType = a_enmType; \
1248 aRegsSet[idxReg].Val.a_ValMember = a_Val; \
1249 idxReg++; \
1250 } while (0)
1251#define KD_REG_INIT_DTR(a_pszName, a_Base, a_Limit) \
1252 do \
1253 { \
1254 aRegsSet[idxReg].pszName = a_pszName; \
1255 aRegsSet[idxReg].enmType = DBGFREGVALTYPE_DTR; \
1256 aRegsSet[idxReg].Val.dtr.u64Base = a_Base; \
1257 aRegsSet[idxReg].Val.dtr.u32Limit = a_Limit; \
1258 idxReg++; \
1259 } while (0)
1260#define KD_REG_INIT_U16(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U16, u16, a_Val)
1261#define KD_REG_INIT_U32(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U32, u32, a_Val)
1262#define KD_REG_INIT_U64(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U64, u64, a_Val)
1263
1264
1265/**
1266 * Writes the indicated values from the given context structure to the guests register set.
1267 *
1268 * @returns VBox status code.
1269 * @param pThis The KD context.
1270 * @param idCpu The CPU to query the context for.
1271 * @param pNtCtx The NT context structure to set.
1272 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to set.
1273 */
1274static int dbgcKdCtxSetNtCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1275{
1276 uint32_t idxReg = 0;
1277 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1278
1279 KD_REG_INIT_U32("mxcsr", pNtCtx->u32RegMxCsr);
1280
1281 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1282 {
1283#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1284 KD_REG_INIT_U16("cs", pNtCtx->u16SegCs);
1285 KD_REG_INIT_U16("ss", pNtCtx->u16SegSs);
1286#endif
1287 KD_REG_INIT_U64("rip", pNtCtx->u64RegRip);
1288 KD_REG_INIT_U64("rsp", pNtCtx->u64RegRsp);
1289 KD_REG_INIT_U64("rbp", pNtCtx->u64RegRbp);
1290 KD_REG_INIT_U32("rflags", pNtCtx->u32RegEflags);
1291 }
1292
1293 if (fCtxFlags & NTCONTEXT_F_INTEGER)
1294 {
1295 KD_REG_INIT_U64("rax", pNtCtx->u64RegRax);
1296 KD_REG_INIT_U64("rcx", pNtCtx->u64RegRcx);
1297 KD_REG_INIT_U64("rdx", pNtCtx->u64RegRdx);
1298 KD_REG_INIT_U64("rbx", pNtCtx->u64RegRbx);
1299 KD_REG_INIT_U64("rsi", pNtCtx->u64RegRsi);
1300 KD_REG_INIT_U64("rdi", pNtCtx->u64RegRdi);
1301 KD_REG_INIT_U64("r8", pNtCtx->u64RegR8);
1302 KD_REG_INIT_U64("r9", pNtCtx->u64RegR9);
1303 KD_REG_INIT_U64("r10", pNtCtx->u64RegR10);
1304 KD_REG_INIT_U64("r11", pNtCtx->u64RegR11);
1305 KD_REG_INIT_U64("r12", pNtCtx->u64RegR12);
1306 KD_REG_INIT_U64("r13", pNtCtx->u64RegR13);
1307 KD_REG_INIT_U64("r14", pNtCtx->u64RegR14);
1308 KD_REG_INIT_U64("r15", pNtCtx->u64RegR15);
1309 }
1310
1311 if (fCtxFlags & NTCONTEXT_F_SEGMENTS)
1312 {
1313#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1314 KD_REG_INIT_U16("ds", pNtCtx->u16SegDs);
1315 KD_REG_INIT_U16("es", pNtCtx->u16SegEs);
1316 KD_REG_INIT_U16("fs", pNtCtx->u16SegFs);
1317 KD_REG_INIT_U16("gs", pNtCtx->u16SegGs);
1318#endif
1319 }
1320
1321 if (fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1322 {
1323 /** @todo. */
1324 }
1325
1326 if (fCtxFlags & NTCONTEXT_F_DEBUG)
1327 {
1328 /** @todo. */
1329 }
1330
1331 return DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
1332}
1333
1334
1335/**
1336 * Fills in the given 64bit NT kernel context structure with the requested values.
1337 *
1338 * @returns VBox status code.
1339 * @param pThis The KD context.
1340 * @param idCpu The CPU to query the context for.
1341 * @param pKNtCtx The NT context structure to fill in.
1342 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1343 */
1344static int dbgcKdCtxQueryNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT64 pKNtCtx, uint32_t fCtxFlags)
1345{
1346 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
1347
1348 int rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u64RegCr0);
1349 if (RT_SUCCESS(rc))
1350 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u64RegCr2);
1351 if (RT_SUCCESS(rc))
1352 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u64RegCr3);
1353 if (RT_SUCCESS(rc))
1354 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u64RegCr4);
1355 if (RT_SUCCESS(rc))
1356 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR8, &pKNtCtx->u64RegCr8);
1357 if (RT_SUCCESS(rc))
1358 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pKNtCtx->u64RegDr0);
1359 if (RT_SUCCESS(rc))
1360 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pKNtCtx->u64RegDr1);
1361 if (RT_SUCCESS(rc))
1362 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR2, &pKNtCtx->u64RegDr2);
1363 if (RT_SUCCESS(rc))
1364 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pKNtCtx->u64RegDr3);
1365 if (RT_SUCCESS(rc))
1366 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pKNtCtx->u64RegDr6);
1367 if (RT_SUCCESS(rc))
1368 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pKNtCtx->u64RegDr7);
1369 if (RT_SUCCESS(rc))
1370 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
1371 if (RT_SUCCESS(rc))
1372 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u64PtrBase);
1373 if (RT_SUCCESS(rc))
1374 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
1375 if (RT_SUCCESS(rc))
1376 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u64PtrBase);
1377 if (RT_SUCCESS(rc))
1378 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
1379 if (RT_SUCCESS(rc))
1380 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
1381 if (RT_SUCCESS(rc))
1382 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pKNtCtx->u32RegMxCsr);
1383 /** @todo Debug control and stuff. */
1384
1385 if (RT_SUCCESS(rc))
1386 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_GS_BASE, &pKNtCtx->u64MsrGsBase);
1387 if (RT_SUCCESS(rc))
1388 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_KERNEL_GS_BASE, &pKNtCtx->u64MsrKernelGsBase);
1389 if (RT_SUCCESS(rc))
1390 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K6_STAR, &pKNtCtx->u64MsrStar);
1391 if (RT_SUCCESS(rc))
1392 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_LSTAR, &pKNtCtx->u64MsrLstar);
1393 if (RT_SUCCESS(rc))
1394 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_CSTAR, &pKNtCtx->u64MsrCstar);
1395 if (RT_SUCCESS(rc))
1396 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_SF_MASK, &pKNtCtx->u64MsrSfMask);
1397 /** @todo XCR0 */
1398
1399 if (RT_SUCCESS(rc))
1400 rc = dbgcKdCtxQueryNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, fCtxFlags);
1401
1402 return rc;
1403}
1404
1405
1406/**
1407 * Fills in the given 64bit NT kernel context structure with the requested values.
1408 *
1409 * @returns VBox status code.
1410 * @param pThis The KD context.
1411 * @param idCpu The CPU to query the context for.
1412 * @param pKNtCtx The NT context structure to fill in.
1413 * @param cbSet How many bytes of the context are valid.
1414 */
1415static int dbgcKdCtxSetNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTKCONTEXT64 pKNtCtx, size_t cbSet)
1416{
1417 AssertReturn(cbSet >= RT_UOFFSETOF(NTKCONTEXT64, Ctx), VERR_INVALID_PARAMETER);
1418
1419 uint32_t idxReg = 0;
1420 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1421
1422 KD_REG_INIT_U64("cr0", pKNtCtx->u64RegCr0);
1423 KD_REG_INIT_U64("cr2", pKNtCtx->u64RegCr2);
1424 KD_REG_INIT_U64("cr3", pKNtCtx->u64RegCr3);
1425 KD_REG_INIT_U64("cr4", pKNtCtx->u64RegCr4);
1426 KD_REG_INIT_U64("cr8", pKNtCtx->u64RegCr8);
1427 KD_REG_INIT_U64("dr0", pKNtCtx->u64RegDr0);
1428 KD_REG_INIT_U64("dr1", pKNtCtx->u64RegDr1);
1429 KD_REG_INIT_U64("dr2", pKNtCtx->u64RegDr2);
1430 KD_REG_INIT_U64("dr3", pKNtCtx->u64RegDr3);
1431 KD_REG_INIT_U64("dr6", pKNtCtx->u64RegDr6);
1432 KD_REG_INIT_U64("dr7", pKNtCtx->u64RegDr7);
1433
1434 KD_REG_INIT_DTR("gdtr", pKNtCtx->Gdtr.u64PtrBase, pKNtCtx->Gdtr.u16Limit);
1435 KD_REG_INIT_DTR("idtr", pKNtCtx->Idtr.u64PtrBase, pKNtCtx->Idtr.u16Limit);
1436
1437#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1438 KD_REG_INIT_U16("tr", pKNtCtx->u16RegTr);
1439 KD_REG_INIT_U16("ldtr", pKNtCtx->u16RegLdtr);
1440#endif
1441 KD_REG_INIT_U32("mxcsr", pKNtCtx->u32RegMxCsr);
1442
1443 KD_REG_INIT_U64("msr_gs_base", pKNtCtx->u64MsrGsBase);
1444 KD_REG_INIT_U64("krnl_gs_base", pKNtCtx->u64MsrKernelGsBase);
1445 KD_REG_INIT_U64("star", pKNtCtx->u64MsrStar);
1446 KD_REG_INIT_U64("lstar", pKNtCtx->u64MsrLstar);
1447 KD_REG_INIT_U64("cstar", pKNtCtx->u64MsrCstar);
1448 KD_REG_INIT_U64("sf_mask", pKNtCtx->u64MsrSfMask);
1449
1450 int rc = DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
1451 if ( RT_SUCCESS(rc)
1452 && cbSet > RT_UOFFSETOF(NTKCONTEXT64, Ctx)) /** @todo Probably wrong. */
1453 rc = dbgcKdCtxSetNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, pKNtCtx->Ctx.fContext);
1454
1455 return rc;
1456}
1457
1458#undef KD_REG_INIT_64
1459#undef KD_REG_INIT_32
1460#undef KD_REG_INIT_16
1461#undef KD_REG_INIT_DTR
1462#undef KD_REG_INIT
1463
1464
1465/**
1466 * Validates the given KD packet header.
1467 *
1468 * @returns Flag whether the packet header is valid, false if invalid.
1469 * @param pPktHdr The packet header to validate.
1470 */
1471static bool dbgcKdPktHdrValidate(PCKDPACKETHDR pPktHdr)
1472{
1473 if ( pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_DATA
1474 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_CONTROL
1475 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_BREAKIN)
1476 return false;
1477
1478 if (pPktHdr->u16SubType >= KD_PACKET_HDR_SUB_TYPE_MAX)
1479 return false;
1480
1481 uint32_t idPacket = pPktHdr->idPacket & UINT32_C(0xfffffffe);
1482 if ( idPacket != KD_PACKET_HDR_ID_INITIAL
1483 && idPacket != KD_PACKET_HDR_ID_RESET
1484 && idPacket != 0 /* Happens on the very first packet */)
1485 return false;
1486
1487 return true;
1488}
1489
1490
1491/**
1492 * Generates a checksum from the given buffer.
1493 *
1494 * @returns Generated checksum.
1495 * @param pv The data to generate a checksum from.
1496 * @param cb Number of bytes to checksum.
1497 */
1498static uint32_t dbgcKdPktChkSumGen(const void *pv, size_t cb)
1499{
1500 const uint8_t *pb = (const uint8_t *)pv;
1501 uint32_t u32ChkSum = 0;
1502
1503 while (cb--)
1504 u32ChkSum += *pb++;
1505
1506 return u32ChkSum;
1507}
1508
1509
1510/**
1511 * Generates a checksum from the given segments.
1512 *
1513 * @returns Generated checksum.
1514 * @param paSegs Pointer to the array of segments containing the data.
1515 * @param cSegs Number of segments.
1516 * @param pcbChkSum Where to store the number of bytes checksummed, optional.
1517 */
1518static uint32_t dbgcKdPktChkSumGenSg(PCRTSGSEG paSegs, uint32_t cSegs, size_t *pcbChkSum)
1519{
1520 size_t cbChkSum = 0;
1521 uint32_t u32ChkSum = 0;
1522
1523 for (uint32_t i = 0; i < cSegs; i++)
1524 {
1525 u32ChkSum += dbgcKdPktChkSumGen(paSegs[i].pvSeg, paSegs[i].cbSeg);
1526 cbChkSum += paSegs[i].cbSeg;
1527 }
1528
1529 if (pcbChkSum)
1530 *pcbChkSum = cbChkSum;
1531
1532 return u32ChkSum;
1533}
1534
1535
1536/**
1537 * Waits for an acknowledgment.
1538 *
1539 * @returns VBox status code.
1540 * @param pThis The KD context.
1541 * @param msWait Maximum number of milliseconds to wait for an acknowledge.
1542 * @param pfResend Where to store the resend requested flag on success.
1543 */
1544static int dbgcKdCtxPktWaitForAck(PKDCTX pThis, RTMSINTERVAL msWait, bool *pfResend)
1545{
1546 KDPACKETHDR PktAck;
1547 uint8_t *pbCur = (uint8_t *)&PktAck;
1548 size_t cbLeft = sizeof(PktAck);
1549 uint64_t tsStartMs = RTTimeMilliTS();
1550 int rc = VINF_SUCCESS;
1551
1552 LogFlowFunc(("pThis=%p msWait=%u pfResend=%p\n", pThis, msWait, pfResend));
1553
1554 RT_ZERO(PktAck);
1555
1556 /* There might be breakin packets in the queue, read until we get something else. */
1557 while ( msWait
1558 && RT_SUCCESS(rc))
1559 {
1560 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
1561 {
1562 size_t cbRead = 0;
1563 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, 1, &cbRead);
1564 if ( RT_SUCCESS(rc)
1565 && cbRead == 1)
1566 {
1567 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
1568 msWait -= RT_MIN(msWait, tsSpanMs);
1569 tsStartMs = RTTimeMilliTS();
1570
1571 if (*pbCur == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
1572 pThis->fBreakinRecv = true;
1573 else
1574 {
1575 pbCur++;
1576 cbLeft--;
1577 break;
1578 }
1579 }
1580 }
1581 else
1582 rc = VERR_TIMEOUT;
1583 }
1584
1585 if ( RT_SUCCESS(rc)
1586 && !msWait)
1587 rc = VERR_TIMEOUT;
1588
1589 if (RT_SUCCESS(rc))
1590 {
1591 while ( msWait
1592 && RT_SUCCESS(rc)
1593 && cbLeft)
1594 {
1595 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
1596 {
1597 size_t cbRead = 0;
1598 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, cbLeft, &cbRead);
1599 if (RT_SUCCESS(rc))
1600 {
1601 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
1602 msWait -= RT_MIN(msWait, tsSpanMs);
1603 tsStartMs = RTTimeMilliTS();
1604
1605 cbLeft -= cbRead;
1606 pbCur += cbRead;
1607 }
1608 }
1609 else
1610 rc = VERR_TIMEOUT;
1611 }
1612
1613 if (RT_SUCCESS(rc))
1614 {
1615 if (PktAck.u32Signature == KD_PACKET_HDR_SIGNATURE_CONTROL)
1616 {
1617 if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE)
1618 rc = VINF_SUCCESS;
1619 else if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_RESEND)
1620 {
1621 *pfResend = true;
1622 rc = VINF_SUCCESS;
1623 }
1624 else
1625 rc = VERR_NET_PROTOCOL_ERROR;
1626 }
1627 else
1628 rc = VERR_NET_PROTOCOL_ERROR;
1629 }
1630 }
1631
1632 LogFlowFunc(("returns rc=%Rrc *pfResend=%RTbool\n", rc, *pfResend));
1633 return rc;
1634}
1635
1636
1637/**
1638 * Sends the given packet header and optional segmented body (the trailing byte is sent automatically).
1639 *
1640 * @returns VBox status code.
1641 * @param pThis The KD context.
1642 * @param u32Signature The signature to send.
1643 * @param u16SubType The sub type to send.
1644 * @param paSegs Pointer to the array of segments to send in the body, optional.
1645 * @param cSegs Number of segments.
1646 * @param fAck Flag whether to wait for an acknowledge.
1647 */
1648static int dbgcKdCtxPktSendSg(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
1649 PCRTSGSEG paSegs, uint32_t cSegs, bool fAck)
1650{
1651 int rc = VINF_SUCCESS;
1652 uint32_t cRetriesLeft = 3;
1653 uint8_t bTrailer = KD_PACKET_TRAILING_BYTE;
1654 KDPACKETHDR Hdr;
1655
1656 size_t cbChkSum = 0;
1657 uint32_t u32ChkSum = dbgcKdPktChkSumGenSg(paSegs, cSegs, &cbChkSum);
1658
1659 Hdr.u32Signature = u32Signature;
1660 Hdr.u16SubType = u16SubType;
1661 Hdr.cbBody = (uint16_t)cbChkSum;
1662 Hdr.idPacket = pThis->idPktNext;
1663 Hdr.u32ChkSum = u32ChkSum;
1664
1665#ifdef LOG_ENABLED
1666 dbgcKdPktDump(&Hdr, paSegs, cSegs, false /*fRx*/);
1667#endif
1668
1669 while (cRetriesLeft--)
1670 {
1671 bool fResend = false;
1672
1673 rc = dbgcKdCtxWrite(pThis, &Hdr, sizeof(Hdr));
1674 if ( RT_SUCCESS(rc)
1675 && paSegs
1676 && cSegs)
1677 {
1678 for (uint32_t i = 0; i < cSegs && RT_SUCCESS(rc); i++)
1679 rc = dbgcKdCtxWrite(pThis, paSegs[i].pvSeg, paSegs[i].cbSeg);
1680
1681 if (RT_SUCCESS(rc))
1682 rc = dbgcKdCtxWrite(pThis, &bTrailer, sizeof(bTrailer));
1683 }
1684
1685 if (RT_SUCCESS(rc))
1686 {
1687 if (fAck)
1688 rc = dbgcKdCtxPktWaitForAck(pThis, 10 * 1000, &fResend);
1689
1690 if ( RT_SUCCESS(rc)
1691 && !fResend)
1692 break;
1693 }
1694 }
1695
1696 return rc;
1697}
1698
1699
1700/**
1701 * Sends the given packet header and optional body (the trailing byte is sent automatically).
1702 *
1703 * @returns VBox status code.
1704 * @param pThis The KD context.
1705 * @param u32Signature The signature to send.
1706 * @param u16SubType The sub type to send.
1707 * @param pvBody The body to send, optional.
1708 * @param cbBody Body size in bytes.
1709 * @param fAck Flag whether to wait for an acknowledge.
1710 */
1711DECLINLINE(int) dbgcKdCtxPktSend(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
1712 const void *pvBody, size_t cbBody,
1713 bool fAck)
1714{
1715 RTSGSEG Seg;
1716
1717 Seg.pvSeg = (void *)pvBody;
1718 Seg.cbSeg = cbBody;
1719 return dbgcKdCtxPktSendSg(pThis, u32Signature, u16SubType, cbBody ? &Seg : NULL, cbBody ? 1 : 0, fAck);
1720}
1721
1722
1723/**
1724 * Sends a resend packet answer.
1725 *
1726 * @returns VBox status code.
1727 * @param pThis The KD context.
1728 */
1729DECLINLINE(int) dbgcKdCtxPktSendResend(PKDCTX pThis)
1730{
1731 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESEND,
1732 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
1733}
1734
1735
1736/**
1737 * Sends a resend packet answer.
1738 *
1739 * @returns VBox status code.
1740 * @param pThis The KD context.
1741 */
1742DECLINLINE(int) dbgcKdCtxPktSendReset(PKDCTX pThis)
1743{
1744 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
1745 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESET,
1746 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
1747}
1748
1749
1750/**
1751 * Sends an acknowledge packet answer.
1752 *
1753 * @returns VBox status code.
1754 * @param pThis The KD context.
1755 */
1756DECLINLINE(int) dbgcKdCtxPktSendAck(PKDCTX pThis)
1757{
1758 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE,
1759 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
1760}
1761
1762
1763/**
1764 * Resets the packet receive state machine.
1765 *
1766 * @returns nothing.
1767 * @param pThis The KD context.
1768 */
1769static void dbgcKdCtxPktRecvReset(PKDCTX pThis)
1770{
1771 pThis->enmState = KDRECVSTATE_PACKET_HDR_FIRST_BYTE;
1772 pThis->pbRecv = &pThis->PktHdr.ab[0];
1773 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[0]);
1774 pThis->msRecvTimeout = RT_INDEFINITE_WAIT;
1775 pThis->tsRecvLast = RTTimeMilliTS();
1776}
1777
1778
1779/**
1780 * Sends a state change event packet.
1781 *
1782 * @returns VBox status code.
1783 * @param pThis The KD context data.
1784 * @param enmType The event type.
1785 */
1786static int dbgcKdCtxStateChangeSend(PKDCTX pThis, DBGFEVENTTYPE enmType)
1787{
1788 LogFlowFunc(("pThis=%p enmType=%u\n", pThis, enmType));
1789
1790 /* Select the record to send based on the CPU mode. */
1791 int rc = VINF_SUCCESS;
1792 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
1793 switch (enmMode)
1794 {
1795 case CPUMMODE_PROTECTED:
1796 {
1797 break;
1798 }
1799 case CPUMMODE_LONG:
1800 {
1801 KDPACKETSTATECHANGE64 StateChange64;
1802 RT_ZERO(StateChange64);
1803
1804 StateChange64.u32StateNew = KD_PACKET_STATE_CHANGE_EXCEPTION;
1805 StateChange64.u16CpuLvl = 0x6; /** @todo Figure this one out. */
1806 StateChange64.idCpu = pThis->Dbgc.idCpu;
1807 StateChange64.cCpus = (uint16_t)DBGFR3CpuGetCount(pThis->Dbgc.pUVM);
1808 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RIP, &StateChange64.u64RipThread);
1809 if (RT_SUCCESS(rc))
1810 {
1811 /** @todo Properly fill in the exception record. */
1812 switch (enmType)
1813 {
1814 case DBGFEVENT_HALT_DONE:
1815 case DBGFEVENT_BREAKPOINT:
1816 case DBGFEVENT_BREAKPOINT_IO:
1817 case DBGFEVENT_BREAKPOINT_MMIO:
1818 case DBGFEVENT_BREAKPOINT_HYPER:
1819 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_BKPT;
1820 break;
1821 case DBGFEVENT_STEPPED:
1822 case DBGFEVENT_STEPPED_HYPER:
1823 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_SINGLE_STEP;
1824 break;
1825 default:
1826 AssertMsgFailed(("Invalid DBGF event type for state change %d!\n", enmType));
1827 }
1828
1829 StateChange64.u.Exception.ExcpRec.cExcpParms = 3;
1830 StateChange64.u.Exception.u32FirstChance = 0x1;
1831
1832 /** @todo Properly fill in the control report. */
1833 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR6, &StateChange64.uCtrlReport.Amd64.u64RegDr6);
1834 if (RT_SUCCESS(rc))
1835 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR7, &StateChange64.uCtrlReport.Amd64.u64RegDr7);
1836 if (RT_SUCCESS(rc))
1837 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RFLAGS, &StateChange64.uCtrlReport.Amd64.u32RegEflags);
1838 if (RT_SUCCESS(rc))
1839 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_CS, &StateChange64.uCtrlReport.Amd64.u16SegCs);
1840 if (RT_SUCCESS(rc))
1841 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DS, &StateChange64.uCtrlReport.Amd64.u16SegDs);
1842 if (RT_SUCCESS(rc))
1843 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_ES, &StateChange64.uCtrlReport.Amd64.u16SegEs);
1844 if (RT_SUCCESS(rc))
1845 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_FS, &StateChange64.uCtrlReport.Amd64.u16SegFs);
1846
1847 /* Read instruction bytes. */
1848 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
1849 DBGFADDRESS AddrRip;
1850 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRip, StateChange64.u64RipThread);
1851 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
1852 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
1853 if (RT_SUCCESS(rc))
1854 {
1855 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
1856 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
1857 &StateChange64, sizeof(StateChange64), false /*fAck*/);
1858 }
1859 }
1860 break;
1861 }
1862 case CPUMMODE_REAL:
1863 default:
1864 return DBGCCmdHlpPrintf(&pThis->Dbgc.CmdHlp, "error: Invalid CPU mode %d.\n", enmMode);
1865 }
1866
1867 LogFlowFunc(("returns %Rrc\n", rc));
1868 return rc;
1869}
1870
1871
1872/**
1873 * Processes a get version 64 request.
1874 *
1875 * @returns VBox status code.
1876 * @param pThis The KD context.
1877 * @param pPktManip The manipulate packet request.
1878 */
1879static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
1880{
1881 KDPACKETMANIPULATE64 Resp;
1882 RT_ZERO(Resp);
1883
1884 /* Fill in the generic part. */
1885 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
1886 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
1887 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
1888 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
1889
1890#if 0
1891 /* Build our own response in case there is no Windows interface available. */
1892 if (pThis->pIfWinNt)
1893 {
1894 RTGCUINTPTR GCPtrKpcr = 0;
1895
1896 int rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, Resp.Hdr.idCpu,
1897 &GCPtrKpcr, NULL /*pKpcrb*/);
1898 if (RT_SUCCESS(rc))
1899 {
1900 DBGFADDRESS AddrKdVersionBlock;
1901 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrKdVersionBlock, GCPtrKpcr + 0x108);
1902 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, Resp.Hdr.idCpu, &AddrKdVersionBlock, &Resp.u.GetVersion, sizeof(Resp.u.GetVersion));
1903 }
1904 }
1905 else
1906#endif
1907 {
1908 /* Fill in the request specific part, the static parts are from an amd64 Windows 10 guest. */
1909 Resp.u.GetVersion.u16VersMaj = 0x0f;
1910 Resp.u.GetVersion.u16VersMin = 0x2800;
1911 Resp.u.GetVersion.u8VersProtocol = 0x6; /** From a Windows 10 guest. */
1912 Resp.u.GetVersion.u8VersKdSecondary = 0x2; /** From a Windows 10 guest. */
1913 Resp.u.GetVersion.fFlags = 0x5; /** 64bit pointer. */
1914 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
1915 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
1916 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
1917 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT - KD_PACKET_MANIPULATE_REQ_MIN;
1918 Resp.u.GetVersion.u64PtrDebuggerDataList = 0 ;//0xfffff800deadc0de;
1919 }
1920
1921 /* Try to fill in the rest using the OS digger interface if available. */
1922 int rc = VINF_SUCCESS;
1923 if (pThis->pIfWinNt)
1924 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, &Resp.u.GetVersion.u64PtrKernBase,
1925 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
1926 else
1927 {
1928 /** @todo */
1929 }
1930
1931 if (RT_SUCCESS(rc))
1932 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
1933 &Resp, sizeof(Resp), true /*fAck*/);
1934
1935 return rc;
1936}
1937
1938
1939/**
1940 * Processes a read memory 64 request.
1941 *
1942 * @returns VBox status code.
1943 * @param pThis The KD context.
1944 * @param pPktManip The manipulate packet request.
1945 */
1946static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
1947{
1948 KDPACKETMANIPULATEHDR RespHdr;
1949 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1950 uint8_t abMem[_4K];
1951 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
1952
1953 DBGFADDRESS AddrRead;
1954 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
1955 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
1956 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, pPktManip->u.XferMem.u64PtrTarget);
1957 else
1958 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, pPktManip->u.XferMem.u64PtrTarget);
1959
1960 RTSGSEG aRespSegs[3];
1961 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
1962 RespHdr.idReq = pPktManip->Hdr.idReq;
1963 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
1964 RespHdr.idCpu = pPktManip->Hdr.idCpu;
1965 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
1966
1967 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
1968 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
1969 XferMem64.cbXfered = (uint32_t)cbRead;
1970
1971 aRespSegs[0].pvSeg = &RespHdr;
1972 aRespSegs[0].cbSeg = sizeof(RespHdr);
1973 aRespSegs[1].pvSeg = &XferMem64;
1974 aRespSegs[1].cbSeg = sizeof(XferMem64);
1975
1976 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
1977 if (RT_SUCCESS(rc))
1978 {
1979 cSegs++;
1980 aRespSegs[2].pvSeg = &abMem[0];
1981 aRespSegs[2].cbSeg = cbRead;
1982 }
1983 else
1984 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
1985
1986 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
1987 &aRespSegs[0], cSegs, true /*fAck*/);
1988}
1989
1990
1991/**
1992 * Processes a write memory 64 request.
1993 *
1994 * @returns VBox status code.
1995 * @param pThis The KD context.
1996 * @param pPktManip The manipulate packet request.
1997 */
1998static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
1999{
2000 KDPACKETMANIPULATEHDR RespHdr;
2001 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2002 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2003
2004 DBGFADDRESS AddrWrite;
2005 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2006 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
2007 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
2008 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, pPktManip->u.XferMem.u64PtrTarget);
2009 else
2010 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, pPktManip->u.XferMem.u64PtrTarget);
2011
2012 RTSGSEG aRespSegs[2];
2013 uint32_t cSegs = 2;
2014 RespHdr.idReq = pPktManip->Hdr.idReq;
2015 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2016 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2017 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2018
2019 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2020 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2021 XferMem64.cbXfered = (uint32_t)cbWrite;
2022
2023 aRespSegs[0].pvSeg = &RespHdr;
2024 aRespSegs[0].cbSeg = sizeof(RespHdr);
2025 aRespSegs[1].pvSeg = &XferMem64;
2026 aRespSegs[1].cbSeg = sizeof(XferMem64);
2027
2028 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
2029 if (RT_FAILURE(rc))
2030 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2031
2032 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2033 &aRespSegs[0], cSegs, true /*fAck*/);
2034}
2035
2036
2037/**
2038 * Processes a continue request.
2039 *
2040 * @returns VBox status code.
2041 * @param pThis The KD context.
2042 * @param pPktManip The manipulate packet request.
2043 */
2044static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2045{
2046 RT_NOREF(pPktManip);
2047 int rc = VINF_SUCCESS;
2048
2049 /* No response, just resume. */
2050 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2051 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2052
2053 return rc;
2054}
2055
2056
2057/**
2058 * Processes a continue request.
2059 *
2060 * @returns VBox status code.
2061 * @param pThis The KD context.
2062 * @param pPktManip The manipulate packet request.
2063 */
2064static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2065{
2066 int rc = VINF_SUCCESS;
2067
2068 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
2069 if (pPktManip->u.Continue2.fTrace)
2070 {
2071 PDBGFADDRESS pStackPop = NULL;
2072 RTGCPTR cbStackPop = 0;
2073 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
2074 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
2075 }
2076 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2077 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2078
2079 return rc;
2080}
2081
2082
2083/**
2084 * Processes a set context request.
2085 *
2086 * @returns VBox status code.
2087 * @param pThis The KD context.
2088 * @param pPktManip The manipulate packet request.
2089 */
2090static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2091{
2092 KDPACKETMANIPULATEHDR RespHdr;
2093 KDPACKETMANIPULATE_SETCONTEXT SetContext;
2094 RT_ZERO(RespHdr); RT_ZERO(SetContext);
2095
2096 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2097
2098 RTSGSEG aRespSegs[2];
2099 uint32_t cSegs = 2;
2100 RespHdr.idReq = pPktManip->Hdr.idReq;
2101 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2102 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2103 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2104
2105 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
2106
2107 aRespSegs[0].pvSeg = &RespHdr;
2108 aRespSegs[0].cbSeg = sizeof(RespHdr);
2109 aRespSegs[1].pvSeg = &SetContext;
2110 aRespSegs[1].cbSeg = sizeof(SetContext);
2111
2112 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, SetContext.u32CtxFlags);
2113 if (RT_FAILURE(rc))
2114 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2115
2116 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2117 &aRespSegs[0], cSegs, true /*fAck*/);
2118}
2119
2120
2121/**
2122 * Processes a read control space 64 request.
2123 *
2124 * @returns VBox status code.
2125 * @param pThis The KD context.
2126 * @param pPktManip The manipulate packet request.
2127 */
2128static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2129{
2130 KDPACKETMANIPULATEHDR RespHdr;
2131 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2132 uint8_t abResp[sizeof(NTKCONTEXT64)];
2133 uint32_t cbData = 0;
2134 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2135 RT_ZERO(abResp);
2136
2137 RTSGSEG aRespSegs[3];
2138 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2139 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
2140 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2141 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2142 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2143
2144 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
2145 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
2146
2147 aRespSegs[0].pvSeg = &RespHdr;
2148 aRespSegs[0].cbSeg = sizeof(RespHdr);
2149 aRespSegs[1].pvSeg = &XferCtrlSpace64;
2150 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
2151
2152 int rc = VINF_SUCCESS;
2153 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
2154 {
2155 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
2156 {
2157 if (pThis->pIfWinNt)
2158 {
2159 RTGCUINTPTR GCPtrKpcr = 0;
2160
2161 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2162 &GCPtrKpcr, NULL /*pKpcrb*/);
2163 if (RT_SUCCESS(rc))
2164 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
2165 }
2166
2167 cbData = sizeof(RTGCUINTPTR);
2168 break;
2169 }
2170 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
2171 {
2172 if (pThis->pIfWinNt)
2173 {
2174 RTGCUINTPTR GCPtrKpcrb = 0;
2175
2176 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2177 NULL /*pKpcr*/, &GCPtrKpcrb);
2178 if (RT_SUCCESS(rc))
2179 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
2180 }
2181
2182 cbData = sizeof(RTGCUINTPTR);
2183 break;
2184 }
2185 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
2186 {
2187 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
2188 if (RT_SUCCESS(rc))
2189 cbData = sizeof(NTKCONTEXT64);
2190 break;
2191 }
2192 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
2193 {
2194 if (pThis->pIfWinNt)
2195 {
2196 RTGCUINTPTR GCPtrCurThrd = 0;
2197
2198 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2199 &GCPtrCurThrd);
2200 if (RT_SUCCESS(rc))
2201 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
2202 }
2203
2204 cbData = sizeof(RTGCUINTPTR);
2205 break;
2206 }
2207 default:
2208 rc = VERR_NOT_SUPPORTED;
2209 break;
2210 }
2211
2212 if ( RT_SUCCESS(rc)
2213 && cbData)
2214 {
2215 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
2216
2217 cSegs++;
2218 aRespSegs[2].pvSeg = &abResp[0];
2219 aRespSegs[2].cbSeg = cbData;
2220 }
2221 else if (RT_FAILURE(rc))
2222 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2223
2224 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2225 &aRespSegs[0], cSegs, true /*fAck*/);
2226}
2227
2228
2229/**
2230 * Processes a write control space 64 request.
2231 *
2232 * @returns VBox status code.
2233 * @param pThis The KD context.
2234 * @param pPktManip The manipulate packet request.
2235 */
2236static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2237{
2238 KDPACKETMANIPULATEHDR RespHdr;
2239 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2240 uint32_t cbData = 0;
2241 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2242
2243 RTSGSEG aRespSegs[2];
2244 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
2245 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2246 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2247 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2248
2249 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
2250 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
2251
2252 aRespSegs[0].pvSeg = &RespHdr;
2253 aRespSegs[0].cbSeg = sizeof(RespHdr);
2254 aRespSegs[1].pvSeg = &XferCtrlSpace64;
2255 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
2256
2257 int rc = VINF_SUCCESS;
2258 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
2259 {
2260 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
2261 {
2262 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2263 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
2264 if (RT_SUCCESS(rc))
2265 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
2266 break;
2267 }
2268 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
2269 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
2270 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
2271 default:
2272 rc = VERR_NOT_SUPPORTED;
2273 break;
2274 }
2275
2276 if (RT_FAILURE(rc))
2277 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2278 else
2279 XferCtrlSpace64.cbXfered = cbData;
2280
2281 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2282 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2283}
2284
2285
2286/**
2287 * Processes a restore breakpoint 64 request.
2288 *
2289 * @returns VBox status code.
2290 * @param pThis The KD context.
2291 * @param pPktManip The manipulate packet request.
2292 */
2293static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2294{
2295 KDPACKETMANIPULATEHDR RespHdr;
2296 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
2297 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
2298
2299 RTSGSEG aRespSegs[2];
2300 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
2301 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2302 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2303 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2304
2305 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
2306
2307 aRespSegs[0].pvSeg = &RespHdr;
2308 aRespSegs[0].cbSeg = sizeof(RespHdr);
2309 aRespSegs[1].pvSeg = &RestoreBkpt64;
2310 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
2311
2312 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
2313 if ( RT_FAILURE(rc)
2314 && rc != VERR_DBGF_BP_NOT_FOUND)
2315 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2316
2317 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2318 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2319}
2320
2321
2322/**
2323 * Processes a write breakpoint 64 request.
2324 *
2325 * @returns VBox status code.
2326 * @param pThis The KD context.
2327 * @param pPktManip The manipulate packet request.
2328 */
2329static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2330{
2331 KDPACKETMANIPULATEHDR RespHdr;
2332 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
2333 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
2334
2335 RTSGSEG aRespSegs[2];
2336 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
2337 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2338 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2339 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2340
2341 aRespSegs[0].pvSeg = &RespHdr;
2342 aRespSegs[0].cbSeg = sizeof(RespHdr);
2343 aRespSegs[1].pvSeg = &WriteBkpt64;
2344 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
2345
2346 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
2347
2348 DBGFADDRESS BpAddr;
2349 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, pPktManip->u.WriteBkpt.u64PtrBkpt);
2350 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
2351 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
2352 if (RT_FAILURE(rc))
2353 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2354
2355 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2356 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2357}
2358
2359
2360/**
2361 * Processes a get context extended 64 request.
2362 *
2363 * @returns VBox status code.
2364 * @param pThis The KD context.
2365 * @param pPktManip The manipulate packet request.
2366 */
2367static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2368{
2369 KDPACKETMANIPULATEHDR RespHdr;
2370 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
2371 NTCONTEXT64 NtCtx;
2372 RT_ZERO(RespHdr); RT_ZERO(ContextEx);
2373
2374 RTSGSEG aRespSegs[3];
2375 uint32_t cSegs = 2;
2376 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
2377 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2378 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2379 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2380
2381 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
2382 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
2383 ContextEx.cbXfered = 0;
2384
2385 aRespSegs[0].pvSeg = &RespHdr;
2386 aRespSegs[0].cbSeg = sizeof(RespHdr);
2387 aRespSegs[1].pvSeg = &ContextEx;
2388 aRespSegs[1].cbSeg = sizeof(ContextEx);
2389
2390 int rc = dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx, NTCONTEXT64_F_FULL);
2391 if ( RT_SUCCESS(rc)
2392 && pPktManip->u.ContextEx.offStart < sizeof(NtCtx))
2393 {
2394 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2395 ContextEx.cbXfered = RT_MIN(sizeof(NtCtx) - ContextEx.offStart, ContextEx.cbXfer);
2396
2397 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
2398 aRespSegs[2].cbSeg = ContextEx.cbXfered;
2399 cSegs++;
2400 }
2401
2402 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2403 &aRespSegs[0], cSegs, true /*fAck*/);
2404}
2405
2406
2407/**
2408 * Processes a manipulate packet.
2409 *
2410 * @returns VBox status code.
2411 * @param pThis The KD context.
2412 */
2413static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
2414{
2415 int rc = VINF_SUCCESS;
2416 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
2417
2418 switch (pPktManip->Hdr.idReq)
2419 {
2420 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
2421 {
2422 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
2423 break;
2424 }
2425 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
2426 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
2427 {
2428 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
2429 break;
2430 }
2431 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
2432 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
2433 {
2434 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
2435 break;
2436 }
2437 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
2438 {
2439 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
2440 break;
2441 }
2442 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
2443 {
2444 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
2445 break;
2446 }
2447 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
2448 {
2449 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
2450 break;
2451 }
2452 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
2453 {
2454 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
2455 break;
2456 }
2457 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
2458 {
2459 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
2460 break;
2461 }
2462 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
2463 {
2464 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
2465 break;
2466 }
2467 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
2468 {
2469 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
2470 break;
2471 }
2472 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
2473 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
2474 break;
2475 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
2476 {
2477 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
2478 break;
2479 }
2480 default:
2481 KDPACKETMANIPULATEHDR RespHdr;
2482 RT_ZERO(RespHdr);
2483
2484 RespHdr.idReq = pPktManip->Hdr.idReq;
2485 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2486 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2487 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
2488 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2489 &RespHdr, sizeof(RespHdr), true /*fAck*/);
2490 break;
2491 }
2492
2493 return rc;
2494}
2495
2496
2497/**
2498 * Processes a fully received packet.
2499 *
2500 * @returns VBox status code.
2501 * @param pThis The KD context.
2502 */
2503static int dbgcKdCtxPktProcess(PKDCTX pThis)
2504{
2505 int rc = VINF_SUCCESS;
2506
2507 pThis->fBreakinRecv = false;
2508
2509 /* Verify checksum. */
2510 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
2511 {
2512 /** @todo Check packet id. */
2513 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
2514 {
2515 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
2516 rc = dbgcKdCtxPktSendAck(pThis);
2517 }
2518 if (RT_SUCCESS(rc))
2519 {
2520#ifdef LOG_ENABLED
2521 RTSGSEG Seg;
2522 Seg.pvSeg = &pThis->abBody[0];
2523 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
2524 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
2525#endif
2526
2527 switch (pThis->PktHdr.Fields.u16SubType)
2528 {
2529 case KD_PACKET_HDR_SUB_TYPE_RESET:
2530 {
2531 pThis->idPktNext = 0;
2532 rc = dbgcKdCtxPktSendReset(pThis);
2533 if (RT_SUCCESS(rc))
2534 {
2535 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2536 if (rc == VWRN_DBGF_ALREADY_HALTED)
2537 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2538 }
2539 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
2540 break;
2541 }
2542 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
2543 {
2544 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
2545 switch (enmMode)
2546 {
2547 case CPUMMODE_PROTECTED:
2548 {
2549 rc = VERR_NOT_IMPLEMENTED;
2550 break;
2551 }
2552 case CPUMMODE_LONG:
2553 {
2554 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
2555 rc = dbgcKdCtxPktManipulate64Process(pThis);
2556 break;
2557 }
2558 case CPUMMODE_REAL:
2559 default:
2560 rc = VERR_NOT_SUPPORTED;
2561 break;
2562 }
2563 break;
2564 }
2565 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
2566 case KD_PACKET_HDR_SUB_TYPE_RESEND:
2567 {
2568 /* Don't do anything. */
2569 rc = VINF_SUCCESS;
2570 break;
2571 }
2572 default:
2573 rc = VERR_NOT_IMPLEMENTED;
2574 }
2575 }
2576 }
2577 else
2578 {
2579 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
2580 rc = dbgcKdCtxPktSendResend(pThis);
2581 }
2582
2583 if (pThis->fBreakinRecv)
2584 {
2585 pThis->fBreakinRecv = false;
2586 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2587 if (rc == VWRN_DBGF_ALREADY_HALTED)
2588 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2589 }
2590
2591 /* Next packet. */
2592 dbgcKdCtxPktRecvReset(pThis);
2593 return rc;
2594}
2595
2596
2597/**
2598 * Processes the received data based on the current state.
2599 *
2600 * @returns VBox status code.
2601 * @param pThis The KD context.
2602 */
2603static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
2604{
2605 int rc = VINF_SUCCESS;
2606
2607 switch (pThis->enmState)
2608 {
2609 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
2610 {
2611 /* Does it look like a valid packet start?. */
2612 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
2613 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
2614 {
2615 pThis->pbRecv = &pThis->PktHdr.ab[1];
2616 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
2617 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
2618 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
2619 }
2620 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2621 {
2622 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2623 if (rc == VWRN_DBGF_ALREADY_HALTED)
2624 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2625 dbgcKdCtxPktRecvReset(pThis);
2626 }
2627 /* else: Ignore and continue. */
2628 break;
2629 }
2630 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
2631 {
2632 /*
2633 * If the first and second byte differ there might be a single breakin
2634 * packet byte received and this is actually the start of a new packet.
2635 */
2636 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
2637 {
2638 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2639 {
2640 /* Halt the VM and rearrange the packet receiving state machine. */
2641 LogFlow(("DbgKd: Halting VM!\n"));
2642
2643 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2644 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
2645 pThis->pbRecv = &pThis->PktHdr.ab[1];
2646 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
2647 }
2648 else
2649 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
2650 }
2651 else
2652 {
2653 /* Normal packet receive continues with the rest of the header. */
2654 pThis->pbRecv = &pThis->PktHdr.ab[2];
2655 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
2656 pThis->enmState = KDRECVSTATE_PACKET_HDR;
2657 }
2658 break;
2659 }
2660 case KDRECVSTATE_PACKET_HDR:
2661 {
2662 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
2663 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
2664 {
2665 /* Start receiving the body. */
2666 if (pThis->PktHdr.Fields.cbBody)
2667 {
2668 pThis->pbRecv = &pThis->abBody[0];
2669 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
2670 pThis->enmState = KDRECVSTATE_PACKET_BODY;
2671 }
2672 else /* No body means no trailer byte it looks like. */
2673 rc = dbgcKdCtxPktProcess(pThis);
2674 }
2675 else
2676 rc = VERR_NET_PROTOCOL_ERROR;
2677 break;
2678 }
2679 case KDRECVSTATE_PACKET_BODY:
2680 {
2681 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
2682 pThis->bTrailer = 0;
2683 pThis->pbRecv = &pThis->bTrailer;
2684 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
2685 break;
2686 }
2687 case KDRECVSTATE_PACKET_TRAILER:
2688 {
2689 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
2690 rc = dbgcKdCtxPktProcess(pThis);
2691 else
2692 rc = VERR_NET_PROTOCOL_ERROR;
2693 break;
2694 }
2695 default:
2696 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
2697 }
2698
2699 return rc;
2700}
2701
2702
2703/**
2704 * Receive data and processes complete packets.
2705 *
2706 * @returns Status code.
2707 * @param pThis The KD context.
2708 */
2709static int dbgcKdCtxRecv(PKDCTX pThis)
2710{
2711 int rc = VINF_SUCCESS;
2712
2713 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
2714
2715 if (pThis->cbRecvLeft)
2716 {
2717 size_t cbRead = 0;
2718 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
2719 if (RT_SUCCESS(rc))
2720 {
2721 pThis->tsRecvLast = RTTimeMilliTS();
2722 pThis->cbRecvLeft -= cbRead;
2723 pThis->pbRecv += cbRead;
2724 if (!pThis->cbRecvLeft)
2725 rc = dbgcKdCtxRecvDataProcess(pThis);
2726 }
2727 }
2728
2729 LogFlowFunc(("returns rc=%Rrc\n", rc));
2730 return rc;
2731}
2732
2733
2734/**
2735 * Processes debugger events.
2736 *
2737 * @returns VBox status code.
2738 * @param pThis The KD context data.
2739 * @param pEvent Pointer to event data.
2740 */
2741static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
2742{
2743 /*
2744 * Process the event.
2745 */
2746 //PDBGC pDbgc = &pThis->Dbgc;
2747 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
2748 pThis->Dbgc.iArg = 0;
2749 int rc = VINF_SUCCESS;
2750 switch (pEvent->enmType)
2751 {
2752 /*
2753 * The first part is events we have initiated with commands.
2754 */
2755 case DBGFEVENT_HALT_DONE:
2756 {
2757 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
2758 break;
2759 }
2760
2761 /*
2762 * The second part is events which can occur at any time.
2763 */
2764#if 0
2765 case DBGFEVENT_FATAL_ERROR:
2766 {
2767 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
2768 dbgcGetEventCtx(pEvent->enmCtx));
2769 if (RT_SUCCESS(rc))
2770 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
2771 break;
2772 }
2773#endif
2774
2775 case DBGFEVENT_BREAKPOINT:
2776 case DBGFEVENT_BREAKPOINT_IO:
2777 case DBGFEVENT_BREAKPOINT_MMIO:
2778 case DBGFEVENT_BREAKPOINT_HYPER:
2779 case DBGFEVENT_STEPPED:
2780 case DBGFEVENT_STEPPED_HYPER:
2781 {
2782 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
2783 break;
2784 }
2785
2786#if 0
2787 case DBGFEVENT_ASSERTION_HYPER:
2788 {
2789 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
2790 "\ndbgf event: Hypervisor Assertion! (%s)\n"
2791 "%s"
2792 "%s"
2793 "\n",
2794 dbgcGetEventCtx(pEvent->enmCtx),
2795 pEvent->u.Assert.pszMsg1,
2796 pEvent->u.Assert.pszMsg2);
2797 if (RT_SUCCESS(rc))
2798 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
2799 break;
2800 }
2801
2802 case DBGFEVENT_DEV_STOP:
2803 {
2804 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
2805 "\n"
2806 "dbgf event: DBGFSTOP (%s)\n"
2807 "File: %s\n"
2808 "Line: %d\n"
2809 "Function: %s\n",
2810 dbgcGetEventCtx(pEvent->enmCtx),
2811 pEvent->u.Src.pszFile,
2812 pEvent->u.Src.uLine,
2813 pEvent->u.Src.pszFunction);
2814 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
2815 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
2816 "Message: %s\n",
2817 pEvent->u.Src.pszMessage);
2818 if (RT_SUCCESS(rc))
2819 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
2820 break;
2821 }
2822
2823
2824 case DBGFEVENT_INVALID_COMMAND:
2825 {
2826 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
2827 break;
2828 }
2829#endif
2830
2831 case DBGFEVENT_POWERING_OFF:
2832 {
2833 pThis->Dbgc.fReady = false;
2834 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, false);
2835 rc = VERR_GENERAL_FAILURE;
2836 break;
2837 }
2838
2839#if 0
2840 default:
2841 {
2842 /*
2843 * Probably a generic event. Look it up to find its name.
2844 */
2845 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
2846 if (pEvtDesc)
2847 {
2848 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
2849 {
2850 Assert(pEvtDesc->pszDesc);
2851 Assert(pEvent->u.Generic.cArgs == 1);
2852 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
2853 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
2854 }
2855 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
2856 {
2857 Assert(pEvent->u.Generic.cArgs >= 5);
2858 char szDetails[512];
2859 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
2860 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
2861 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
2862 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
2863 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
2864 szDetails);
2865 }
2866 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
2867 || pEvent->u.Generic.cArgs > 1
2868 || ( pEvent->u.Generic.cArgs == 1
2869 && pEvent->u.Generic.auArgs[0] != 0))
2870 {
2871 if (pEvtDesc->pszDesc)
2872 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
2873 pEvtDesc->pszName, pEvtDesc->pszDesc);
2874 else
2875 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
2876 if (pEvent->u.Generic.cArgs <= 1)
2877 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
2878 else
2879 {
2880 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
2881 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
2882 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
2883 }
2884 }
2885 else
2886 {
2887 if (pEvtDesc->pszDesc)
2888 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
2889 pEvtDesc->pszName, pEvtDesc->pszDesc);
2890 else
2891 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
2892 }
2893 }
2894 else
2895 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
2896 break;
2897 }
2898#else
2899 default:
2900 rc = VERR_NOT_IMPLEMENTED;
2901 break;
2902#endif
2903 }
2904
2905 return rc;
2906}
2907
2908
2909/**
2910 * Handle a receive timeout.
2911 *
2912 * @returns VBox status code.
2913 * @param pThis Pointer to the KD context.
2914 */
2915static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
2916{
2917 int rc = VINF_SUCCESS;
2918
2919 LogFlowFunc(("pThis=%p\n", pThis));
2920
2921 /*
2922 * If a single breakin packet byte was received but the header is otherwise incomplete
2923 * the VM is halted and a state change will be sent in the event processing loop.
2924 */
2925 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
2926 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2927 {
2928 LogFlow(("DbgKd: Halting VM!\n"));
2929 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2930 }
2931 else /* Send a reset packet (@todo Figure out the semantics in this case exactly). */
2932 rc = dbgcKdCtxPktSendReset(pThis);
2933
2934 dbgcKdCtxPktRecvReset(pThis);
2935
2936 LogFlowFunc(("rc=%Rrc\n", rc));
2937 return rc;
2938}
2939
2940
2941/**
2942 * Run the debugger console.
2943 *
2944 * @returns VBox status code.
2945 * @param pThis Pointer to the KD context.
2946 */
2947int dbgcKdRun(PKDCTX pThis)
2948{
2949 /*
2950 * We're ready for commands now.
2951 */
2952 pThis->Dbgc.fReady = true;
2953 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, true);
2954
2955 /*
2956 * Main Debugger Loop.
2957 *
2958 * This loop will either block on waiting for input or on waiting on
2959 * debug events. If we're forwarding the log we cannot wait for long
2960 * before we must flush the log.
2961 */
2962 int rc;
2963 for (;;)
2964 {
2965 rc = VERR_SEM_OUT_OF_TURN;
2966 if (pThis->Dbgc.pUVM)
2967 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
2968
2969 if (RT_SUCCESS(rc))
2970 {
2971 /*
2972 * Wait for a debug event.
2973 */
2974 DBGFEVENT Evt;
2975 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
2976 if (RT_SUCCESS(rc))
2977 {
2978 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
2979 if (RT_FAILURE(rc))
2980 break;
2981 }
2982 else if (rc != VERR_TIMEOUT)
2983 break;
2984
2985 /*
2986 * Check for input.
2987 */
2988 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 0))
2989 {
2990 rc = dbgcKdCtxRecv(pThis);
2991 if (RT_FAILURE(rc))
2992 break;
2993 }
2994 }
2995 else if (rc == VERR_SEM_OUT_OF_TURN)
2996 {
2997 /*
2998 * Wait for input.
2999 */
3000 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 1000))
3001 {
3002 rc = dbgcKdCtxRecv(pThis);
3003 if (RT_FAILURE(rc))
3004 break;
3005 }
3006 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
3007 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
3008 rc = dbgcKdCtxRecvTimeout(pThis);
3009 }
3010 else
3011 break;
3012 }
3013
3014 return rc;
3015}
3016
3017
3018/**
3019 * Creates a KD context instance with the given backend.
3020 *
3021 * @returns VBox status code.
3022 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
3023 * @param pBack The backend to use for I/O.
3024 * @param fFlags Flags controlling the behavior.
3025 */
3026static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PDBGCBACK pBack, unsigned fFlags)
3027{
3028 /*
3029 * Validate input.
3030 */
3031 AssertPtrReturn(pBack, VERR_INVALID_POINTER);
3032 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
3033
3034 /*
3035 * Allocate and initialize.
3036 */
3037 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
3038 if (!pThis)
3039 return VERR_NO_MEMORY;
3040
3041 dbgcInitCmdHlp(&pThis->Dbgc);
3042 /*
3043 * This is compied from the native debug console (will be used for monitor commands)
3044 * in DBGCConsole.cpp. Try to keep both functions in sync.
3045 */
3046 pThis->Dbgc.pBack = pBack;
3047 /*pThis->Dbgc.pfnOutput = dbgcOutputGdb;*/
3048 pThis->Dbgc.pvOutputUser = pThis;
3049 pThis->Dbgc.pVM = NULL;
3050 pThis->Dbgc.pUVM = NULL;
3051 pThis->Dbgc.idCpu = 0;
3052 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
3053 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
3054 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
3055 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
3056 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
3057 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
3058 //pThis->Dbgc.fLog = false;
3059 pThis->Dbgc.fRegTerse = true;
3060 pThis->Dbgc.fStepTraceRegs = true;
3061 //pThis->Dbgc.cPagingHierarchyDumps = 0;
3062 //pThis->Dbgc.DisasmPos = {0};
3063 //pThis->Dbgc.SourcePos = {0};
3064 //pThis->Dbgc.DumpPos = {0};
3065 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
3066 //pThis->Dbgc.cbDumpElement = 0;
3067 //pThis->Dbgc.cVars = 0;
3068 //pThis->Dbgc.paVars = NULL;
3069 //pThis->Dbgc.pPlugInHead = NULL;
3070 //pThis->Dbgc.pFirstBp = NULL;
3071 //pThis->Dbgc.abSearch = {0};
3072 //pThis->Dbgc.cbSearch = 0;
3073 pThis->Dbgc.cbSearchUnit = 1;
3074 pThis->Dbgc.cMaxSearchHits = 1;
3075 //pThis->Dbgc.SearchAddr = {0};
3076 //pThis->Dbgc.cbSearchRange = 0;
3077
3078 //pThis->Dbgc.uInputZero = 0;
3079 //pThis->Dbgc.iRead = 0;
3080 //pThis->Dbgc.iWrite = 0;
3081 //pThis->Dbgc.cInputLines = 0;
3082 //pThis->Dbgc.fInputOverflow = false;
3083 pThis->Dbgc.fReady = true;
3084 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
3085 //pThis->Dbgc.iArg = 0;
3086 //pThis->Dbgc.rcOutput = 0;
3087 //pThis->Dbgc.rcCmd = 0;
3088
3089 //pThis->Dbgc.pszHistoryFile = NULL;
3090 //pThis->Dbgc.pszGlobalInitScript = NULL;
3091 //pThis->Dbgc.pszLocalInitScript = NULL;
3092
3093 dbgcEvalInit();
3094
3095 pThis->fBreakinRecv = false;
3096 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
3097 pThis->pIfWinNt = NULL;
3098 dbgcKdCtxPktRecvReset(pThis);
3099
3100 *ppKdCtx = pThis;
3101 return VINF_SUCCESS;
3102}
3103
3104
3105/**
3106 * Destroys the given KD context.
3107 *
3108 * @returns nothing.
3109 * @param pThis The KD context to destroy.
3110 */
3111static void dbgcKdCtxDestroy(PKDCTX pThis)
3112{
3113 AssertPtr(pThis);
3114
3115 pThis->pIfWinNt = NULL;
3116
3117 /* Detach from the VM. */
3118 if (pThis->Dbgc.pUVM)
3119 DBGFR3Detach(pThis->Dbgc.pUVM);
3120
3121 /* Free config strings. */
3122 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
3123 pThis->Dbgc.pszGlobalInitScript = NULL;
3124 RTStrFree(pThis->Dbgc.pszLocalInitScript);
3125 pThis->Dbgc.pszLocalInitScript = NULL;
3126 RTStrFree(pThis->Dbgc.pszHistoryFile);
3127 pThis->Dbgc.pszHistoryFile = NULL;
3128
3129 /* Finally, free the instance memory. */
3130 RTMemFree(pThis);
3131}
3132
3133
3134DECLHIDDEN(int) dbgcKdStubCreate(PUVM pUVM, PDBGCBACK pBack, unsigned fFlags)
3135{
3136 /*
3137 * Validate input.
3138 */
3139 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
3140 PVM pVM = NULL;
3141 if (pUVM)
3142 {
3143 pVM = VMR3GetVM(pUVM);
3144 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
3145 }
3146
3147 /*
3148 * Allocate and initialize instance data
3149 */
3150 PKDCTX pThis;
3151 int rc = dbgcKdCtxCreate(&pThis, pBack, fFlags);
3152 if (RT_FAILURE(rc))
3153 return rc;
3154 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
3155 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
3156
3157 /*
3158 * Attach to the specified VM.
3159 */
3160 if (RT_SUCCESS(rc) && pUVM)
3161 {
3162 rc = DBGFR3Attach(pUVM);
3163 if (RT_SUCCESS(rc))
3164 {
3165 pThis->Dbgc.pVM = pVM;
3166 pThis->Dbgc.pUVM = pUVM;
3167 pThis->Dbgc.idCpu = 0;
3168
3169 /* Try detecting a Windows NT guest. */
3170 char szName[64];
3171 rc = DBGFR3OSDetect(pUVM, szName, sizeof(szName));
3172 if (RT_SUCCESS(rc))
3173 {
3174 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pUVM, DBGFOSINTERFACE_WINNT);
3175 if (pThis->pIfWinNt)
3176 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3177 else
3178 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3179 }
3180 else
3181 {
3182 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3183 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3184 }
3185 }
3186 else
3187 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
3188 }
3189
3190 /*
3191 * Load plugins.
3192 */
3193 if (RT_SUCCESS(rc))
3194 {
3195 if (pVM)
3196 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
3197 dbgcEventInit(&pThis->Dbgc);
3198
3199 /*
3200 * Run the debugger main loop.
3201 */
3202 rc = dbgcKdRun(pThis);
3203 dbgcEventTerm(&pThis->Dbgc);
3204 }
3205
3206 /*
3207 * Cleanup console debugger session.
3208 */
3209 dbgcKdCtxDestroy(pThis);
3210 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
3211}
3212
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette