VirtualBox

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

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

Debugger/DBGCRemoteKd: Implement access to the internal VBox debugger. [...] [doxygen fix]

  • 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 86187 2020-09-20 12:17:44Z 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 pachPrompt The prompt to send (ASCII).
2258 * @param cbPrompt 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