VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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