VirtualBox

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

Last change on this file was 104612, checked in by vboxsync, 4 months ago

Debugger/DBGCRemoteKd.cpp: Error handling fixes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 170.4 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 104612 2024-05-13 16:10:11Z 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 Human readable string (read only).
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 * @param pSgBuf S/G buffer containing the manipulate packet payload.
1510 */
1511static void dbgcKdPktDumpManipulate(PRTSGBUF pSgBuf)
1512{
1513 KDPACKETMANIPULATEHDR Hdr;
1514 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, &Hdr, sizeof(Hdr));
1515
1516 if (cbCopied == sizeof(Hdr))
1517 {
1518 const char *pszReq = dbgcKdPktDumpManipulateReqToStr(Hdr.idReq);
1519
1520 Log3((" MANIPULATE(%#x (%s), %#x, %u, %#x)\n",
1521 Hdr.idReq, pszReq, Hdr.u16CpuLvl, Hdr.idCpu, Hdr.u32NtStatus));
1522
1523 switch (Hdr.idReq)
1524 {
1525 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
1526 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
1527 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
1528 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
1529 {
1530 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1531 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferMem64, sizeof(XferMem64));
1532 if (cbCopied == sizeof(XferMem64))
1533 {
1534 Log3((" u64PtrTarget: %RX64\n"
1535 " cbXferReq: %RX32\n"
1536 " cbXfered: %RX32\n",
1537 XferMem64.u64PtrTarget, XferMem64.cbXferReq, XferMem64.cbXfered));
1538 }
1539 else
1540 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferMem64), cbCopied));
1541 break;
1542 }
1543 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
1544 {
1545 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
1546 cbCopied = RTSgBufCopyToBuf(pSgBuf, &RestoreBkpt64, sizeof(RestoreBkpt64));
1547 if (cbCopied == sizeof(RestoreBkpt64))
1548 Log3((" u32HndBkpt: %RX32\n", RestoreBkpt64.u32HndBkpt));
1549 else
1550 Log3((" Payload to small, expected %u, got %zu\n", sizeof(RestoreBkpt64), cbCopied));
1551 break;
1552 }
1553 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
1554 {
1555 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
1556 cbCopied = RTSgBufCopyToBuf(pSgBuf, &WriteBkpt64, sizeof(WriteBkpt64));
1557 if (cbCopied == sizeof(WriteBkpt64))
1558 Log3((" u64PtrBkpt: %RX64\n"
1559 " u32HndBkpt: %RX32\n",
1560 WriteBkpt64.u64PtrBkpt, WriteBkpt64.u32HndBkpt));
1561 else
1562 Log3((" Payload to small, expected %u, got %zu\n", sizeof(WriteBkpt64), cbCopied));
1563 break;
1564 }
1565 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
1566 {
1567 KDPACKETMANIPULATE_CONTINUE Continue;
1568 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1569 if (cbCopied == sizeof(Continue))
1570 Log3((" u32NtContSts: %RX32\n", Continue.u32NtContSts));
1571 else
1572 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1573 break;
1574 }
1575 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
1576 {
1577 KDPACKETMANIPULATE_CONTINUE2 Continue;
1578 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1579 if (cbCopied == sizeof(Continue))
1580 Log3((" u32NtContSts: %RX32\n"
1581 " fTrace: %RX32\n",
1582 Continue.u32NtContSts, Continue.fTrace));
1583 else
1584 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1585 break;
1586 }
1587 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
1588 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
1589 {
1590 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
1591 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferCtrlSpace64, sizeof(XferCtrlSpace64));
1592 if (cbCopied == sizeof(XferCtrlSpace64))
1593 {
1594 Log3((" u64IdXfer: %RX64\n"
1595 " cbXferReq: %RX32\n"
1596 " cbXfered: %RX32\n",
1597 XferCtrlSpace64.u64IdXfer, XferCtrlSpace64.cbXferReq, XferCtrlSpace64.cbXfered));
1598 }
1599 else
1600 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferCtrlSpace64), cbCopied));
1601 break;
1602 }
1603 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
1604 {
1605 KDPACKETMANIPULATE_CONTEXTEX GetContextEx;
1606 cbCopied = RTSgBufCopyToBuf(pSgBuf, &GetContextEx, sizeof(GetContextEx));
1607 if (cbCopied == sizeof(GetContextEx))
1608 {
1609 Log3((" offStart: %RX32\n"
1610 " cbXferReq: %RX32\n"
1611 " cbXfered: %RX32\n",
1612 GetContextEx.offStart, GetContextEx.cbXfer, GetContextEx.cbXfered));
1613 }
1614 else
1615 Log3((" Payload to small, expected %u, got %zu\n", sizeof(GetContextEx), cbCopied));
1616 break;
1617 }
1618 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
1619 {
1620 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
1621 cbCopied = RTSgBufCopyToBuf(pSgBuf, &QueryMemory, sizeof(QueryMemory));
1622 if (cbCopied == sizeof(QueryMemory))
1623 {
1624 Log3((" u64GCPtr: %RX64\n"
1625 " u32AddrSpace: %RX32\n"
1626 " u32Flags: %RX32\n",
1627 QueryMemory.u64GCPtr, QueryMemory.u32AddrSpace, QueryMemory.u32Flags));
1628 }
1629 else
1630 Log3((" Payload to small, expected %u, got %zu\n", sizeof(QueryMemory), cbCopied));
1631 break;
1632 }
1633 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
1634 {
1635 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
1636 cbCopied = RTSgBufCopyToBuf(pSgBuf, &SearchMemory, sizeof(SearchMemory));
1637 if (cbCopied == sizeof(SearchMemory))
1638 {
1639 Log3((" u64GCPtr: %RX64\n"
1640 " cbSearch: %RX64\n"
1641 " cbPattern: %RX32\n",
1642 SearchMemory.u64GCPtr, SearchMemory.cbSearch, SearchMemory.cbPattern));
1643 }
1644 else
1645 Log3((" Payload to small, expected %u, got %zu\n", sizeof(SearchMemory), cbCopied));
1646 break;
1647 }
1648 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR:
1649 default:
1650 break;
1651 }
1652 }
1653 else
1654 Log3((" MANIPULATE(Header too small, expected %u, got %zu)\n", sizeof(Hdr), cbCopied));
1655}
1656
1657
1658/**
1659 * Dumps the received packet to the debug log.
1660 *
1661 * @returns VBox status code.
1662 * @param pPktHdr The packet header to dump.
1663 * @param fRx Flag whether the packet was received (false indicates an outgoing packet).
1664 */
1665static void dbgcKdPktDump(PCKDPACKETHDR pPktHdr, PCRTSGSEG paSegs, uint32_t cSegs, bool fRx)
1666{
1667 RTSGBUF SgBuf;
1668
1669 RTSgBufInit(&SgBuf, paSegs, cSegs);
1670
1671 Log3(("%s KDPKTHDR(%#x, %#x (%s), %u, %#x, %#x)\n",
1672 fRx ? "=>" : "<=",
1673 pPktHdr->u32Signature, pPktHdr->u16SubType, dbgcKdPktDumpSubTypeToStr(pPktHdr->u16SubType),
1674 pPktHdr->cbBody, pPktHdr->idPacket, pPktHdr->u32ChkSum));
1675 switch (pPktHdr->u16SubType)
1676 {
1677 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
1678 dbgcKdPktDumpManipulate(&SgBuf);
1679 break;
1680 default:
1681 break;
1682 }
1683}
1684#endif
1685
1686
1687/**
1688 * Resets the emulated hardware breakpoint state to a state similar after a reboot.
1689 *
1690 * @param pThis The KD context.
1691 */
1692static void dbgcKdCtxHwBpReset(PKDCTX pThis)
1693{
1694 pThis->fSingleStepped = false;
1695
1696 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1697 {
1698 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1699
1700 if (pBp->hDbgfBp != NIL_DBGFBP)
1701 {
1702 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->hDbgfBp);
1703 AssertRC(rc);
1704 }
1705
1706 pBp->hDbgfBp = NIL_DBGFBP;
1707 pBp->GCPtrBp = 0;
1708 pBp->fAcc = 0;
1709 pBp->fLen = 0;
1710 pBp->fLocal = false;
1711 pBp->fGlobal = false;
1712 pBp->fTriggered = false;
1713 }
1714}
1715
1716
1717/**
1718 * Updates the given breakpoint with the given properties.
1719 *
1720 * @returns VBox status code.
1721 * @param pThis The KD context.
1722 * @param pBp The breakpoint to update.
1723 * @param fAcc Access mode.
1724 * @param fLen Access length.
1725 * @param fGlobal Global breakpoint.
1726 * @param fLocal Local breakpoint.
1727 * @param GCPtrBp Linear address of the breakpoint.
1728 */
1729static int dbgcKdCtxHwBpUpdate(PKDCTX pThis, PKDCTXHWBP pBp, uint8_t fAcc, uint8_t fLen,
1730 bool fGlobal, bool fLocal, RTGCPTR GCPtrBp)
1731{
1732 int rc = VINF_SUCCESS;
1733
1734 /* Did anything actually change?. */
1735 if ( pBp->fAcc != fAcc
1736 || pBp->fLen != fLen
1737 || pBp->fGlobal != fGlobal
1738 || pBp->fLocal != fLocal
1739 || pBp->GCPtrBp != GCPtrBp)
1740 {
1741 /* Clear the old breakpoint. */
1742 if (pBp->hDbgfBp != NIL_DBGFBP)
1743 {
1744 rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->hDbgfBp);
1745 AssertRC(rc);
1746 pBp->hDbgfBp = NIL_DBGFBP;
1747 }
1748
1749 pBp->fAcc = fAcc;
1750 pBp->fLen = fLen;
1751 pBp->fGlobal = fGlobal;
1752 pBp->fLocal = fLocal;
1753 pBp->GCPtrBp = GCPtrBp;
1754 if (pBp->fGlobal || pBp->fLocal)
1755 {
1756 DBGFADDRESS AddrBp;
1757 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrBp, GCPtrBp);
1758
1759 uint8_t cb = 0;
1760 switch (pBp->fLen)
1761 {
1762 case X86_DR7_LEN_BYTE:
1763 cb = 1;
1764 break;
1765 case X86_DR7_LEN_WORD:
1766 cb = 2;
1767 break;
1768 case X86_DR7_LEN_DWORD:
1769 cb = 4;
1770 break;
1771 case X86_DR7_LEN_QWORD:
1772 cb = 8;
1773 break;
1774 default:
1775 AssertFailed();
1776 return VERR_NET_PROTOCOL_ERROR;
1777 }
1778
1779 rc = DBGFR3BpSetReg(pThis->Dbgc.pUVM, &AddrBp, 0 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/,
1780 pBp->fAcc, cb, &pBp->hDbgfBp);
1781 }
1782 }
1783
1784 return rc;
1785}
1786
1787
1788/**
1789 * Updates emulated hardware breakpoints based on the written DR7 value.
1790 *
1791 * @returns VBox status code.
1792 * @param pThis The KD context.
1793 * @param uDr7 The DR7 value which is written.
1794 */
1795static int dbgcKdCtxHwBpDr7Update(PKDCTX pThis, uint32_t uDr7)
1796{
1797 int rc = VINF_SUCCESS;
1798
1799 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1800 {
1801 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1802 uint8_t fAcc = X86_DR7_GET_RW(uDr7, i);
1803 uint8_t fLen = X86_DR7_GET_LEN(uDr7, i);
1804 bool fGlobal = (uDr7 & RT_BIT_32(1 + i * 2)) ? true : false;
1805 bool fLocal = (uDr7 & RT_BIT_32(i * 2)) ? true : false;
1806
1807 int rc2 = dbgcKdCtxHwBpUpdate(pThis, pBp, fAcc, fLen, fGlobal, fLocal, pThis->aHwBp[i].GCPtrBp);
1808 if ( RT_FAILURE(rc2)
1809 && RT_SUCCESS(rc))
1810 rc = rc2;
1811 }
1812
1813 return rc;
1814}
1815
1816
1817/**
1818 * Updates the linear guest pointer for the given hardware breakpoint.
1819 *
1820 * @returns VBox status code.
1821 * @param pThis The KD context.
1822 * @param pBp The breakpoint to update.
1823 * @param GCPtrBp The linear breakpoint address.
1824 */
1825DECLINLINE(int) dbgcKdCtxHwBpGCPtrUpdate(PKDCTX pThis, PKDCTXHWBP pBp, RTGCPTR GCPtrBp)
1826{
1827 return dbgcKdCtxHwBpUpdate(pThis, pBp, pBp->fAcc, pBp->fLen, pBp->fGlobal, pBp->fLocal, GCPtrBp);
1828}
1829
1830
1831/**
1832 * Calculates the DR7 value based on the emulated hardware breakpoint state and returns it.
1833 *
1834 * @returns The emulated DR7 value.
1835 * @param pThis The KD context.
1836 */
1837static uint32_t dbgcKdCtxHwBpDr7Get(PKDCTX pThis)
1838{
1839 uint32_t uDr7 = 0;
1840
1841 uDr7 |= X86_DR7_RW(0, pThis->aHwBp[0].fAcc);
1842 uDr7 |= X86_DR7_RW(1, pThis->aHwBp[1].fAcc);
1843 uDr7 |= X86_DR7_RW(2, pThis->aHwBp[2].fAcc);
1844 uDr7 |= X86_DR7_RW(3, pThis->aHwBp[3].fAcc);
1845
1846 uDr7 |= X86_DR7_LEN(0, pThis->aHwBp[0].fLen);
1847 uDr7 |= X86_DR7_LEN(1, pThis->aHwBp[1].fLen);
1848 uDr7 |= X86_DR7_LEN(2, pThis->aHwBp[2].fLen);
1849 uDr7 |= X86_DR7_LEN(3, pThis->aHwBp[3].fLen);
1850
1851 uDr7 |= pThis->aHwBp[0].fGlobal ? X86_DR7_G(0) : 0;
1852 uDr7 |= pThis->aHwBp[1].fGlobal ? X86_DR7_G(1) : 0;
1853 uDr7 |= pThis->aHwBp[2].fGlobal ? X86_DR7_G(2) : 0;
1854 uDr7 |= pThis->aHwBp[3].fGlobal ? X86_DR7_G(3) : 0;
1855
1856 uDr7 |= pThis->aHwBp[0].fLocal ? X86_DR7_L(0) : 0;
1857 uDr7 |= pThis->aHwBp[1].fLocal ? X86_DR7_L(1) : 0;
1858 uDr7 |= pThis->aHwBp[2].fLocal ? X86_DR7_L(2) : 0;
1859 uDr7 |= pThis->aHwBp[3].fLocal ? X86_DR7_L(3) : 0;
1860
1861 return uDr7;
1862}
1863
1864
1865/**
1866 * Updates emulated hardware breakpoints based on the written DR6 value.
1867 *
1868 * @param pThis The KD context.
1869 * @param uDr6 The DR7 value which is written.
1870 */
1871static void dbgcKdCtxHwBpDr6Update(PKDCTX pThis, uint32_t uDr6)
1872{
1873 pThis->aHwBp[0].fTriggered = (uDr6 & X86_DR6_B0) ? true : false;
1874 pThis->aHwBp[1].fTriggered = (uDr6 & X86_DR6_B1) ? true : false;
1875 pThis->aHwBp[2].fTriggered = (uDr6 & X86_DR6_B2) ? true : false;
1876 pThis->aHwBp[3].fTriggered = (uDr6 & X86_DR6_B3) ? true : false;
1877 pThis->fSingleStepped = (uDr6 & X86_DR6_BS) ? true : false;
1878}
1879
1880
1881/**
1882 * Calculates the DR6 value based on the emulated hardware breakpoint state and returns it.
1883 *
1884 * @returns The emulated DR6 value.
1885 * @param pThis The KD context.
1886 */
1887static uint32_t dbgcKdCtxHwBpDr6Get(PKDCTX pThis)
1888{
1889 uint32_t uDr6 = 0;
1890
1891 if (pThis->aHwBp[0].fTriggered)
1892 uDr6 |= X86_DR6_B0;
1893 if (pThis->aHwBp[1].fTriggered)
1894 uDr6 |= X86_DR6_B1;
1895 if (pThis->aHwBp[2].fTriggered)
1896 uDr6 |= X86_DR6_B2;
1897 if (pThis->aHwBp[3].fTriggered)
1898 uDr6 |= X86_DR6_B3;
1899 if (pThis->fSingleStepped)
1900 uDr6 |= X86_DR6_BS;
1901
1902 return uDr6;
1903}
1904
1905
1906/**
1907 * Wrapper for the I/O interface write callback.
1908 *
1909 * @returns Status code.
1910 * @param pThis The KD context.
1911 * @param pvPkt The packet data to send.
1912 * @param cbPkt Size of the packet in bytes.
1913 */
1914DECLINLINE(int) dbgcKdCtxWrite(PKDCTX pThis, const void *pvPkt, size_t cbPkt)
1915{
1916 return pThis->Dbgc.pIo->pfnWrite(pThis->Dbgc.pIo, pvPkt, cbPkt, NULL /*pcbWritten*/);
1917}
1918
1919
1920/**
1921 * Queries a given register set and stores it into the given context buffer.
1922 *
1923 * @returns VBox status code.
1924 * @param pThis The KD context.
1925 * @param idCpu The CPU to query the context for.
1926 * @param paRegs The register set to query.
1927 * @param cRegs Number of entries in the register set.
1928 * @param pvCtx The context buffer to store the data into.
1929 */
1930static int dbgcKdCtxQueryRegs(PKDCTX pThis, VMCPUID idCpu, PCKDREGDESC paRegs, uint32_t cRegs, void *pvCtx)
1931{
1932 int rc = VINF_SUCCESS;
1933
1934 for (uint32_t i = 0; i < cRegs && rc == VINF_SUCCESS; i++)
1935 {
1936 void *pvStart = (uint8_t *)pvCtx + paRegs[i].offReg;
1937
1938 switch (paRegs[i].enmValType)
1939 {
1940 case DBGFREGVALTYPE_U16: rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, paRegs[i].enmReg, (uint16_t *)pvStart); break;
1941 case DBGFREGVALTYPE_U32: rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, paRegs[i].enmReg, (uint32_t *)pvStart); break;
1942 case DBGFREGVALTYPE_U64: rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, paRegs[i].enmReg, (uint64_t *)pvStart); break;
1943 //case DBGFREGVALTYPE_R80: rc = DBGFR3RegCpuQueryR80(pThis->Dbgc.pUVM, idCpu, paRegs[i].enmReg, (RTFLOAT80U *)pvStart); break;
1944 //case DBGFREGVALTYPE_U128: rc = DBGFR3RegCpuQueryU128(pThis->Dbgc.pUVM, idCpu, paRegs[i].enmReg, (PRTUINT128U)pvStart); break;
1945 default: AssertMsgFailedBreakStmt(("Register type %u not implemented\n", paRegs[i].enmValType), rc = VERR_NOT_IMPLEMENTED);
1946 }
1947
1948 if ( rc == VINF_DBGF_ZERO_EXTENDED_REGISTER
1949 || ( rc == VINF_DBGF_TRUNCATED_REGISTER
1950 && paRegs[i].enmReg == DBGFREG_RFLAGS)) /* KD protocol specifies 32bit but is really 64bit. */
1951 rc = VINF_SUCCESS;
1952 }
1953
1954 if ( RT_SUCCESS(rc)
1955 && rc != VINF_SUCCESS)
1956 rc = VERR_DBGF_UNSUPPORTED_CAST;
1957
1958 return rc;
1959}
1960
1961
1962/**
1963 * Fills in the given 64bit NT context structure with the requested values.
1964 *
1965 * @returns VBox status code.
1966 * @param pThis The KD context.
1967 * @param idCpu The CPU to query the context for.
1968 * @param pNtCtx The NT context structure to fill in.
1969 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1970 */
1971static int dbgcKdCtxQueryNtCtx64(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1972{
1973 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1974
1975 pNtCtx->fContext = NTCONTEXT_F_AMD64;
1976 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pNtCtx->u32RegMxCsr);
1977
1978 if ( RT_SUCCESS(rc)
1979 && fCtxFlags & NTCONTEXT_F_CONTROL)
1980 {
1981 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsCtrl64[0], RT_ELEMENTS(g_aRegsCtrl64), pNtCtx);
1982 if (RT_SUCCESS(rc))
1983 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1984 }
1985
1986 if ( RT_SUCCESS(rc)
1987 && fCtxFlags & NTCONTEXT_F_INTEGER)
1988 {
1989 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsInt64[0], RT_ELEMENTS(g_aRegsInt64), pNtCtx);
1990 if (RT_SUCCESS(rc))
1991 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1992 }
1993
1994 if ( RT_SUCCESS(rc)
1995 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1996 {
1997 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsSegs64[0], RT_ELEMENTS(g_aRegsSegs64), pNtCtx);
1998 if (RT_SUCCESS(rc))
1999 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
2000 }
2001
2002 if ( RT_SUCCESS(rc)
2003 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
2004 {
2005 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsFx64[0], RT_ELEMENTS(g_aRegsFx64), pNtCtx);
2006 if (RT_SUCCESS(rc))
2007 pNtCtx->fContext |= NTCONTEXT_F_FLOATING_POINT;
2008 }
2009
2010 if ( RT_SUCCESS(rc)
2011 && fCtxFlags & NTCONTEXT_F_DEBUG)
2012 {
2013 /** @todo NTCONTEXT_F_DEBUG */
2014 }
2015
2016 return rc;
2017}
2018
2019
2020/**
2021 * Fills in the given 32bit NT context structure with the requested values.
2022 *
2023 * @returns VBox status code.
2024 * @param pThis The KD context.
2025 * @param idCpu The CPU to query the context for.
2026 * @param pNtCtx The NT context structure to fill in.
2027 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
2028 */
2029static int dbgcKdCtxQueryNtCtx32(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT32 pNtCtx, uint32_t fCtxFlags)
2030{
2031 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
2032
2033 pNtCtx->fContext = NTCONTEXT_F_X86;
2034
2035 int rc = VINF_SUCCESS;
2036 if (fCtxFlags & NTCONTEXT_F_CONTROL)
2037 {
2038 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsCtrl32[0], RT_ELEMENTS(g_aRegsCtrl32), pNtCtx);
2039 if (RT_SUCCESS(rc))
2040 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
2041 }
2042
2043 if ( RT_SUCCESS(rc)
2044 && fCtxFlags & NTCONTEXT_F_INTEGER)
2045 {
2046 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsInt32[0], RT_ELEMENTS(g_aRegsInt32), pNtCtx);
2047 if (RT_SUCCESS(rc))
2048 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
2049 }
2050
2051 if ( RT_SUCCESS(rc)
2052 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
2053 {
2054 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsSegs32[0], RT_ELEMENTS(g_aRegsSegs32), pNtCtx);
2055 if (RT_SUCCESS(rc))
2056 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
2057 }
2058
2059 if ( RT_SUCCESS(rc)
2060 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
2061 {
2062 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsFx32[0], RT_ELEMENTS(g_aRegsFx32), pNtCtx);
2063 if (RT_SUCCESS(rc))
2064 pNtCtx->fContext |= NTCONTEXT_F_FLOATING_POINT;
2065 }
2066
2067 if ( RT_SUCCESS(rc)
2068 && fCtxFlags & NTCONTEXT_F_DEBUG)
2069 {
2070 rc = dbgcKdCtxQueryRegs(pThis, idCpu, &g_aRegsDbg32[0], RT_ELEMENTS(g_aRegsDbg32), pNtCtx);
2071 if (RT_SUCCESS(rc))
2072 pNtCtx->fContext |= NTCONTEXT_F_DEBUG;
2073 }
2074
2075 return rc;
2076}
2077
2078
2079#define KD_REG_INIT(a_pszName, a_enmType, a_ValMember, a_Val) \
2080 do \
2081 { \
2082 aRegsSet[idxReg].pszName = a_pszName; \
2083 aRegsSet[idxReg].enmType = a_enmType; \
2084 aRegsSet[idxReg].Val.a_ValMember = a_Val; \
2085 idxReg++; \
2086 } while (0)
2087#define KD_REG_INIT_DTR(a_pszName, a_Base, a_Limit) \
2088 do \
2089 { \
2090 aRegsSet[idxReg].pszName = a_pszName; \
2091 aRegsSet[idxReg].enmType = DBGFREGVALTYPE_DTR; \
2092 aRegsSet[idxReg].Val.dtr.u64Base = a_Base; \
2093 aRegsSet[idxReg].Val.dtr.u32Limit = a_Limit; \
2094 idxReg++; \
2095 } while (0)
2096#define KD_REG_INIT_U16(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U16, u16, a_Val)
2097#define KD_REG_INIT_U32(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U32, u32, a_Val)
2098#define KD_REG_INIT_U64(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U64, u64, a_Val)
2099
2100
2101/**
2102 * Writes the indicated values from the given context structure to the guests register set.
2103 *
2104 * @returns VBox status code.
2105 * @param pThis The KD context.
2106 * @param idCpu The CPU to query the context for.
2107 * @param pNtCtx The NT context structure to set.
2108 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to set.
2109 */
2110static int dbgcKdCtxSetNtCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
2111{
2112 uint32_t idxReg = 0;
2113 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
2114
2115 KD_REG_INIT_U32("mxcsr", pNtCtx->u32RegMxCsr);
2116
2117 if (fCtxFlags & NTCONTEXT_F_CONTROL)
2118 {
2119#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2120 KD_REG_INIT_U16("cs", pNtCtx->u16SegCs);
2121 KD_REG_INIT_U16("ss", pNtCtx->u16SegSs);
2122#endif
2123 KD_REG_INIT_U64("rip", pNtCtx->u64RegRip);
2124 KD_REG_INIT_U64("rsp", pNtCtx->u64RegRsp);
2125 KD_REG_INIT_U64("rbp", pNtCtx->u64RegRbp);
2126 KD_REG_INIT_U32("rflags", pNtCtx->u32RegEflags);
2127 }
2128
2129 if (fCtxFlags & NTCONTEXT_F_INTEGER)
2130 {
2131 KD_REG_INIT_U64("rax", pNtCtx->u64RegRax);
2132 KD_REG_INIT_U64("rcx", pNtCtx->u64RegRcx);
2133 KD_REG_INIT_U64("rdx", pNtCtx->u64RegRdx);
2134 KD_REG_INIT_U64("rbx", pNtCtx->u64RegRbx);
2135 KD_REG_INIT_U64("rsi", pNtCtx->u64RegRsi);
2136 KD_REG_INIT_U64("rdi", pNtCtx->u64RegRdi);
2137 KD_REG_INIT_U64("r8", pNtCtx->u64RegR8);
2138 KD_REG_INIT_U64("r9", pNtCtx->u64RegR9);
2139 KD_REG_INIT_U64("r10", pNtCtx->u64RegR10);
2140 KD_REG_INIT_U64("r11", pNtCtx->u64RegR11);
2141 KD_REG_INIT_U64("r12", pNtCtx->u64RegR12);
2142 KD_REG_INIT_U64("r13", pNtCtx->u64RegR13);
2143 KD_REG_INIT_U64("r14", pNtCtx->u64RegR14);
2144 KD_REG_INIT_U64("r15", pNtCtx->u64RegR15);
2145 }
2146
2147 if (fCtxFlags & NTCONTEXT_F_SEGMENTS)
2148 {
2149#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2150 KD_REG_INIT_U16("ds", pNtCtx->u16SegDs);
2151 KD_REG_INIT_U16("es", pNtCtx->u16SegEs);
2152 KD_REG_INIT_U16("fs", pNtCtx->u16SegFs);
2153 KD_REG_INIT_U16("gs", pNtCtx->u16SegGs);
2154#endif
2155 }
2156
2157 if (fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
2158 {
2159 /** @todo NTCONTEXT_F_FLOATING_POINT. */
2160 }
2161
2162 if (fCtxFlags & NTCONTEXT_F_DEBUG)
2163 dbgcKdCtxMsgSend(pThis, true /*fWarning*/, "Setting local DR registers does not work!");
2164
2165 return DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2166}
2167
2168
2169/**
2170 * Fills in the given 64bit NT kernel context structure with the requested values.
2171 *
2172 * @returns VBox status code.
2173 * @param pThis The KD context.
2174 * @param idCpu The CPU to query the context for.
2175 * @param pKNtCtx The NT context structure to fill in.
2176 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
2177 */
2178static int dbgcKdCtxQueryNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT64 pKNtCtx, uint32_t fCtxFlags)
2179{
2180 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2181
2182 int rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u64RegCr0);
2183 if (RT_SUCCESS(rc))
2184 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u64RegCr2);
2185 if (RT_SUCCESS(rc))
2186 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u64RegCr3);
2187 if (RT_SUCCESS(rc))
2188 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u64RegCr4);
2189 if (RT_SUCCESS(rc))
2190 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR8, &pKNtCtx->u64RegCr8);
2191 if (RT_SUCCESS(rc))
2192 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2193 if (RT_SUCCESS(rc))
2194 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u64PtrBase);
2195 if (RT_SUCCESS(rc))
2196 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2197 if (RT_SUCCESS(rc))
2198 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u64PtrBase);
2199 if (RT_SUCCESS(rc))
2200 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2201 if (RT_SUCCESS(rc))
2202 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2203 if (RT_SUCCESS(rc))
2204 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pKNtCtx->u32RegMxCsr);
2205
2206 if (RT_SUCCESS(rc))
2207 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_GS_BASE, &pKNtCtx->u64MsrGsBase);
2208 if (RT_SUCCESS(rc))
2209 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_KERNEL_GS_BASE, &pKNtCtx->u64MsrKernelGsBase);
2210 if (RT_SUCCESS(rc))
2211 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K6_STAR, &pKNtCtx->u64MsrStar);
2212 if (RT_SUCCESS(rc))
2213 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_LSTAR, &pKNtCtx->u64MsrLstar);
2214 if (RT_SUCCESS(rc))
2215 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_CSTAR, &pKNtCtx->u64MsrCstar);
2216 if (RT_SUCCESS(rc))
2217 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_SF_MASK, &pKNtCtx->u64MsrSfMask);
2218 /** @todo XCR0 */
2219
2220 /* Get the emulated DR register state. */
2221 pKNtCtx->u64RegDr0 = pThis->aHwBp[0].GCPtrBp;
2222 pKNtCtx->u64RegDr1 = pThis->aHwBp[1].GCPtrBp;
2223 pKNtCtx->u64RegDr2 = pThis->aHwBp[2].GCPtrBp;
2224 pKNtCtx->u64RegDr3 = pThis->aHwBp[3].GCPtrBp;
2225 pKNtCtx->u64RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2226 pKNtCtx->u64RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2227
2228 if (RT_SUCCESS(rc))
2229 rc = dbgcKdCtxQueryNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, fCtxFlags);
2230
2231 return rc;
2232}
2233
2234
2235/**
2236 * Fills in the given 32bit NT kernel context structure with the requested values.
2237 *
2238 * @returns VBox status code.
2239 * @param pThis The KD context.
2240 * @param idCpu The CPU to query the context for.
2241 * @param pKNtCtx The NT context structure to fill in.
2242 */
2243static int dbgcKdCtxQueryNtKCtx32(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT32 pKNtCtx)
2244{
2245 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2246
2247 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u32RegCr0);
2248 if (RT_SUCCESS(rc))
2249 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u32RegCr2);
2250 if (RT_SUCCESS(rc))
2251 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u32RegCr3);
2252 if (RT_SUCCESS(rc))
2253 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u32RegCr4);
2254
2255 if (RT_SUCCESS(rc))
2256 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2257 if (RT_SUCCESS(rc))
2258 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u32PtrBase);
2259 if (RT_SUCCESS(rc))
2260 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2261 if (RT_SUCCESS(rc))
2262 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u32PtrBase);
2263 if (RT_SUCCESS(rc))
2264 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2265 if (RT_SUCCESS(rc))
2266 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2267
2268 /* Get the emulated DR register state. */
2269 pKNtCtx->u32RegDr0 = (uint32_t)pThis->aHwBp[0].GCPtrBp;
2270 pKNtCtx->u32RegDr1 = (uint32_t)pThis->aHwBp[1].GCPtrBp;
2271 pKNtCtx->u32RegDr2 = (uint32_t)pThis->aHwBp[2].GCPtrBp;
2272 pKNtCtx->u32RegDr3 = (uint32_t)pThis->aHwBp[3].GCPtrBp;
2273 pKNtCtx->u32RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2274 pKNtCtx->u32RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2275
2276 return rc;
2277}
2278
2279
2280/**
2281 * Fills in the given 64bit NT kernel context structure with the requested values.
2282 *
2283 * @returns VBox status code.
2284 * @param pThis The KD context.
2285 * @param idCpu The CPU to query the context for.
2286 * @param pKNtCtx The NT context structure to fill in.
2287 * @param cbSet How many bytes of the context are valid.
2288 */
2289static int dbgcKdCtxSetNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTKCONTEXT64 pKNtCtx, size_t cbSet)
2290{
2291 AssertReturn(cbSet >= RT_UOFFSETOF(NTKCONTEXT64, Ctx), VERR_INVALID_PARAMETER);
2292
2293 uint32_t idxReg = 0;
2294 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
2295
2296 KD_REG_INIT_U64("cr0", pKNtCtx->u64RegCr0);
2297 KD_REG_INIT_U64("cr2", pKNtCtx->u64RegCr2);
2298 KD_REG_INIT_U64("cr3", pKNtCtx->u64RegCr3);
2299 KD_REG_INIT_U64("cr4", pKNtCtx->u64RegCr4);
2300 KD_REG_INIT_U64("cr8", pKNtCtx->u64RegCr8);
2301
2302 KD_REG_INIT_DTR("gdtr", pKNtCtx->Gdtr.u64PtrBase, pKNtCtx->Gdtr.u16Limit);
2303 KD_REG_INIT_DTR("idtr", pKNtCtx->Idtr.u64PtrBase, pKNtCtx->Idtr.u16Limit);
2304
2305#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2306 KD_REG_INIT_U16("tr", pKNtCtx->u16RegTr);
2307 KD_REG_INIT_U16("ldtr", pKNtCtx->u16RegLdtr);
2308#endif
2309 KD_REG_INIT_U32("mxcsr", pKNtCtx->u32RegMxCsr);
2310
2311 KD_REG_INIT_U64("msr_gs_base", pKNtCtx->u64MsrGsBase);
2312 KD_REG_INIT_U64("krnl_gs_base", pKNtCtx->u64MsrKernelGsBase);
2313 KD_REG_INIT_U64("star", pKNtCtx->u64MsrStar);
2314 KD_REG_INIT_U64("lstar", pKNtCtx->u64MsrLstar);
2315 KD_REG_INIT_U64("cstar", pKNtCtx->u64MsrCstar);
2316 KD_REG_INIT_U64("sf_mask", pKNtCtx->u64MsrSfMask);
2317
2318 int rc = DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2319 if ( RT_SUCCESS(rc)
2320 && cbSet > RT_UOFFSETOF(NTKCONTEXT64, Ctx)) /** @todo Probably wrong. */
2321 rc = dbgcKdCtxSetNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, pKNtCtx->Ctx.fContext);
2322
2323 if (RT_SUCCESS(rc))
2324 {
2325 /* Update emulated hardware breakpoint state. */
2326 dbgcKdCtxHwBpDr6Update(pThis, (uint32_t)pKNtCtx->u64RegDr6);
2327 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pKNtCtx->u64RegDr7);
2328 if (RT_SUCCESS(rc))
2329 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[0], pKNtCtx->u64RegDr0);
2330 if (RT_SUCCESS(rc))
2331 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[1], pKNtCtx->u64RegDr1);
2332 if (RT_SUCCESS(rc))
2333 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[2], pKNtCtx->u64RegDr2);
2334 if (RT_SUCCESS(rc))
2335 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[3], pKNtCtx->u64RegDr3);
2336 }
2337
2338 return rc;
2339}
2340
2341#undef KD_REG_INIT_64
2342#undef KD_REG_INIT_32
2343#undef KD_REG_INIT_16
2344#undef KD_REG_INIT_DTR
2345#undef KD_REG_INIT
2346
2347
2348/**
2349 * Validates the given KD packet header.
2350 *
2351 * @returns Flag whether the packet header is valid, false if invalid.
2352 * @param pPktHdr The packet header to validate.
2353 */
2354static bool dbgcKdPktHdrValidate(PCKDPACKETHDR pPktHdr)
2355{
2356 if ( pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_DATA
2357 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_CONTROL
2358 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_BREAKIN)
2359 return false;
2360
2361 if (pPktHdr->u16SubType >= KD_PACKET_HDR_SUB_TYPE_MAX)
2362 return false;
2363
2364 uint32_t idPacket = pPktHdr->idPacket & UINT32_C(0xfffffffe);
2365 if ( idPacket != KD_PACKET_HDR_ID_INITIAL
2366 && idPacket != KD_PACKET_HDR_ID_RESET
2367 && idPacket != 0 /* Happens on the very first packet */)
2368 return false;
2369
2370 return true;
2371}
2372
2373
2374/**
2375 * Generates a checksum from the given buffer.
2376 *
2377 * @returns Generated checksum.
2378 * @param pv The data to generate a checksum from.
2379 * @param cb Number of bytes to checksum.
2380 */
2381static uint32_t dbgcKdPktChkSumGen(const void *pv, size_t cb)
2382{
2383 const uint8_t *pb = (const uint8_t *)pv;
2384 uint32_t u32ChkSum = 0;
2385
2386 while (cb--)
2387 u32ChkSum += *pb++;
2388
2389 return u32ChkSum;
2390}
2391
2392
2393/**
2394 * Generates a checksum from the given segments.
2395 *
2396 * @returns Generated checksum.
2397 * @param paSegs Pointer to the array of segments containing the data.
2398 * @param cSegs Number of segments.
2399 * @param pcbChkSum Where to store the number of bytes checksummed, optional.
2400 */
2401static uint32_t dbgcKdPktChkSumGenSg(PCRTSGSEG paSegs, uint32_t cSegs, size_t *pcbChkSum)
2402{
2403 size_t cbChkSum = 0;
2404 uint32_t u32ChkSum = 0;
2405
2406 for (uint32_t i = 0; i < cSegs; i++)
2407 {
2408 u32ChkSum += dbgcKdPktChkSumGen(paSegs[i].pvSeg, paSegs[i].cbSeg);
2409 cbChkSum += paSegs[i].cbSeg;
2410 }
2411
2412 if (pcbChkSum)
2413 *pcbChkSum = cbChkSum;
2414
2415 return u32ChkSum;
2416}
2417
2418
2419/**
2420 * Waits for an acknowledgment.
2421 *
2422 * @returns VBox status code.
2423 * @param pThis The KD context.
2424 * @param msWait Maximum number of milliseconds to wait for an acknowledge.
2425 * @param pfResend Where to store the resend requested flag on success.
2426 */
2427static int dbgcKdCtxPktWaitForAck(PKDCTX pThis, RTMSINTERVAL msWait, bool *pfResend)
2428{
2429 KDPACKETHDR PktAck;
2430 uint8_t *pbCur = (uint8_t *)&PktAck;
2431 size_t cbLeft = sizeof(PktAck);
2432 uint64_t tsStartMs = RTTimeMilliTS();
2433 int rc = VINF_SUCCESS;
2434
2435 LogFlowFunc(("pThis=%p msWait=%u pfResend=%p\n", pThis, msWait, pfResend));
2436
2437 RT_ZERO(PktAck);
2438
2439 /* There might be breakin packets in the queue, read until we get something else. */
2440 while ( msWait
2441 && RT_SUCCESS(rc))
2442 {
2443 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, msWait))
2444 {
2445 size_t cbRead = 0;
2446 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pbCur, 1, &cbRead);
2447 if ( RT_SUCCESS(rc)
2448 && cbRead == 1)
2449 {
2450 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2451 msWait -= RT_MIN(msWait, tsSpanMs);
2452 tsStartMs = RTTimeMilliTS();
2453
2454 if (*pbCur == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2455 pThis->fBreakinRecv = true;
2456 else
2457 {
2458 pbCur++;
2459 cbLeft--;
2460 break;
2461 }
2462 }
2463 }
2464 else
2465 rc = VERR_TIMEOUT;
2466 }
2467
2468 if ( RT_SUCCESS(rc)
2469 && !msWait)
2470 rc = VERR_TIMEOUT;
2471
2472 if (RT_SUCCESS(rc))
2473 {
2474 while ( msWait
2475 && RT_SUCCESS(rc)
2476 && cbLeft)
2477 {
2478 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, msWait))
2479 {
2480 size_t cbRead = 0;
2481 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pbCur, cbLeft, &cbRead);
2482 if (RT_SUCCESS(rc))
2483 {
2484 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2485 msWait -= RT_MIN(msWait, tsSpanMs);
2486 tsStartMs = RTTimeMilliTS();
2487
2488 cbLeft -= cbRead;
2489 pbCur += cbRead;
2490 }
2491 }
2492 else
2493 rc = VERR_TIMEOUT;
2494 }
2495
2496 if (RT_SUCCESS(rc))
2497 {
2498 if (PktAck.u32Signature == KD_PACKET_HDR_SIGNATURE_CONTROL)
2499 {
2500 if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE)
2501 rc = VINF_SUCCESS;
2502 else if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_RESEND)
2503 {
2504 *pfResend = true;
2505 rc = VINF_SUCCESS;
2506 }
2507 else
2508 rc = VERR_NET_PROTOCOL_ERROR;
2509 }
2510 else
2511 rc = VERR_NET_PROTOCOL_ERROR;
2512 }
2513 }
2514
2515 LogFlowFunc(("returns rc=%Rrc *pfResend=%RTbool\n", rc, *pfResend));
2516 return rc;
2517}
2518
2519
2520/**
2521 * Sends the given packet header and optional segmented body (the trailing byte is sent automatically).
2522 *
2523 * @returns VBox status code.
2524 * @param pThis The KD context.
2525 * @param u32Signature The signature to send.
2526 * @param u16SubType The sub type to send.
2527 * @param paSegs Pointer to the array of segments to send in the body, optional.
2528 * @param cSegs Number of segments.
2529 * @param fAck Flag whether to wait for an acknowledge.
2530 */
2531static int dbgcKdCtxPktSendSg(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2532 PCRTSGSEG paSegs, uint32_t cSegs, bool fAck)
2533{
2534 int rc = VINF_SUCCESS;
2535 uint32_t cRetriesLeft = 3;
2536 uint8_t bTrailer = KD_PACKET_TRAILING_BYTE;
2537 KDPACKETHDR Hdr;
2538
2539 size_t cbChkSum = 0;
2540 uint32_t u32ChkSum = dbgcKdPktChkSumGenSg(paSegs, cSegs, &cbChkSum);
2541
2542 Hdr.u32Signature = u32Signature;
2543 Hdr.u16SubType = u16SubType;
2544 Hdr.cbBody = (uint16_t)cbChkSum;
2545 Hdr.idPacket = pThis->idPktNext;
2546 Hdr.u32ChkSum = u32ChkSum;
2547
2548#ifdef LOG_ENABLED
2549 dbgcKdPktDump(&Hdr, paSegs, cSegs, false /*fRx*/);
2550#endif
2551
2552 while (cRetriesLeft--)
2553 {
2554 bool fResend = false;
2555
2556 if (pThis->Dbgc.pIo->pfnPktBegin)
2557 {
2558 rc = pThis->Dbgc.pIo->pfnPktBegin(pThis->Dbgc.pIo, 0 /*cbPktHint*/);
2559 AssertRC(rc);
2560 }
2561
2562 rc = dbgcKdCtxWrite(pThis, &Hdr, sizeof(Hdr));
2563 if ( RT_SUCCESS(rc)
2564 && paSegs
2565 && cSegs)
2566 {
2567 for (uint32_t i = 0; i < cSegs && RT_SUCCESS(rc); i++)
2568 rc = dbgcKdCtxWrite(pThis, paSegs[i].pvSeg, paSegs[i].cbSeg);
2569
2570 if (RT_SUCCESS(rc))
2571 rc = dbgcKdCtxWrite(pThis, &bTrailer, sizeof(bTrailer));
2572 }
2573
2574 if ( RT_SUCCESS(rc)
2575 && pThis->Dbgc.pIo->pfnPktEnd)
2576 rc = pThis->Dbgc.pIo->pfnPktEnd(pThis->Dbgc.pIo);
2577
2578 if (RT_SUCCESS(rc))
2579 {
2580 if (fAck)
2581 rc = dbgcKdCtxPktWaitForAck(pThis, 10 * 1000, &fResend);
2582
2583 if ( RT_SUCCESS(rc)
2584 && !fResend)
2585 break;
2586 }
2587 }
2588
2589 return rc;
2590}
2591
2592
2593/**
2594 * Sends the given packet header and optional body (the trailing byte is sent automatically).
2595 *
2596 * @returns VBox status code.
2597 * @param pThis The KD context.
2598 * @param u32Signature The signature to send.
2599 * @param u16SubType The sub type to send.
2600 * @param pvBody The body to send, optional.
2601 * @param cbBody Body size in bytes.
2602 * @param fAck Flag whether to wait for an acknowledge.
2603 */
2604DECLINLINE(int) dbgcKdCtxPktSend(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2605 const void *pvBody, size_t cbBody,
2606 bool fAck)
2607{
2608 RTSGSEG Seg;
2609
2610 Seg.pvSeg = (void *)pvBody;
2611 Seg.cbSeg = cbBody;
2612 return dbgcKdCtxPktSendSg(pThis, u32Signature, u16SubType, cbBody ? &Seg : NULL, cbBody ? 1 : 0, fAck);
2613}
2614
2615
2616/**
2617 * Sends a resend packet answer.
2618 *
2619 * @returns VBox status code.
2620 * @param pThis The KD context.
2621 */
2622DECLINLINE(int) dbgcKdCtxPktSendResend(PKDCTX pThis)
2623{
2624 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESEND,
2625 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2626}
2627
2628
2629/**
2630 * Sends a resend packet answer.
2631 *
2632 * @returns VBox status code.
2633 * @param pThis The KD context.
2634 */
2635DECLINLINE(int) dbgcKdCtxPktSendReset(PKDCTX pThis)
2636{
2637 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2638 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESET,
2639 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2640}
2641
2642
2643/**
2644 * Sends an acknowledge packet answer.
2645 *
2646 * @returns VBox status code.
2647 * @param pThis The KD context.
2648 */
2649DECLINLINE(int) dbgcKdCtxPktSendAck(PKDCTX pThis)
2650{
2651 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE,
2652 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2653}
2654
2655
2656/**
2657 * Resets the packet receive state machine.
2658 *
2659 * @param pThis The KD context.
2660 */
2661static void dbgcKdCtxPktRecvReset(PKDCTX pThis)
2662{
2663 pThis->enmState = KDRECVSTATE_PACKET_HDR_FIRST_BYTE;
2664 pThis->pbRecv = &pThis->PktHdr.ab[0];
2665 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[0]);
2666 pThis->msRecvTimeout = RT_INDEFINITE_WAIT;
2667 pThis->tsRecvLast = RTTimeMilliTS();
2668}
2669
2670
2671/**
2672 * Sends a Debug I/O string packet.
2673 *
2674 * @returns VBox status code.
2675 * @param pThis The KD context data.
2676 * @param idCpu The CPU ID generating this packet.
2677 * @param pachChars The characters to send (ASCII).
2678 * @param cbChars Number of characters to send.
2679 */
2680static int dbgcKdCtxDebugIoStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachChars, size_t cbChars)
2681{
2682 KDPACKETDEBUGIO DebugIo;
2683 RT_ZERO(DebugIo);
2684
2685 /* Fix your damn log strings if this exceeds 4GB... */
2686 if (cbChars != (uint32_t)cbChars)
2687 return VERR_BUFFER_OVERFLOW;
2688
2689 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2690 DebugIo.u16CpuLvl = 0x6;
2691 DebugIo.idCpu = (uint16_t)idCpu;
2692 DebugIo.u.Str.cbStr = (uint32_t)cbChars;
2693
2694 RTSGSEG aRespSegs[2];
2695
2696 aRespSegs[0].pvSeg = &DebugIo;
2697 aRespSegs[0].cbSeg = sizeof(DebugIo);
2698 aRespSegs[1].pvSeg = (void *)pachChars;
2699 aRespSegs[1].cbSeg = cbChars;
2700
2701 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2702 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2703 if (RT_SUCCESS(rc))
2704 pThis->idPktNext ^= 0x1;
2705
2706 return rc;
2707}
2708
2709
2710/**
2711 * Sends a message to the remotes end.
2712 *
2713 * @param pThis The KD context data.
2714 * @param fWarning Flag whether this is a warning or an informational message.
2715 * @param pszMsg The message to send.
2716 */
2717static void dbgcKdCtxMsgSend(PKDCTX pThis, bool fWarning, const char *pszMsg)
2718{
2719 size_t cchMsg = strlen(pszMsg);
2720
2721 KDPACKETDEBUGIO DebugIo;
2722 RT_ZERO(DebugIo);
2723
2724 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2725 DebugIo.u16CpuLvl = 0x6;
2726 DebugIo.idCpu = 0;
2727
2728 RTSGSEG aRespSegs[5];
2729
2730 aRespSegs[0].pvSeg = &DebugIo;
2731 aRespSegs[0].cbSeg = sizeof(DebugIo);
2732 aRespSegs[1].pvSeg = (void *)"VBoxDbg ";
2733 aRespSegs[1].cbSeg = sizeof("VBoxDbg ") - 1;
2734 if (fWarning)
2735 {
2736 aRespSegs[2].pvSeg = (void *)"WARNING ";
2737 aRespSegs[2].cbSeg = sizeof("WARNING ") - 1;
2738 }
2739 else
2740 {
2741 aRespSegs[2].pvSeg = (void *)"INFO ";
2742 aRespSegs[2].cbSeg = sizeof("INFO ") - 1;
2743 }
2744 aRespSegs[3].pvSeg = (void *)pszMsg;
2745 aRespSegs[3].cbSeg = cchMsg;
2746 aRespSegs[4].pvSeg = (void *)"\r\n";
2747 aRespSegs[4].cbSeg = 2;
2748
2749 DebugIo.u.Str.cbStr = (uint32_t)( aRespSegs[1].cbSeg
2750 + aRespSegs[2].cbSeg
2751 + aRespSegs[3].cbSeg
2752 + aRespSegs[4].cbSeg);
2753
2754 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2755 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2756 if (RT_SUCCESS(rc))
2757 pThis->idPktNext ^= 0x1;
2758}
2759
2760
2761/**
2762 * Queries some user input from the remotes end.
2763 *
2764 * @returns VBox status code.
2765 * @param pThis The KD context data.
2766 * @param idCpu The CPU ID generating this packet.
2767 * @param pachPrompt The prompt to send (ASCII).
2768 * @param cbPrompt Number of characters to send for the prompt.
2769 * @param cbResponseMax Maximum size for the response.
2770 */
2771static int dbgcKdCtxDebugIoGetStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachPrompt, size_t cbPrompt,
2772 size_t cbResponseMax)
2773{
2774 KDPACKETDEBUGIO DebugIo;
2775 RT_ZERO(DebugIo);
2776
2777 /* Fix your damn log strings if this exceeds 4GB... */
2778 if ( cbPrompt != (uint32_t)cbPrompt
2779 || cbResponseMax != (uint32_t)cbResponseMax)
2780 return VERR_BUFFER_OVERFLOW;
2781
2782 DebugIo.u32Type = KD_PACKET_DEBUG_IO_GET_STRING;
2783 DebugIo.u16CpuLvl = 0x6;
2784 DebugIo.idCpu = (uint16_t)idCpu;
2785 DebugIo.u.Prompt.cbPrompt = (uint32_t)cbPrompt;
2786 DebugIo.u.Prompt.cbReturn = (uint32_t)cbResponseMax;
2787
2788 RTSGSEG aRespSegs[2];
2789
2790 aRespSegs[0].pvSeg = &DebugIo;
2791 aRespSegs[0].cbSeg = sizeof(DebugIo);
2792 aRespSegs[1].pvSeg = (void *)pachPrompt;
2793 aRespSegs[1].cbSeg = cbPrompt;
2794
2795 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2796 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2797 if (RT_SUCCESS(rc))
2798 pThis->idPktNext ^= 0x1;
2799
2800 return rc;
2801}
2802
2803
2804/**
2805 * Sends a state change event packet.
2806 *
2807 * @returns VBox status code.
2808 * @param pThis The KD context data.
2809 * @param enmType The event type.
2810 */
2811static int dbgcKdCtxStateChangeSend(PKDCTX pThis, DBGFEVENTTYPE enmType)
2812{
2813 LogFlowFunc(("pThis=%p enmType=%u\n", pThis, enmType));
2814
2815 /* Select the record to send based on the CPU mode. */
2816 int rc = VINF_SUCCESS;
2817 KDPACKETSTATECHANGE64 StateChange64;
2818 RT_ZERO(StateChange64);
2819
2820 StateChange64.u32StateNew = KD_PACKET_STATE_CHANGE_EXCEPTION;
2821 StateChange64.u16CpuLvl = 0x6; /** @todo Figure this one out. */
2822 StateChange64.idCpu = pThis->Dbgc.idCpu;
2823 StateChange64.cCpus = (uint16_t)DBGFR3CpuGetCount(pThis->Dbgc.pUVM);
2824 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RIP, &StateChange64.u64RipThread);
2825 if (RT_SUCCESS(rc))
2826 {
2827 DBGFADDRESS AddrRip;
2828 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRip, StateChange64.u64RipThread);
2829
2830 StateChange64.u64RipThread = KD_PTR_CREATE(pThis, StateChange64.u64RipThread);
2831
2832 /** @todo Properly fill in the exception record. */
2833 switch (enmType)
2834 {
2835 case DBGFEVENT_HALT_DONE:
2836 case DBGFEVENT_BREAKPOINT:
2837 case DBGFEVENT_BREAKPOINT_IO:
2838 case DBGFEVENT_BREAKPOINT_MMIO:
2839 case DBGFEVENT_BREAKPOINT_HYPER:
2840 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_BKPT;
2841 break;
2842 case DBGFEVENT_STEPPED:
2843 case DBGFEVENT_STEPPED_HYPER:
2844 pThis->fSingleStepped = true; /* For emulation of DR6. */
2845 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_SINGLE_STEP;
2846 break;
2847 default:
2848 AssertMsgFailed(("Invalid DBGF event type for state change %d!\n", enmType));
2849 }
2850
2851 StateChange64.u.Exception.ExcpRec.cExcpParms = 3;
2852 StateChange64.u.Exception.u32FirstChance = 0x1;
2853
2854 /** @todo Properly fill in the control report. */
2855 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR6, &StateChange64.uCtrlReport.Amd64.u64RegDr6);
2856 if (RT_SUCCESS(rc))
2857 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR7, &StateChange64.uCtrlReport.Amd64.u64RegDr7);
2858 if (RT_SUCCESS(rc))
2859 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RFLAGS, &StateChange64.uCtrlReport.Amd64.u32RegEflags);
2860 if (RT_SUCCESS(rc))
2861 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_CS, &StateChange64.uCtrlReport.Amd64.u16SegCs);
2862 if (RT_SUCCESS(rc))
2863 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DS, &StateChange64.uCtrlReport.Amd64.u16SegDs);
2864 if (RT_SUCCESS(rc))
2865 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_ES, &StateChange64.uCtrlReport.Amd64.u16SegEs);
2866 if (RT_SUCCESS(rc))
2867 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_FS, &StateChange64.uCtrlReport.Amd64.u16SegFs);
2868 if (RT_SUCCESS(rc))
2869 {
2870 /* Read instruction bytes. */
2871 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
2872 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
2873 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
2874 if (RT_SUCCESS(rc))
2875 {
2876 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2877 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
2878 &StateChange64, sizeof(StateChange64), false /*fAck*/);
2879 }
2880 }
2881 }
2882
2883 LogFlowFunc(("returns %Rrc\n", rc));
2884 return rc;
2885}
2886
2887
2888/**
2889 * Processes a get version 64 request.
2890 *
2891 * @returns VBox status code.
2892 * @param pThis The KD context.
2893 * @param pPktManip The manipulate packet request.
2894 */
2895static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2896{
2897 KDPACKETMANIPULATE64 Resp;
2898 RT_ZERO(Resp);
2899
2900 /* Fill in the generic part. */
2901 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
2902 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2903 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
2904 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
2905
2906 /* Build our own response in case there is no Windows interface available. */
2907 uint32_t NtBuildNumber = 0x0f2800; /* Used when there is no NT interface available, which probably breaks symbol loading. */
2908 bool f32Bit = false;
2909 if (pThis->pIfWinNt)
2910 {
2911 int rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
2912 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
2913 &NtBuildNumber, &f32Bit);
2914 if (RT_SUCCESS(rc))
2915 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
2916 &Resp.u.GetVersion.u64PtrKernBase,
2917 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2918 if (RT_FAILURE(rc))
2919 LogRel(("DBGC/Kd: Failed to query WIndows version or kernel pointers rc=%Rrc\n", rc));
2920 }
2921
2922 /* Fill in the request specific part. */
2923 Resp.u.GetVersion.u16VersMaj = NtBuildNumber >> 16;
2924 Resp.u.GetVersion.u16VersMin = NtBuildNumber & UINT32_C(0xffff);
2925 Resp.u.GetVersion.u8VersProtocol = 0x6; /* From a Windows 10 guest. */
2926 Resp.u.GetVersion.u8VersKdSecondary = pThis->f32Bit ? 0 : 0x2; /* amd64 has a versioned context (0 and 1 are obsolete). */
2927 Resp.u.GetVersion.fFlags = KD_PACKET_MANIPULATE64_GET_VERSION_F_MP;
2928 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
2929 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
2930 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_MAX - KD_PACKET_MANIPULATE_REQ_MIN;
2931 Resp.u.GetVersion.u64PtrDebuggerDataList = 0;
2932
2933 if (f32Bit)
2934 {
2935 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_I386;
2936 Resp.u.GetVersion.u64PtrKernBase = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrKernBase);
2937 Resp.u.GetVersion.u64PtrPsLoadedModuleList = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2938 }
2939 else
2940 {
2941 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
2942 Resp.u.GetVersion.fFlags |= KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64;
2943 }
2944
2945 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2946 &Resp, sizeof(Resp), true /*fAck*/);
2947}
2948
2949
2950/**
2951 * Processes a read memory 64 request.
2952 *
2953 * @returns VBox status code.
2954 * @param pThis The KD context.
2955 * @param pPktManip The manipulate packet request.
2956 */
2957static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2958{
2959 KDPACKETMANIPULATEHDR RespHdr;
2960 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2961 uint8_t abMem[_4K];
2962 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2963
2964 DBGFADDRESS AddrRead;
2965 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
2966 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
2967 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2968 else
2969 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2970
2971 RTSGSEG aRespSegs[3];
2972 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2973 RespHdr.idReq = pPktManip->Hdr.idReq;
2974 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2975 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2976 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2977
2978 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2979 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2980 XferMem64.cbXfered = (uint32_t)cbRead;
2981
2982 aRespSegs[0].pvSeg = &RespHdr;
2983 aRespSegs[0].cbSeg = sizeof(RespHdr);
2984 aRespSegs[1].pvSeg = &XferMem64;
2985 aRespSegs[1].cbSeg = sizeof(XferMem64);
2986
2987 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
2988 if (RT_SUCCESS(rc))
2989 {
2990 cSegs++;
2991 aRespSegs[2].pvSeg = &abMem[0];
2992 aRespSegs[2].cbSeg = cbRead;
2993 }
2994 else
2995 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2996
2997 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2998 &aRespSegs[0], cSegs, true /*fAck*/);
2999}
3000
3001
3002/**
3003 * Processes a write memory 64 request.
3004 *
3005 * @returns VBox status code.
3006 * @param pThis The KD context.
3007 * @param pPktManip The manipulate packet request.
3008 */
3009static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3010{
3011 KDPACKETMANIPULATEHDR RespHdr;
3012 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
3013 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
3014
3015 DBGFADDRESS AddrWrite;
3016 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3017 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
3018 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
3019 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
3020 else
3021 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
3022
3023 RTSGSEG aRespSegs[2];
3024 uint32_t cSegs = 2;
3025 RespHdr.idReq = pPktManip->Hdr.idReq;
3026 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3027 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3028 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3029
3030 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
3031 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
3032 XferMem64.cbXfered = (uint32_t)cbWrite;
3033
3034 aRespSegs[0].pvSeg = &RespHdr;
3035 aRespSegs[0].cbSeg = sizeof(RespHdr);
3036 aRespSegs[1].pvSeg = &XferMem64;
3037 aRespSegs[1].cbSeg = sizeof(XferMem64);
3038
3039 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
3040 if (RT_FAILURE(rc))
3041 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3042
3043 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3044 &aRespSegs[0], cSegs, true /*fAck*/);
3045}
3046
3047
3048/**
3049 * Processes a continue request.
3050 *
3051 * @returns VBox status code.
3052 * @param pThis The KD context.
3053 * @param pPktManip The manipulate packet request.
3054 */
3055static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3056{
3057 RT_NOREF(pPktManip);
3058 int rc = VINF_SUCCESS;
3059
3060 /* No response, just resume. */
3061 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3062 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3063
3064 return rc;
3065}
3066
3067
3068/**
3069 * Processes a continue request.
3070 *
3071 * @returns VBox status code.
3072 * @param pThis The KD context.
3073 * @param pPktManip The manipulate packet request.
3074 */
3075static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3076{
3077 int rc = VINF_SUCCESS;
3078
3079 /* Update DR7. */
3080 if (pThis->f32Bit)
3081 rc = dbgcKdCtxHwBpDr7Update(pThis, pPktManip->u.Continue2.u.x86.u32RegDr7);
3082 else
3083 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pPktManip->u.Continue2.u.amd64.u64RegDr7);
3084
3085 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
3086 if (pPktManip->u.Continue2.fTrace)
3087 {
3088 PDBGFADDRESS pStackPop = NULL;
3089 RTGCPTR cbStackPop = 0;
3090 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
3091 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
3092 }
3093 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3094 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3095
3096 return rc;
3097}
3098
3099
3100/**
3101 * Processes a set context request.
3102 *
3103 * @returns VBox status code.
3104 * @param pThis The KD context.
3105 * @param pPktManip The manipulate packet request.
3106 */
3107static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3108{
3109 KDPACKETMANIPULATEHDR RespHdr;
3110 KDPACKETMANIPULATE_SETCONTEXT SetContext;
3111 RT_ZERO(RespHdr); RT_ZERO(SetContext);
3112
3113 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3114
3115 RTSGSEG aRespSegs[2];
3116 uint32_t cSegs = 2;
3117 RespHdr.idReq = pPktManip->Hdr.idReq;
3118 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3119 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3120 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3121
3122 /** @todo What do these flags mean? Can't be the context state to set because the valid one is
3123 * in NTCONTEXT64::fContext (observed with WinDbg). */
3124 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
3125
3126 aRespSegs[0].pvSeg = &RespHdr;
3127 aRespSegs[0].cbSeg = sizeof(RespHdr);
3128 aRespSegs[1].pvSeg = &SetContext;
3129 aRespSegs[1].cbSeg = sizeof(SetContext);
3130
3131 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, pNtCtx->fContext);
3132 if (RT_FAILURE(rc))
3133 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3134
3135 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3136 &aRespSegs[0], cSegs, true /*fAck*/);
3137}
3138
3139
3140/**
3141 * Processes a read control space 64 request.
3142 *
3143 * @returns VBox status code.
3144 * @param pThis The KD context.
3145 * @param pPktManip The manipulate packet request.
3146 */
3147static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3148{
3149 KDPACKETMANIPULATEHDR RespHdr;
3150 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
3151 uint8_t abResp[sizeof(NTKCONTEXT64)];
3152 uint32_t cbData = 0;
3153 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3154 RT_ZERO(abResp);
3155
3156 RTSGSEG aRespSegs[3];
3157 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
3158 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
3159 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3160 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3161 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3162
3163 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3164 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3165
3166 aRespSegs[0].pvSeg = &RespHdr;
3167 aRespSegs[0].cbSeg = sizeof(RespHdr);
3168 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3169 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3170
3171 int rc = VINF_SUCCESS;
3172 if (pThis->f32Bit)
3173 {
3174 if (pPktManip->u.XferCtrlSpace.u64IdXfer == sizeof(NTCONTEXT32))
3175 {
3176 /* Queries the kernel context. */
3177 rc = dbgcKdCtxQueryNtKCtx32(pThis, RespHdr.idCpu, (PNTKCONTEXT32)&abResp[0]);
3178 if (RT_SUCCESS(rc))
3179 cbData = sizeof(NTKCONTEXT32);
3180 }
3181 }
3182 else
3183 {
3184 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3185 {
3186 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3187 {
3188 if (pThis->pIfWinNt)
3189 {
3190 RTGCUINTPTR GCPtrKpcr = 0;
3191
3192 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(), RespHdr.idCpu,
3193 &GCPtrKpcr, NULL /*pKpcrb*/);
3194 if (RT_SUCCESS(rc))
3195 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
3196 }
3197
3198 cbData = sizeof(RTGCUINTPTR);
3199 break;
3200 }
3201 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3202 {
3203 if (pThis->pIfWinNt)
3204 {
3205 RTGCUINTPTR GCPtrKpcrb = 0;
3206
3207 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(), RespHdr.idCpu,
3208 NULL /*pKpcr*/, &GCPtrKpcrb);
3209 if (RT_SUCCESS(rc))
3210 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
3211 }
3212
3213 cbData = sizeof(RTGCUINTPTR);
3214 break;
3215 }
3216 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3217 {
3218 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
3219 if (RT_SUCCESS(rc))
3220 cbData = sizeof(NTKCONTEXT64);
3221 break;
3222 }
3223 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3224 {
3225 if (pThis->pIfWinNt)
3226 {
3227 RTGCUINTPTR GCPtrCurThrd = 0;
3228
3229 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
3230 RespHdr.idCpu, &GCPtrCurThrd);
3231 if (RT_SUCCESS(rc))
3232 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
3233 }
3234
3235 cbData = sizeof(RTGCUINTPTR);
3236 break;
3237 }
3238 default:
3239 rc = VERR_NOT_SUPPORTED;
3240 break;
3241 }
3242 }
3243
3244 if ( RT_SUCCESS(rc)
3245 && cbData)
3246 {
3247 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
3248
3249 cSegs++;
3250 aRespSegs[2].pvSeg = &abResp[0];
3251 aRespSegs[2].cbSeg = cbData;
3252 }
3253 else if (RT_FAILURE(rc))
3254 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3255
3256 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3257 &aRespSegs[0], cSegs, true /*fAck*/);
3258}
3259
3260
3261/**
3262 * Processes a write control space 64 request.
3263 *
3264 * @returns VBox status code.
3265 * @param pThis The KD context.
3266 * @param pPktManip The manipulate packet request.
3267 */
3268static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3269{
3270 KDPACKETMANIPULATEHDR RespHdr;
3271 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
3272 uint32_t cbData = 0;
3273 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3274
3275 RTSGSEG aRespSegs[2];
3276 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
3277 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3278 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3279 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3280
3281 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3282 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3283
3284 aRespSegs[0].pvSeg = &RespHdr;
3285 aRespSegs[0].cbSeg = sizeof(RespHdr);
3286 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3287 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3288
3289 int rc = VINF_SUCCESS;
3290 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3291 {
3292 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3293 {
3294 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3295 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
3296 if (RT_SUCCESS(rc))
3297 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
3298 break;
3299 }
3300 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3301 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3302 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3303 default:
3304 rc = VERR_NOT_SUPPORTED;
3305 break;
3306 }
3307
3308 if (RT_FAILURE(rc))
3309 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3310 else
3311 XferCtrlSpace64.cbXfered = cbData;
3312
3313 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3314 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3315}
3316
3317
3318/**
3319 * Processes a restore breakpoint 64 request.
3320 *
3321 * @returns VBox status code.
3322 * @param pThis The KD context.
3323 * @param pPktManip The manipulate packet request.
3324 */
3325static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3326{
3327 KDPACKETMANIPULATEHDR RespHdr;
3328 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
3329 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
3330
3331 RTSGSEG aRespSegs[2];
3332 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
3333 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3334 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3335 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3336
3337 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
3338
3339 aRespSegs[0].pvSeg = &RespHdr;
3340 aRespSegs[0].cbSeg = sizeof(RespHdr);
3341 aRespSegs[1].pvSeg = &RestoreBkpt64;
3342 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
3343
3344 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
3345 if (RT_SUCCESS(rc))
3346 {
3347 rc = dbgcBpDelete(&pThis->Dbgc, pPktManip->u.RestoreBkpt.u32HndBkpt);
3348 AssertRC(rc);
3349 }
3350 else if (rc != VERR_DBGF_BP_NOT_FOUND)
3351 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3352
3353 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3354 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3355}
3356
3357
3358/**
3359 * Processes a write breakpoint 64 request.
3360 *
3361 * @returns VBox status code.
3362 * @param pThis The KD context.
3363 * @param pPktManip The manipulate packet request.
3364 */
3365static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3366{
3367 KDPACKETMANIPULATEHDR RespHdr;
3368 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
3369 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
3370
3371 RTSGSEG aRespSegs[2];
3372 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
3373 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3374 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3375 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3376
3377 aRespSegs[0].pvSeg = &RespHdr;
3378 aRespSegs[0].cbSeg = sizeof(RespHdr);
3379 aRespSegs[1].pvSeg = &WriteBkpt64;
3380 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
3381
3382 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
3383
3384 DBGFADDRESS BpAddr;
3385 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, KD_PTR_GET(pThis, pPktManip->u.WriteBkpt.u64PtrBkpt));
3386 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
3387 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
3388 if (RT_SUCCESS(rc))
3389 {
3390 rc = dbgcBpAdd(&pThis->Dbgc, WriteBkpt64.u32HndBkpt, NULL /*pszCmd*/);
3391 if (RT_FAILURE(rc))
3392 DBGFR3BpClear(pThis->Dbgc.pUVM, WriteBkpt64.u32HndBkpt);
3393 }
3394 else
3395 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3396
3397 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3398 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3399}
3400
3401
3402/**
3403 * Processes a get context extended 64 request.
3404 *
3405 * @returns VBox status code.
3406 * @param pThis The KD context.
3407 * @param pPktManip The manipulate packet request.
3408 */
3409static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3410{
3411 KDPACKETMANIPULATEHDR RespHdr;
3412 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
3413 union
3414 {
3415 NTCONTEXT64 v64;
3416 NTCONTEXT32 v32;
3417 } NtCtx;
3418 RT_ZERO(RespHdr); RT_ZERO(ContextEx); RT_ZERO(NtCtx);
3419
3420 RTSGSEG aRespSegs[3];
3421 uint32_t cSegs = 2;
3422 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
3423 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3424 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3425 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3426
3427 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
3428 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
3429 ContextEx.cbXfered = 0;
3430
3431 aRespSegs[0].pvSeg = &RespHdr;
3432 aRespSegs[0].cbSeg = sizeof(RespHdr);
3433 aRespSegs[1].pvSeg = &ContextEx;
3434 aRespSegs[1].cbSeg = sizeof(ContextEx);
3435
3436 int rc = VINF_SUCCESS;
3437 uint32_t cbCtx = pThis->f32Bit ? sizeof(NtCtx.v32) : sizeof(NtCtx.v64);
3438 if (pThis->f32Bit)
3439 dbgcKdCtxQueryNtCtx32(pThis, pPktManip->Hdr.idCpu, &NtCtx.v32, NTCONTEXT32_F_FULL);
3440 else
3441 dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx.v64, NTCONTEXT64_F_FULL);
3442 if ( RT_SUCCESS(rc)
3443 && pPktManip->u.ContextEx.offStart < cbCtx)
3444 {
3445 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3446 ContextEx.cbXfered = RT_MIN(cbCtx - ContextEx.offStart, ContextEx.cbXfer);
3447
3448 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
3449 aRespSegs[2].cbSeg = ContextEx.cbXfered;
3450 cSegs++;
3451 }
3452
3453 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3454 &aRespSegs[0], cSegs, true /*fAck*/);
3455}
3456
3457
3458/**
3459 * Processes a query memory 64 request.
3460 *
3461 * @returns VBox status code.
3462 * @param pThis The KD context.
3463 * @param pPktManip The manipulate packet request.
3464 */
3465static int dbgcKdCtxPktManipulate64QueryMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3466{
3467 KDPACKETMANIPULATEHDR RespHdr;
3468 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
3469 RT_ZERO(RespHdr); RT_ZERO(QueryMemory);
3470
3471 RTSGSEG aRespSegs[2];
3472 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY;
3473 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3474 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3475 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3476
3477 /** @todo Need DBGF API to query protection and privilege level from guest page tables. */
3478 QueryMemory.u64GCPtr = pPktManip->u.QueryMemory.u64GCPtr;
3479 QueryMemory.u32AddrSpace = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_KERNEL;
3480 QueryMemory.u32Flags = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_READ
3481 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_WRITE
3482 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_EXEC;
3483
3484 aRespSegs[0].pvSeg = &RespHdr;
3485 aRespSegs[0].cbSeg = sizeof(RespHdr);
3486 aRespSegs[1].pvSeg = &QueryMemory;
3487 aRespSegs[1].cbSeg = sizeof(QueryMemory);
3488
3489 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3490 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3491}
3492
3493
3494/**
3495 * Processes a search memory 64 request.
3496 *
3497 * @returns VBox status code.
3498 * @param pThis The KD context.
3499 * @param pPktManip The manipulate packet request.
3500 */
3501static int dbgcKdCtxPktManipulate64SearchMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3502{
3503 KDPACKETMANIPULATEHDR RespHdr;
3504 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
3505 RT_ZERO(RespHdr); RT_ZERO(SearchMemory);
3506
3507 RTSGSEG aRespSegs[2];
3508 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY;
3509 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3510 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3511 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3512
3513 SearchMemory.u64GCPtr = pPktManip->u.SearchMemory.u64GCPtr;
3514 SearchMemory.cbSearch = pPktManip->u.SearchMemory.cbSearch;
3515 SearchMemory.cbPattern = pPktManip->u.SearchMemory.cbPattern;
3516
3517 /* Validate the pattern length and start searching. */
3518 if (pPktManip->u.SearchMemory.cbPattern < sizeof(pThis->abBody) - sizeof(*pPktManip))
3519 {
3520 DBGFADDRESS StartAddress;
3521 DBGFADDRESS HitAddress;
3522 VMCPUID idCpu = pPktManip->Hdr.idCpu;
3523 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &StartAddress, pPktManip->u.SearchMemory.u64GCPtr);
3524
3525 /** @todo WindDbg sends CPU ID 32 sometimes, maybe that means continue search on last used CPU?. */
3526 if (idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM))
3527 idCpu = pThis->Dbgc.idCpu;
3528
3529 int rc = DBGFR3MemScan(pThis->Dbgc.pUVM, idCpu, &StartAddress, pPktManip->u.SearchMemory.cbSearch, 1,
3530 &pThis->abBody[sizeof(*pPktManip)], pPktManip->u.SearchMemory.cbPattern, &HitAddress);
3531 if (RT_SUCCESS(rc))
3532 SearchMemory.u64GCPtr = HitAddress.FlatPtr;
3533 else if (rc == VERR_DBGF_MEM_NOT_FOUND)
3534 RespHdr.u32NtStatus = NTSTATUS_NOT_FOUND;
3535 else
3536 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3537 }
3538 else
3539 RespHdr.u32NtStatus = NTSTATUS_BUFFER_OVERFLOW;
3540
3541 aRespSegs[0].pvSeg = &RespHdr;
3542 aRespSegs[0].cbSeg = sizeof(RespHdr);
3543 aRespSegs[1].pvSeg = &SearchMemory;
3544 aRespSegs[1].cbSeg = sizeof(SearchMemory);
3545
3546 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3547 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3548}
3549
3550
3551/**
3552 * Processes a cause bugcheck 64 request.
3553 *
3554 * @returns VBox status code.
3555 * @param pThis The KD context.
3556 * @param pPktManip The manipulate packet request.
3557 *
3558 * @note We abuse this request to initiate a native VBox debugger command prompt from the remote end
3559 * (There is monitor/Rcmd equivalent like with GDB unfortunately).
3560 */
3561static int dbgcKdCtxPktManipulate64CauseBugCheck(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3562{
3563 RT_NOREF(pPktManip);
3564 pThis->fInVBoxDbg = true;
3565 return dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3566 512 /*cbResponseMax*/);
3567}
3568
3569
3570/**
3571 * Processes a switch processor request.
3572 *
3573 * @returns VBox status code.
3574 * @param pThis The KD context.
3575 * @param pPktManip The manipulate packet request.
3576 */
3577static int dbgcKdCtxPktManipulate64SwitchProcessor(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3578{
3579 int rc = VINF_SUCCESS;
3580
3581 if (RT_UNLIKELY(pPktManip->Hdr.idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM)))
3582 {
3583 KDPACKETMANIPULATEHDR RespHdr;
3584 RT_ZERO(RespHdr);
3585
3586 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR;
3587 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3588 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3589 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Test this path. */
3590 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3591 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3592 }
3593 else
3594 {
3595 pThis->Dbgc.idCpu = pPktManip->Hdr.idCpu;
3596 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3597 }
3598
3599 return rc;
3600}
3601
3602
3603/**
3604 * Processes a manipulate packet.
3605 *
3606 * @returns VBox status code.
3607 * @param pThis The KD context.
3608 */
3609static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
3610{
3611 int rc = VINF_SUCCESS;
3612 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
3613
3614 switch (pPktManip->Hdr.idReq)
3615 {
3616 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
3617 {
3618 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
3619 break;
3620 }
3621 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
3622 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
3623 {
3624 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
3625 break;
3626 }
3627 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
3628 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
3629 {
3630 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
3631 break;
3632 }
3633 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
3634 {
3635 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
3636 break;
3637 }
3638 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
3639 {
3640 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
3641 break;
3642 }
3643 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
3644 {
3645 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
3646 break;
3647 }
3648 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
3649 {
3650 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
3651 break;
3652 }
3653 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
3654 {
3655 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
3656 break;
3657 }
3658 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
3659 {
3660 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
3661 break;
3662 }
3663 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
3664 {
3665 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
3666 break;
3667 }
3668 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
3669 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
3670 break;
3671 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
3672 {
3673 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
3674 break;
3675 }
3676 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
3677 {
3678 rc = dbgcKdCtxPktManipulate64QueryMemory(pThis, pPktManip);
3679 break;
3680 }
3681 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
3682 {
3683 rc = dbgcKdCtxPktManipulate64SearchMemory(pThis, pPktManip);
3684 break;
3685 }
3686 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK:
3687 {
3688 rc = dbgcKdCtxPktManipulate64CauseBugCheck(pThis, pPktManip);
3689 break;
3690 }
3691 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR:
3692 {
3693 rc = dbgcKdCtxPktManipulate64SwitchProcessor(pThis, pPktManip);
3694 break;
3695 }
3696 case KD_PACKET_MANIPULATE_REQ_REBOOT:
3697 {
3698 rc = VMR3Reset(pThis->Dbgc.pUVM); /* Doesn't expect an answer here. */
3699 if ( RT_SUCCESS(rc)
3700 && DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3701 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3702 break;
3703 }
3704 default:
3705 KDPACKETMANIPULATEHDR RespHdr;
3706 RT_ZERO(RespHdr);
3707
3708 RespHdr.idReq = pPktManip->Hdr.idReq;
3709 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3710 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3711 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
3712 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3713 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3714 break;
3715 }
3716
3717 return rc;
3718}
3719
3720
3721/**
3722 * Tries to detect the guest OS running in the VM looking specifically for the Windows NT kind.
3723 *
3724 * @param pThis The KD context.
3725 */
3726static void dbgcKdCtxDetectGstOs(PKDCTX pThis)
3727{
3728 pThis->pIfWinNt = NULL;
3729
3730 /* Try detecting a Windows NT guest. */
3731 char szName[64];
3732 int rc = DBGFR3OSDetect(pThis->Dbgc.pUVM, szName, sizeof(szName));
3733 if (RT_SUCCESS(rc))
3734 {
3735 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pThis->Dbgc.pUVM, DBGFOSINTERFACE_WINNT);
3736 if (pThis->pIfWinNt)
3737 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3738 else
3739 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3740 }
3741 else
3742 {
3743 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3744 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3745 }
3746
3747 if (pThis->pIfWinNt)
3748 {
3749 rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
3750 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
3751 NULL /*puBuildNumber*/, &pThis->f32Bit);
3752 AssertRC(rc);
3753 }
3754 else
3755 {
3756 /*
3757 * Try to detect bitness based on the current CPU mode which might fool us (32bit process running
3758 * inside of 64bit host).
3759 */
3760 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
3761 if (enmMode == CPUMMODE_PROTECTED)
3762 pThis->f32Bit = true;
3763 else if (enmMode == CPUMMODE_LONG)
3764 pThis->f32Bit = false;
3765 else
3766 LogRel(("DBGC/Kd: Heh, trying to debug real mode code with WinDbg are we? Good luck with that...\n"));
3767 }
3768}
3769
3770
3771/**
3772 * Processes a fully received packet.
3773 *
3774 * @returns VBox status code.
3775 * @param pThis The KD context.
3776 */
3777static int dbgcKdCtxPktProcess(PKDCTX pThis)
3778{
3779 int rc = VINF_SUCCESS;
3780
3781 pThis->fBreakinRecv = false;
3782
3783 /* Verify checksum. */
3784 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
3785 {
3786 /** @todo Check packet id. */
3787 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
3788 {
3789 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3790 rc = dbgcKdCtxPktSendAck(pThis);
3791 }
3792 if (RT_SUCCESS(rc))
3793 {
3794#ifdef LOG_ENABLED
3795 RTSGSEG Seg;
3796 Seg.pvSeg = &pThis->abBody[0];
3797 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
3798 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
3799#endif
3800
3801 switch (pThis->PktHdr.Fields.u16SubType)
3802 {
3803 case KD_PACKET_HDR_SUB_TYPE_RESET:
3804 {
3805 dbgcKdCtxDetectGstOs(pThis);
3806
3807 pThis->idPktNext = 0;
3808 rc = dbgcKdCtxPktSendReset(pThis);
3809 if (RT_SUCCESS(rc))
3810 {
3811 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3812 if (rc == VWRN_DBGF_ALREADY_HALTED)
3813 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3814 }
3815 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
3816 break;
3817 }
3818 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
3819 {
3820 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3821 rc = dbgcKdCtxPktManipulate64Process(pThis);
3822 break;
3823 }
3824 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
3825 case KD_PACKET_HDR_SUB_TYPE_RESEND:
3826 {
3827 /* Don't do anything. */
3828 rc = VINF_SUCCESS;
3829 break;
3830 }
3831 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO:
3832 {
3833 if (pThis->fInVBoxDbg)
3834 {
3835 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3836 /* Get the string and execute it. */
3837 PCKDPACKETDEBUGIO pPktDbgIo = (PCKDPACKETDEBUGIO)&pThis->abBody[0];
3838 if ( pPktDbgIo->u32Type == KD_PACKET_DEBUG_IO_GET_STRING
3839 && pPktDbgIo->u.Prompt.cbReturn <= sizeof(pThis->abBody) - sizeof(*pPktDbgIo) - 1)
3840 {
3841 if (pPktDbgIo->u.Prompt.cbReturn)
3842 {
3843 /* Terminate return value. */
3844 pThis->abBody[sizeof(*pPktDbgIo) + pPktDbgIo->u.Prompt.cbReturn] = '\0';
3845
3846 const char *pszCmd = (const char *)&pThis->abBody[sizeof(*pPktDbgIo)];
3847 /* Filter out 'exit' which is handled here directly and exits the debug loop. */
3848 if (!strcmp(pszCmd, "exit"))
3849 pThis->fInVBoxDbg = false;
3850 else
3851 {
3852 rc = pThis->Dbgc.CmdHlp.pfnExec(&pThis->Dbgc.CmdHlp, pszCmd);
3853 if (RT_SUCCESS(rc))
3854 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3855 512 /*cbResponseMax*/);
3856 else
3857 LogRel(("DBGC/Kd: Executing command \"%s\" failed with rc=%Rrc\n", pszCmd, rc));
3858 }
3859 }
3860 else
3861 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3862 512 /*cbResponseMax*/);
3863 }
3864 else
3865 LogRel(("DBGC/Kd: Received invalid DEBUG_IO packet from remote end, ignoring\n"));
3866 }
3867 else
3868 LogRel(("DBGC/Kd: Received out of band DEBUG_IO packet from remote end, ignoring\n"));
3869 break;
3870 }
3871 default:
3872 rc = VERR_NOT_IMPLEMENTED;
3873 }
3874 }
3875 }
3876 else
3877 {
3878 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3879 rc = dbgcKdCtxPktSendResend(pThis);
3880 }
3881
3882 if (pThis->fBreakinRecv)
3883 {
3884 pThis->fBreakinRecv = false;
3885 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3886 if (rc == VWRN_DBGF_ALREADY_HALTED)
3887 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3888 }
3889
3890 /* Next packet. */
3891 dbgcKdCtxPktRecvReset(pThis);
3892 return rc;
3893}
3894
3895
3896/**
3897 * Processes the received data based on the current state.
3898 *
3899 * @returns VBox status code.
3900 * @param pThis The KD context.
3901 */
3902static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
3903{
3904 int rc = VINF_SUCCESS;
3905
3906 switch (pThis->enmState)
3907 {
3908 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
3909 {
3910 /* Does it look like a valid packet start?. */
3911 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
3912 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
3913 {
3914 pThis->pbRecv = &pThis->PktHdr.ab[1];
3915 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3916 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
3917 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
3918 }
3919 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3920 {
3921 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3922 if (rc == VWRN_DBGF_ALREADY_HALTED)
3923 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3924 dbgcKdCtxPktRecvReset(pThis);
3925 }
3926 else
3927 dbgcKdCtxPktRecvReset(pThis); /* Reset and continue. */
3928 break;
3929 }
3930 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
3931 {
3932 /*
3933 * If the first and second byte differ there might be a single breakin
3934 * packet byte received and this is actually the start of a new packet.
3935 */
3936 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
3937 {
3938 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3939 {
3940 /* Halt the VM and rearrange the packet receiving state machine. */
3941 LogFlow(("DbgKd: Halting VM!\n"));
3942
3943 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3944 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
3945 pThis->pbRecv = &pThis->PktHdr.ab[1];
3946 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3947 }
3948 else
3949 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
3950 }
3951 else
3952 {
3953 /* Normal packet receive continues with the rest of the header. */
3954 pThis->pbRecv = &pThis->PktHdr.ab[2];
3955 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
3956 pThis->enmState = KDRECVSTATE_PACKET_HDR;
3957 }
3958 break;
3959 }
3960 case KDRECVSTATE_PACKET_HDR:
3961 {
3962 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
3963 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
3964 {
3965 /* Start receiving the body. */
3966 if (pThis->PktHdr.Fields.cbBody)
3967 {
3968 pThis->pbRecv = &pThis->abBody[0];
3969 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
3970 pThis->enmState = KDRECVSTATE_PACKET_BODY;
3971 }
3972 else /* No body means no trailer byte it looks like. */
3973 rc = dbgcKdCtxPktProcess(pThis);
3974 }
3975 else
3976 rc = VERR_NET_PROTOCOL_ERROR;
3977 break;
3978 }
3979 case KDRECVSTATE_PACKET_BODY:
3980 {
3981 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
3982 pThis->bTrailer = 0;
3983 pThis->pbRecv = &pThis->bTrailer;
3984 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
3985 break;
3986 }
3987 case KDRECVSTATE_PACKET_TRAILER:
3988 {
3989 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
3990 rc = dbgcKdCtxPktProcess(pThis);
3991 else
3992 rc = VERR_NET_PROTOCOL_ERROR;
3993 break;
3994 }
3995 default:
3996 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
3997 }
3998
3999 return rc;
4000}
4001
4002
4003/**
4004 * Receive data and processes complete packets.
4005 *
4006 * @returns Status code.
4007 * @param pThis The KD context.
4008 */
4009static int dbgcKdCtxRecv(PKDCTX pThis)
4010{
4011 int rc = VINF_SUCCESS;
4012
4013 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
4014
4015 if (pThis->cbRecvLeft)
4016 {
4017 size_t cbRead = 0;
4018 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
4019 if (RT_SUCCESS(rc))
4020 {
4021 pThis->tsRecvLast = RTTimeMilliTS();
4022 pThis->cbRecvLeft -= cbRead;
4023 pThis->pbRecv += cbRead;
4024 if (!pThis->cbRecvLeft)
4025 rc = dbgcKdCtxRecvDataProcess(pThis);
4026 }
4027 }
4028
4029 LogFlowFunc(("returns rc=%Rrc\n", rc));
4030 return rc;
4031}
4032
4033
4034/**
4035 * Processes debugger events.
4036 *
4037 * @returns VBox status code.
4038 * @param pThis The KD context data.
4039 * @param pEvent Pointer to event data.
4040 */
4041static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
4042{
4043 /*
4044 * Process the event.
4045 */
4046 PDBGC pDbgc = &pThis->Dbgc;
4047 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
4048 pThis->Dbgc.iArg = 0;
4049 int rc = VINF_SUCCESS;
4050 VMCPUID idCpuOld = pDbgc->idCpu;
4051 pDbgc->idCpu = pEvent->idCpu;
4052 switch (pEvent->enmType)
4053 {
4054 /*
4055 * The first part is events we have initiated with commands.
4056 */
4057 case DBGFEVENT_HALT_DONE:
4058 {
4059 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
4060 break;
4061 }
4062
4063 /*
4064 * The second part is events which can occur at any time.
4065 */
4066 case DBGFEVENT_FATAL_ERROR:
4067 {
4068 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
4069 dbgcGetEventCtx(pEvent->enmCtx));
4070 if (RT_SUCCESS(rc))
4071 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4072 break;
4073 }
4074
4075 case DBGFEVENT_BREAKPOINT:
4076 case DBGFEVENT_BREAKPOINT_IO:
4077 case DBGFEVENT_BREAKPOINT_MMIO:
4078 case DBGFEVENT_BREAKPOINT_HYPER:
4079 {
4080 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.hBp);
4081 switch (rc)
4082 {
4083 case VERR_DBGC_BP_NOT_FOUND:
4084 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
4085 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
4086 break;
4087
4088 case VINF_DBGC_BP_NO_COMMAND:
4089 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
4090 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
4091 break;
4092
4093 case VINF_BUFFER_OVERFLOW:
4094 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
4095 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
4096 break;
4097
4098 default:
4099 break;
4100 }
4101 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL))
4102 {
4103 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4104
4105 /* Set the resume flag to ignore the breakpoint when resuming execution. */
4106 if ( RT_SUCCESS(rc)
4107 && pEvent->enmType == DBGFEVENT_BREAKPOINT)
4108 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
4109 }
4110
4111 /* Figure out the breakpoint and set the triggered flag for emulation of DR6. */
4112 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
4113 {
4114 if (pThis->aHwBp[i].hDbgfBp == pEvent->u.Bp.hBp)
4115 {
4116 pThis->aHwBp[i].fTriggered = true;
4117 break;
4118 }
4119 }
4120
4121 if (RT_SUCCESS(rc))
4122 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
4123 break;
4124 }
4125
4126 case DBGFEVENT_STEPPED:
4127 case DBGFEVENT_STEPPED_HYPER:
4128 {
4129 pThis->fSingleStepped = true; /* For emulation of DR6. */
4130 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
4131 break;
4132 }
4133
4134 case DBGFEVENT_ASSERTION_HYPER:
4135 {
4136 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4137 "\ndbgf event: Hypervisor Assertion! (%s)\n"
4138 "%s"
4139 "%s"
4140 "\n",
4141 dbgcGetEventCtx(pEvent->enmCtx),
4142 pEvent->u.Assert.pszMsg1,
4143 pEvent->u.Assert.pszMsg2);
4144 if (RT_SUCCESS(rc))
4145 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4146 break;
4147 }
4148
4149 case DBGFEVENT_DEV_STOP:
4150 {
4151 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4152 "\n"
4153 "dbgf event: DBGFSTOP (%s)\n"
4154 "File: %s\n"
4155 "Line: %d\n"
4156 "Function: %s\n",
4157 dbgcGetEventCtx(pEvent->enmCtx),
4158 pEvent->u.Src.pszFile,
4159 pEvent->u.Src.uLine,
4160 pEvent->u.Src.pszFunction);
4161 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
4162 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4163 "Message: %s\n",
4164 pEvent->u.Src.pszMessage);
4165 if (RT_SUCCESS(rc))
4166 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4167 break;
4168 }
4169
4170
4171 case DBGFEVENT_INVALID_COMMAND:
4172 {
4173 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
4174 break;
4175 }
4176
4177 case DBGFEVENT_POWERING_OFF:
4178 {
4179 pThis->Dbgc.fReady = false;
4180 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, false);
4181 rc = VERR_GENERAL_FAILURE;
4182 break;
4183 }
4184
4185 default:
4186 {
4187 /*
4188 * Probably a generic event. Look it up to find its name.
4189 */
4190 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
4191 if (pEvtDesc)
4192 {
4193 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
4194 {
4195 Assert(pEvtDesc->pszDesc);
4196 Assert(pEvent->u.Generic.cArgs == 1);
4197 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
4198 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
4199 }
4200 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
4201 {
4202 Assert(pEvent->u.Generic.cArgs >= 5);
4203 char szDetails[512];
4204 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
4205 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
4206 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
4207 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
4208 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
4209 szDetails);
4210 }
4211 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
4212 || pEvent->u.Generic.cArgs > 1
4213 || ( pEvent->u.Generic.cArgs == 1
4214 && pEvent->u.Generic.auArgs[0] != 0))
4215 {
4216 if (pEvtDesc->pszDesc)
4217 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
4218 pEvtDesc->pszName, pEvtDesc->pszDesc);
4219 else
4220 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
4221 if (RT_SUCCESS(rc))
4222 {
4223 if (pEvent->u.Generic.cArgs <= 1)
4224 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
4225 else
4226 {
4227 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
4228 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
4229 if (RT_SUCCESS(rc))
4230 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
4231 }
4232 }
4233 }
4234 else
4235 {
4236 if (pEvtDesc->pszDesc)
4237 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
4238 pEvtDesc->pszName, pEvtDesc->pszDesc);
4239 else
4240 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
4241 }
4242 }
4243 else
4244 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
4245 break;
4246 }
4247 }
4248
4249 pDbgc->idCpu = idCpuOld;
4250 return rc;
4251}
4252
4253
4254/**
4255 * Handle a receive timeout.
4256 *
4257 * @returns VBox status code.
4258 * @param pThis Pointer to the KD context.
4259 */
4260static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
4261{
4262 int rc = VINF_SUCCESS;
4263
4264 LogFlowFunc(("pThis=%p\n", pThis));
4265
4266 /*
4267 * If a single breakin packet byte was received but the header is otherwise incomplete
4268 * the VM is halted and a state change will be sent in the event processing loop.
4269 */
4270 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
4271 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
4272 {
4273 LogFlow(("DbgKd: Halting VM!\n"));
4274 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
4275 }
4276 else /* Send a reset packet */ /** @todo Figure out the semantics in this case exactly. */
4277 rc = dbgcKdCtxPktSendReset(pThis);
4278
4279 dbgcKdCtxPktRecvReset(pThis);
4280
4281 LogFlowFunc(("rc=%Rrc\n", rc));
4282 return rc;
4283}
4284
4285
4286/**
4287 * @copydoc DBGC::pfnOutput
4288 */
4289static DECLCALLBACK(int) dbgcKdOutput(void *pvUser, const char *pachChars, size_t cbChars)
4290{
4291 PKDCTX pThis = (PKDCTX)pvUser;
4292
4293 return dbgcKdCtxDebugIoStrSend(pThis, pThis->Dbgc.idCpu, pachChars, cbChars);
4294}
4295
4296
4297/**
4298 * Run the debugger console.
4299 *
4300 * @returns VBox status code.
4301 * @param pThis Pointer to the KD context.
4302 */
4303static int dbgcKdRun(PKDCTX pThis)
4304{
4305 /*
4306 * We're ready for commands now.
4307 */
4308 pThis->Dbgc.fReady = true;
4309 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, true);
4310
4311 /*
4312 * Main Debugger Loop.
4313 *
4314 * This loop will either block on waiting for input or on waiting on
4315 * debug events. If we're forwarding the log we cannot wait for long
4316 * before we must flush the log.
4317 */
4318 int rc;
4319 for (;;)
4320 {
4321 rc = VERR_SEM_OUT_OF_TURN;
4322 if (pThis->Dbgc.pUVM)
4323 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
4324
4325 if (RT_SUCCESS(rc))
4326 {
4327 /*
4328 * Wait for a debug event.
4329 */
4330 DBGFEVENT Evt;
4331 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
4332 if (RT_SUCCESS(rc))
4333 {
4334 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
4335 if (RT_FAILURE(rc))
4336 break;
4337 }
4338 else if (rc != VERR_TIMEOUT)
4339 break;
4340
4341 /*
4342 * Check for input.
4343 */
4344 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 0))
4345 {
4346 rc = dbgcKdCtxRecv(pThis);
4347 if (RT_FAILURE(rc))
4348 break;
4349 }
4350 }
4351 else if (rc == VERR_SEM_OUT_OF_TURN)
4352 {
4353 /*
4354 * Wait for input.
4355 */
4356 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 1000))
4357 rc = dbgcKdCtxRecv(pThis);
4358 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
4359 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
4360 rc = dbgcKdCtxRecvTimeout(pThis);
4361
4362 if (RT_FAILURE(rc))
4363 break;
4364 }
4365 else
4366 break;
4367 }
4368
4369 return rc;
4370}
4371
4372
4373/**
4374 * Creates a KD context instance with the given backend.
4375 *
4376 * @returns VBox status code.
4377 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
4378 * @param pIo Pointer to the I/O callback table.
4379 * @param fFlags Flags controlling the behavior.
4380 */
4381static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PCDBGCIO pIo, unsigned fFlags)
4382{
4383 /*
4384 * Validate input.
4385 */
4386 AssertPtrReturn(pIo, VERR_INVALID_POINTER);
4387 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
4388
4389 /*
4390 * Allocate and initialize.
4391 */
4392 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
4393 if (!pThis)
4394 return VERR_NO_MEMORY;
4395
4396 dbgcInitCmdHlp(&pThis->Dbgc);
4397 /*
4398 * This is compied from the native debug console (will be used for monitor commands)
4399 * in DBGCConsole.cpp. Try to keep both functions in sync.
4400 */
4401 pThis->Dbgc.pIo = pIo;
4402 pThis->Dbgc.pfnOutput = dbgcKdOutput;
4403 pThis->Dbgc.pvOutputUser = pThis;
4404 pThis->Dbgc.pVM = NULL;
4405 pThis->Dbgc.pUVM = NULL;
4406 pThis->Dbgc.idCpu = 0;
4407 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
4408 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
4409 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
4410 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
4411 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
4412 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
4413 //pThis->Dbgc.fLog = false;
4414 pThis->Dbgc.fRegTerse = true;
4415 pThis->Dbgc.fStepTraceRegs = true;
4416 //pThis->Dbgc.cPagingHierarchyDumps = 0;
4417 //pThis->Dbgc.DisasmPos = {0};
4418 //pThis->Dbgc.SourcePos = {0};
4419 //pThis->Dbgc.DumpPos = {0};
4420 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
4421 //pThis->Dbgc.cbDumpElement = 0;
4422 //pThis->Dbgc.cVars = 0;
4423 //pThis->Dbgc.paVars = NULL;
4424 //pThis->Dbgc.pPlugInHead = NULL;
4425 //pThis->Dbgc.pFirstBp = NULL;
4426 //pThis->Dbgc.abSearch = {0};
4427 //pThis->Dbgc.cbSearch = 0;
4428 pThis->Dbgc.cbSearchUnit = 1;
4429 pThis->Dbgc.cMaxSearchHits = 1;
4430 //pThis->Dbgc.SearchAddr = {0};
4431 //pThis->Dbgc.cbSearchRange = 0;
4432
4433 //pThis->Dbgc.uInputZero = 0;
4434 //pThis->Dbgc.iRead = 0;
4435 //pThis->Dbgc.iWrite = 0;
4436 //pThis->Dbgc.cInputLines = 0;
4437 //pThis->Dbgc.fInputOverflow = false;
4438 pThis->Dbgc.fReady = true;
4439 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
4440 //pThis->Dbgc.iArg = 0;
4441 //pThis->Dbgc.rcOutput = 0;
4442 //pThis->Dbgc.rcCmd = 0;
4443
4444 //pThis->Dbgc.pszHistoryFile = NULL;
4445 //pThis->Dbgc.pszGlobalInitScript = NULL;
4446 //pThis->Dbgc.pszLocalInitScript = NULL;
4447
4448 dbgcEvalInit();
4449
4450 pThis->fBreakinRecv = false;
4451 pThis->fInVBoxDbg = false;
4452 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
4453 pThis->pIfWinNt = NULL;
4454 pThis->f32Bit = false;
4455 dbgcKdCtxPktRecvReset(pThis);
4456
4457 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
4458 {
4459 PKDCTXHWBP pBp = &pThis->aHwBp[i];
4460 pBp->hDbgfBp = NIL_DBGFBP;
4461 }
4462
4463 dbgcKdCtxHwBpReset(pThis);
4464
4465 *ppKdCtx = pThis;
4466 return VINF_SUCCESS;
4467}
4468
4469
4470/**
4471 * Destroys the given KD context.
4472 *
4473 * @param pThis The KD context to destroy.
4474 */
4475static void dbgcKdCtxDestroy(PKDCTX pThis)
4476{
4477 AssertPtr(pThis);
4478
4479 pThis->pIfWinNt = NULL;
4480
4481 /* Detach from the VM. */
4482 if (pThis->Dbgc.pUVM)
4483 DBGFR3Detach(pThis->Dbgc.pUVM);
4484
4485 /* Free config strings. */
4486 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
4487 pThis->Dbgc.pszGlobalInitScript = NULL;
4488 RTStrFree(pThis->Dbgc.pszLocalInitScript);
4489 pThis->Dbgc.pszLocalInitScript = NULL;
4490 RTStrFree(pThis->Dbgc.pszHistoryFile);
4491 pThis->Dbgc.pszHistoryFile = NULL;
4492
4493 /* Finally, free the instance memory. */
4494 RTMemFree(pThis);
4495}
4496
4497
4498DECL_HIDDEN_CALLBACK(int) dbgcKdStubRunloop(PUVM pUVM, PCDBGCIO pIo, unsigned fFlags)
4499{
4500 /*
4501 * Validate input.
4502 */
4503 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
4504 PVM pVM = NULL;
4505 if (pUVM)
4506 {
4507 pVM = VMR3GetVM(pUVM);
4508 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
4509 }
4510
4511 /*
4512 * Allocate and initialize instance data
4513 */
4514 PKDCTX pThis;
4515 int rc = dbgcKdCtxCreate(&pThis, pIo, fFlags);
4516 if (RT_FAILURE(rc))
4517 return rc;
4518 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
4519 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
4520
4521 /*
4522 * Attach to the specified VM.
4523 */
4524 if (RT_SUCCESS(rc) && pUVM)
4525 {
4526 rc = DBGFR3Attach(pUVM);
4527 if (RT_SUCCESS(rc))
4528 {
4529 pThis->Dbgc.pVM = pVM;
4530 pThis->Dbgc.pUVM = pUVM;
4531 pThis->Dbgc.idCpu = 0;
4532 }
4533 else
4534 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
4535 }
4536
4537 /*
4538 * Load plugins.
4539 */
4540 if (RT_SUCCESS(rc))
4541 {
4542 if (pVM)
4543 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
4544 dbgcEventInit(&pThis->Dbgc);
4545
4546 /*
4547 * Run the debugger main loop.
4548 */
4549 rc = dbgcKdRun(pThis);
4550 dbgcEventTerm(&pThis->Dbgc);
4551 }
4552
4553 /*
4554 * Cleanup console debugger session.
4555 */
4556 dbgcKdCtxDestroy(pThis);
4557 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
4558}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle
ContactPrivacy/Do Not Sell My InfoTerms of Use