VirtualBox

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

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

Debugger/DBGCRemoteKd: Implement access to the internal VBox debugger. The protocol doesn't support something similar to GDBs monitor command which translates to a Rcmd packet unfortunately. However, KD supports a driver querying the debugger for some string input via DbgPrompt() which translates to DEBUG_IO packets being exchanged for setting the prompt and reading the response. This needs to be initiaed from our stub though, which is done by abusing the CauseBugCheck request is abused to drop into the VBoxDbg prompt. The request can be issued with WinDbgs .crash command

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