VirtualBox

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

Last change on this file since 103574 was 103433, checked in by vboxsync, 10 months ago

Debugger: Some warning fixes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 170.0 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 103433 2024-02-19 12:11:34Z 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
2869 /* Read instruction bytes. */
2870 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
2871 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
2872 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
2873 if (RT_SUCCESS(rc))
2874 {
2875 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2876 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
2877 &StateChange64, sizeof(StateChange64), false /*fAck*/);
2878 }
2879 }
2880
2881 LogFlowFunc(("returns %Rrc\n", rc));
2882 return rc;
2883}
2884
2885
2886/**
2887 * Processes a get version 64 request.
2888 *
2889 * @returns VBox status code.
2890 * @param pThis The KD context.
2891 * @param pPktManip The manipulate packet request.
2892 */
2893static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2894{
2895 KDPACKETMANIPULATE64 Resp;
2896 RT_ZERO(Resp);
2897
2898 /* Fill in the generic part. */
2899 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
2900 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2901 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
2902 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
2903
2904 /* Build our own response in case there is no Windows interface available. */
2905 uint32_t NtBuildNumber = 0x0f2800; /* Used when there is no NT interface available, which probably breaks symbol loading. */
2906 bool f32Bit = false;
2907 if (pThis->pIfWinNt)
2908 {
2909 int rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
2910 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
2911 &NtBuildNumber, &f32Bit);
2912 if (RT_SUCCESS(rc))
2913 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
2914 &Resp.u.GetVersion.u64PtrKernBase,
2915 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2916 }
2917
2918 /* Fill in the request specific part. */
2919 Resp.u.GetVersion.u16VersMaj = NtBuildNumber >> 16;
2920 Resp.u.GetVersion.u16VersMin = NtBuildNumber & UINT32_C(0xffff);
2921 Resp.u.GetVersion.u8VersProtocol = 0x6; /* From a Windows 10 guest. */
2922 Resp.u.GetVersion.u8VersKdSecondary = pThis->f32Bit ? 0 : 0x2; /* amd64 has a versioned context (0 and 1 are obsolete). */
2923 Resp.u.GetVersion.fFlags = KD_PACKET_MANIPULATE64_GET_VERSION_F_MP;
2924 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
2925 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
2926 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_MAX - KD_PACKET_MANIPULATE_REQ_MIN;
2927 Resp.u.GetVersion.u64PtrDebuggerDataList = 0;
2928
2929 if (f32Bit)
2930 {
2931 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_I386;
2932 Resp.u.GetVersion.u64PtrKernBase = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrKernBase);
2933 Resp.u.GetVersion.u64PtrPsLoadedModuleList = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2934 }
2935 else
2936 {
2937 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
2938 Resp.u.GetVersion.fFlags |= KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64;
2939 }
2940
2941 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2942 &Resp, sizeof(Resp), true /*fAck*/);
2943}
2944
2945
2946/**
2947 * Processes a read memory 64 request.
2948 *
2949 * @returns VBox status code.
2950 * @param pThis The KD context.
2951 * @param pPktManip The manipulate packet request.
2952 */
2953static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2954{
2955 KDPACKETMANIPULATEHDR RespHdr;
2956 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2957 uint8_t abMem[_4K];
2958 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2959
2960 DBGFADDRESS AddrRead;
2961 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
2962 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
2963 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2964 else
2965 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2966
2967 RTSGSEG aRespSegs[3];
2968 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2969 RespHdr.idReq = pPktManip->Hdr.idReq;
2970 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2971 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2972 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2973
2974 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2975 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2976 XferMem64.cbXfered = (uint32_t)cbRead;
2977
2978 aRespSegs[0].pvSeg = &RespHdr;
2979 aRespSegs[0].cbSeg = sizeof(RespHdr);
2980 aRespSegs[1].pvSeg = &XferMem64;
2981 aRespSegs[1].cbSeg = sizeof(XferMem64);
2982
2983 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
2984 if (RT_SUCCESS(rc))
2985 {
2986 cSegs++;
2987 aRespSegs[2].pvSeg = &abMem[0];
2988 aRespSegs[2].cbSeg = cbRead;
2989 }
2990 else
2991 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2992
2993 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2994 &aRespSegs[0], cSegs, true /*fAck*/);
2995}
2996
2997
2998/**
2999 * Processes a write memory 64 request.
3000 *
3001 * @returns VBox status code.
3002 * @param pThis The KD context.
3003 * @param pPktManip The manipulate packet request.
3004 */
3005static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3006{
3007 KDPACKETMANIPULATEHDR RespHdr;
3008 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
3009 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
3010
3011 DBGFADDRESS AddrWrite;
3012 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3013 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
3014 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
3015 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
3016 else
3017 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
3018
3019 RTSGSEG aRespSegs[2];
3020 uint32_t cSegs = 2;
3021 RespHdr.idReq = pPktManip->Hdr.idReq;
3022 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3023 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3024 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3025
3026 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
3027 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
3028 XferMem64.cbXfered = (uint32_t)cbWrite;
3029
3030 aRespSegs[0].pvSeg = &RespHdr;
3031 aRespSegs[0].cbSeg = sizeof(RespHdr);
3032 aRespSegs[1].pvSeg = &XferMem64;
3033 aRespSegs[1].cbSeg = sizeof(XferMem64);
3034
3035 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
3036 if (RT_FAILURE(rc))
3037 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3038
3039 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3040 &aRespSegs[0], cSegs, true /*fAck*/);
3041}
3042
3043
3044/**
3045 * Processes a continue request.
3046 *
3047 * @returns VBox status code.
3048 * @param pThis The KD context.
3049 * @param pPktManip The manipulate packet request.
3050 */
3051static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3052{
3053 RT_NOREF(pPktManip);
3054 int rc = VINF_SUCCESS;
3055
3056 /* No response, just resume. */
3057 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3058 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3059
3060 return rc;
3061}
3062
3063
3064/**
3065 * Processes a continue request.
3066 *
3067 * @returns VBox status code.
3068 * @param pThis The KD context.
3069 * @param pPktManip The manipulate packet request.
3070 */
3071static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3072{
3073 int rc = VINF_SUCCESS;
3074
3075 /* Update DR7. */
3076 if (pThis->f32Bit)
3077 rc = dbgcKdCtxHwBpDr7Update(pThis, pPktManip->u.Continue2.u.x86.u32RegDr7);
3078 else
3079 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pPktManip->u.Continue2.u.amd64.u64RegDr7);
3080
3081 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
3082 if (pPktManip->u.Continue2.fTrace)
3083 {
3084 PDBGFADDRESS pStackPop = NULL;
3085 RTGCPTR cbStackPop = 0;
3086 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
3087 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
3088 }
3089 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3090 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3091
3092 return rc;
3093}
3094
3095
3096/**
3097 * Processes a set context request.
3098 *
3099 * @returns VBox status code.
3100 * @param pThis The KD context.
3101 * @param pPktManip The manipulate packet request.
3102 */
3103static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3104{
3105 KDPACKETMANIPULATEHDR RespHdr;
3106 KDPACKETMANIPULATE_SETCONTEXT SetContext;
3107 RT_ZERO(RespHdr); RT_ZERO(SetContext);
3108
3109 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3110
3111 RTSGSEG aRespSegs[2];
3112 uint32_t cSegs = 2;
3113 RespHdr.idReq = pPktManip->Hdr.idReq;
3114 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3115 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3116 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3117
3118 /** @todo What do these flags mean? Can't be the context state to set because the valid one is
3119 * in NTCONTEXT64::fContext (observed with WinDbg). */
3120 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
3121
3122 aRespSegs[0].pvSeg = &RespHdr;
3123 aRespSegs[0].cbSeg = sizeof(RespHdr);
3124 aRespSegs[1].pvSeg = &SetContext;
3125 aRespSegs[1].cbSeg = sizeof(SetContext);
3126
3127 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, pNtCtx->fContext);
3128 if (RT_FAILURE(rc))
3129 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3130
3131 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3132 &aRespSegs[0], cSegs, true /*fAck*/);
3133}
3134
3135
3136/**
3137 * Processes a read control space 64 request.
3138 *
3139 * @returns VBox status code.
3140 * @param pThis The KD context.
3141 * @param pPktManip The manipulate packet request.
3142 */
3143static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3144{
3145 KDPACKETMANIPULATEHDR RespHdr;
3146 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
3147 uint8_t abResp[sizeof(NTKCONTEXT64)];
3148 uint32_t cbData = 0;
3149 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3150 RT_ZERO(abResp);
3151
3152 RTSGSEG aRespSegs[3];
3153 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
3154 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
3155 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3156 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3157 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3158
3159 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3160 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3161
3162 aRespSegs[0].pvSeg = &RespHdr;
3163 aRespSegs[0].cbSeg = sizeof(RespHdr);
3164 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3165 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3166
3167 int rc = VINF_SUCCESS;
3168 if (pThis->f32Bit)
3169 {
3170 if (pPktManip->u.XferCtrlSpace.u64IdXfer == sizeof(NTCONTEXT32))
3171 {
3172 /* Queries the kernel context. */
3173 rc = dbgcKdCtxQueryNtKCtx32(pThis, RespHdr.idCpu, (PNTKCONTEXT32)&abResp[0]);
3174 if (RT_SUCCESS(rc))
3175 cbData = sizeof(NTKCONTEXT32);
3176 }
3177 }
3178 else
3179 {
3180 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3181 {
3182 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3183 {
3184 if (pThis->pIfWinNt)
3185 {
3186 RTGCUINTPTR GCPtrKpcr = 0;
3187
3188 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(), RespHdr.idCpu,
3189 &GCPtrKpcr, NULL /*pKpcrb*/);
3190 if (RT_SUCCESS(rc))
3191 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
3192 }
3193
3194 cbData = sizeof(RTGCUINTPTR);
3195 break;
3196 }
3197 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3198 {
3199 if (pThis->pIfWinNt)
3200 {
3201 RTGCUINTPTR GCPtrKpcrb = 0;
3202
3203 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(), RespHdr.idCpu,
3204 NULL /*pKpcr*/, &GCPtrKpcrb);
3205 if (RT_SUCCESS(rc))
3206 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
3207 }
3208
3209 cbData = sizeof(RTGCUINTPTR);
3210 break;
3211 }
3212 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3213 {
3214 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
3215 if (RT_SUCCESS(rc))
3216 cbData = sizeof(NTKCONTEXT64);
3217 break;
3218 }
3219 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3220 {
3221 if (pThis->pIfWinNt)
3222 {
3223 RTGCUINTPTR GCPtrCurThrd = 0;
3224
3225 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
3226 RespHdr.idCpu, &GCPtrCurThrd);
3227 if (RT_SUCCESS(rc))
3228 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
3229 }
3230
3231 cbData = sizeof(RTGCUINTPTR);
3232 break;
3233 }
3234 default:
3235 rc = VERR_NOT_SUPPORTED;
3236 break;
3237 }
3238 }
3239
3240 if ( RT_SUCCESS(rc)
3241 && cbData)
3242 {
3243 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
3244
3245 cSegs++;
3246 aRespSegs[2].pvSeg = &abResp[0];
3247 aRespSegs[2].cbSeg = cbData;
3248 }
3249 else if (RT_FAILURE(rc))
3250 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3251
3252 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3253 &aRespSegs[0], cSegs, true /*fAck*/);
3254}
3255
3256
3257/**
3258 * Processes a write control space 64 request.
3259 *
3260 * @returns VBox status code.
3261 * @param pThis The KD context.
3262 * @param pPktManip The manipulate packet request.
3263 */
3264static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3265{
3266 KDPACKETMANIPULATEHDR RespHdr;
3267 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
3268 uint32_t cbData = 0;
3269 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3270
3271 RTSGSEG aRespSegs[2];
3272 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
3273 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3274 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3275 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3276
3277 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3278 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3279
3280 aRespSegs[0].pvSeg = &RespHdr;
3281 aRespSegs[0].cbSeg = sizeof(RespHdr);
3282 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3283 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3284
3285 int rc = VINF_SUCCESS;
3286 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3287 {
3288 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3289 {
3290 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3291 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
3292 if (RT_SUCCESS(rc))
3293 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
3294 break;
3295 }
3296 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3297 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3298 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3299 default:
3300 rc = VERR_NOT_SUPPORTED;
3301 break;
3302 }
3303
3304 if (RT_FAILURE(rc))
3305 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3306 else
3307 XferCtrlSpace64.cbXfered = cbData;
3308
3309 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3310 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3311}
3312
3313
3314/**
3315 * Processes a restore breakpoint 64 request.
3316 *
3317 * @returns VBox status code.
3318 * @param pThis The KD context.
3319 * @param pPktManip The manipulate packet request.
3320 */
3321static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3322{
3323 KDPACKETMANIPULATEHDR RespHdr;
3324 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
3325 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
3326
3327 RTSGSEG aRespSegs[2];
3328 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
3329 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3330 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3331 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3332
3333 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
3334
3335 aRespSegs[0].pvSeg = &RespHdr;
3336 aRespSegs[0].cbSeg = sizeof(RespHdr);
3337 aRespSegs[1].pvSeg = &RestoreBkpt64;
3338 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
3339
3340 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
3341 if (RT_SUCCESS(rc))
3342 {
3343 rc = dbgcBpDelete(&pThis->Dbgc, pPktManip->u.RestoreBkpt.u32HndBkpt);
3344 AssertRC(rc);
3345 }
3346 else if (rc != VERR_DBGF_BP_NOT_FOUND)
3347 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3348
3349 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3350 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3351}
3352
3353
3354/**
3355 * Processes a write breakpoint 64 request.
3356 *
3357 * @returns VBox status code.
3358 * @param pThis The KD context.
3359 * @param pPktManip The manipulate packet request.
3360 */
3361static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3362{
3363 KDPACKETMANIPULATEHDR RespHdr;
3364 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
3365 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
3366
3367 RTSGSEG aRespSegs[2];
3368 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
3369 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3370 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3371 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3372
3373 aRespSegs[0].pvSeg = &RespHdr;
3374 aRespSegs[0].cbSeg = sizeof(RespHdr);
3375 aRespSegs[1].pvSeg = &WriteBkpt64;
3376 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
3377
3378 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
3379
3380 DBGFADDRESS BpAddr;
3381 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, KD_PTR_GET(pThis, pPktManip->u.WriteBkpt.u64PtrBkpt));
3382 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
3383 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
3384 if (RT_SUCCESS(rc))
3385 {
3386 rc = dbgcBpAdd(&pThis->Dbgc, WriteBkpt64.u32HndBkpt, NULL /*pszCmd*/);
3387 if (RT_FAILURE(rc))
3388 DBGFR3BpClear(pThis->Dbgc.pUVM, WriteBkpt64.u32HndBkpt);
3389 }
3390 else
3391 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3392
3393 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3394 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3395}
3396
3397
3398/**
3399 * Processes a get context extended 64 request.
3400 *
3401 * @returns VBox status code.
3402 * @param pThis The KD context.
3403 * @param pPktManip The manipulate packet request.
3404 */
3405static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3406{
3407 KDPACKETMANIPULATEHDR RespHdr;
3408 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
3409 union
3410 {
3411 NTCONTEXT64 v64;
3412 NTCONTEXT32 v32;
3413 } NtCtx;
3414 RT_ZERO(RespHdr); RT_ZERO(ContextEx); RT_ZERO(NtCtx);
3415
3416 RTSGSEG aRespSegs[3];
3417 uint32_t cSegs = 2;
3418 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
3419 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3420 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3421 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3422
3423 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
3424 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
3425 ContextEx.cbXfered = 0;
3426
3427 aRespSegs[0].pvSeg = &RespHdr;
3428 aRespSegs[0].cbSeg = sizeof(RespHdr);
3429 aRespSegs[1].pvSeg = &ContextEx;
3430 aRespSegs[1].cbSeg = sizeof(ContextEx);
3431
3432 int rc = VINF_SUCCESS;
3433 uint32_t cbCtx = pThis->f32Bit ? sizeof(NtCtx.v32) : sizeof(NtCtx.v64);
3434 if (pThis->f32Bit)
3435 dbgcKdCtxQueryNtCtx32(pThis, pPktManip->Hdr.idCpu, &NtCtx.v32, NTCONTEXT32_F_FULL);
3436 else
3437 dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx.v64, NTCONTEXT64_F_FULL);
3438 if ( RT_SUCCESS(rc)
3439 && pPktManip->u.ContextEx.offStart < cbCtx)
3440 {
3441 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3442 ContextEx.cbXfered = RT_MIN(cbCtx - ContextEx.offStart, ContextEx.cbXfer);
3443
3444 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
3445 aRespSegs[2].cbSeg = ContextEx.cbXfered;
3446 cSegs++;
3447 }
3448
3449 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3450 &aRespSegs[0], cSegs, true /*fAck*/);
3451}
3452
3453
3454/**
3455 * Processes a query memory 64 request.
3456 *
3457 * @returns VBox status code.
3458 * @param pThis The KD context.
3459 * @param pPktManip The manipulate packet request.
3460 */
3461static int dbgcKdCtxPktManipulate64QueryMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3462{
3463 KDPACKETMANIPULATEHDR RespHdr;
3464 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
3465 RT_ZERO(RespHdr); RT_ZERO(QueryMemory);
3466
3467 RTSGSEG aRespSegs[2];
3468 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY;
3469 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3470 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3471 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3472
3473 /** @todo Need DBGF API to query protection and privilege level from guest page tables. */
3474 QueryMemory.u64GCPtr = pPktManip->u.QueryMemory.u64GCPtr;
3475 QueryMemory.u32AddrSpace = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_KERNEL;
3476 QueryMemory.u32Flags = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_READ
3477 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_WRITE
3478 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_EXEC;
3479
3480 aRespSegs[0].pvSeg = &RespHdr;
3481 aRespSegs[0].cbSeg = sizeof(RespHdr);
3482 aRespSegs[1].pvSeg = &QueryMemory;
3483 aRespSegs[1].cbSeg = sizeof(QueryMemory);
3484
3485 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3486 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3487}
3488
3489
3490/**
3491 * Processes a search memory 64 request.
3492 *
3493 * @returns VBox status code.
3494 * @param pThis The KD context.
3495 * @param pPktManip The manipulate packet request.
3496 */
3497static int dbgcKdCtxPktManipulate64SearchMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3498{
3499 KDPACKETMANIPULATEHDR RespHdr;
3500 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
3501 RT_ZERO(RespHdr); RT_ZERO(SearchMemory);
3502
3503 RTSGSEG aRespSegs[2];
3504 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY;
3505 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3506 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3507 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3508
3509 SearchMemory.u64GCPtr = pPktManip->u.SearchMemory.u64GCPtr;
3510 SearchMemory.cbSearch = pPktManip->u.SearchMemory.cbSearch;
3511 SearchMemory.cbPattern = pPktManip->u.SearchMemory.cbPattern;
3512
3513 /* Validate the pattern length and start searching. */
3514 if (pPktManip->u.SearchMemory.cbPattern < sizeof(pThis->abBody) - sizeof(*pPktManip))
3515 {
3516 DBGFADDRESS StartAddress;
3517 DBGFADDRESS HitAddress;
3518 VMCPUID idCpu = pPktManip->Hdr.idCpu;
3519 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &StartAddress, pPktManip->u.SearchMemory.u64GCPtr);
3520
3521 /** @todo WindDbg sends CPU ID 32 sometimes, maybe that means continue search on last used CPU?. */
3522 if (idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM))
3523 idCpu = pThis->Dbgc.idCpu;
3524
3525 int rc = DBGFR3MemScan(pThis->Dbgc.pUVM, idCpu, &StartAddress, pPktManip->u.SearchMemory.cbSearch, 1,
3526 &pThis->abBody[sizeof(*pPktManip)], pPktManip->u.SearchMemory.cbPattern, &HitAddress);
3527 if (RT_SUCCESS(rc))
3528 SearchMemory.u64GCPtr = HitAddress.FlatPtr;
3529 else if (rc == VERR_DBGF_MEM_NOT_FOUND)
3530 RespHdr.u32NtStatus = NTSTATUS_NOT_FOUND;
3531 else
3532 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3533 }
3534 else
3535 RespHdr.u32NtStatus = NTSTATUS_BUFFER_OVERFLOW;
3536
3537 aRespSegs[0].pvSeg = &RespHdr;
3538 aRespSegs[0].cbSeg = sizeof(RespHdr);
3539 aRespSegs[1].pvSeg = &SearchMemory;
3540 aRespSegs[1].cbSeg = sizeof(SearchMemory);
3541
3542 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3543 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3544}
3545
3546
3547/**
3548 * Processes a cause bugcheck 64 request.
3549 *
3550 * @returns VBox status code.
3551 * @param pThis The KD context.
3552 * @param pPktManip The manipulate packet request.
3553 *
3554 * @note We abuse this request to initiate a native VBox debugger command prompt from the remote end
3555 * (There is monitor/Rcmd equivalent like with GDB unfortunately).
3556 */
3557static int dbgcKdCtxPktManipulate64CauseBugCheck(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3558{
3559 RT_NOREF(pPktManip);
3560 pThis->fInVBoxDbg = true;
3561 return dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3562 512 /*cbResponseMax*/);
3563}
3564
3565
3566/**
3567 * Processes a switch processor request.
3568 *
3569 * @returns VBox status code.
3570 * @param pThis The KD context.
3571 * @param pPktManip The manipulate packet request.
3572 */
3573static int dbgcKdCtxPktManipulate64SwitchProcessor(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3574{
3575 int rc = VINF_SUCCESS;
3576
3577 if (RT_UNLIKELY(pPktManip->Hdr.idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM)))
3578 {
3579 KDPACKETMANIPULATEHDR RespHdr;
3580 RT_ZERO(RespHdr);
3581
3582 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR;
3583 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3584 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3585 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Test this path. */
3586 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3587 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3588 }
3589 else
3590 {
3591 pThis->Dbgc.idCpu = pPktManip->Hdr.idCpu;
3592 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3593 }
3594
3595 return rc;
3596}
3597
3598
3599/**
3600 * Processes a manipulate packet.
3601 *
3602 * @returns VBox status code.
3603 * @param pThis The KD context.
3604 */
3605static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
3606{
3607 int rc = VINF_SUCCESS;
3608 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
3609
3610 switch (pPktManip->Hdr.idReq)
3611 {
3612 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
3613 {
3614 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
3615 break;
3616 }
3617 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
3618 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
3619 {
3620 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
3621 break;
3622 }
3623 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
3624 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
3625 {
3626 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
3627 break;
3628 }
3629 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
3630 {
3631 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
3632 break;
3633 }
3634 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
3635 {
3636 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
3637 break;
3638 }
3639 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
3640 {
3641 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
3642 break;
3643 }
3644 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
3645 {
3646 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
3647 break;
3648 }
3649 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
3650 {
3651 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
3652 break;
3653 }
3654 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
3655 {
3656 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
3657 break;
3658 }
3659 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
3660 {
3661 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
3662 break;
3663 }
3664 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
3665 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
3666 break;
3667 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
3668 {
3669 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
3670 break;
3671 }
3672 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
3673 {
3674 rc = dbgcKdCtxPktManipulate64QueryMemory(pThis, pPktManip);
3675 break;
3676 }
3677 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
3678 {
3679 rc = dbgcKdCtxPktManipulate64SearchMemory(pThis, pPktManip);
3680 break;
3681 }
3682 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK:
3683 {
3684 rc = dbgcKdCtxPktManipulate64CauseBugCheck(pThis, pPktManip);
3685 break;
3686 }
3687 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR:
3688 {
3689 rc = dbgcKdCtxPktManipulate64SwitchProcessor(pThis, pPktManip);
3690 break;
3691 }
3692 case KD_PACKET_MANIPULATE_REQ_REBOOT:
3693 {
3694 rc = VMR3Reset(pThis->Dbgc.pUVM); /* Doesn't expect an answer here. */
3695 if ( RT_SUCCESS(rc)
3696 && DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3697 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3698 break;
3699 }
3700 default:
3701 KDPACKETMANIPULATEHDR RespHdr;
3702 RT_ZERO(RespHdr);
3703
3704 RespHdr.idReq = pPktManip->Hdr.idReq;
3705 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3706 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3707 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
3708 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3709 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3710 break;
3711 }
3712
3713 return rc;
3714}
3715
3716
3717/**
3718 * Tries to detect the guest OS running in the VM looking specifically for the Windows NT kind.
3719 *
3720 * @param pThis The KD context.
3721 */
3722static void dbgcKdCtxDetectGstOs(PKDCTX pThis)
3723{
3724 pThis->pIfWinNt = NULL;
3725
3726 /* Try detecting a Windows NT guest. */
3727 char szName[64];
3728 int rc = DBGFR3OSDetect(pThis->Dbgc.pUVM, szName, sizeof(szName));
3729 if (RT_SUCCESS(rc))
3730 {
3731 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pThis->Dbgc.pUVM, DBGFOSINTERFACE_WINNT);
3732 if (pThis->pIfWinNt)
3733 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3734 else
3735 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3736 }
3737 else
3738 {
3739 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3740 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3741 }
3742
3743 if (pThis->pIfWinNt)
3744 {
3745 rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
3746 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
3747 NULL /*puBuildNumber*/, &pThis->f32Bit);
3748 AssertRC(rc);
3749 }
3750 else
3751 {
3752 /*
3753 * Try to detect bitness based on the current CPU mode which might fool us (32bit process running
3754 * inside of 64bit host).
3755 */
3756 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
3757 if (enmMode == CPUMMODE_PROTECTED)
3758 pThis->f32Bit = true;
3759 else if (enmMode == CPUMMODE_LONG)
3760 pThis->f32Bit = false;
3761 else
3762 LogRel(("DBGC/Kd: Heh, trying to debug real mode code with WinDbg are we? Good luck with that...\n"));
3763 }
3764}
3765
3766
3767/**
3768 * Processes a fully received packet.
3769 *
3770 * @returns VBox status code.
3771 * @param pThis The KD context.
3772 */
3773static int dbgcKdCtxPktProcess(PKDCTX pThis)
3774{
3775 int rc = VINF_SUCCESS;
3776
3777 pThis->fBreakinRecv = false;
3778
3779 /* Verify checksum. */
3780 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
3781 {
3782 /** @todo Check packet id. */
3783 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
3784 {
3785 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3786 rc = dbgcKdCtxPktSendAck(pThis);
3787 }
3788 if (RT_SUCCESS(rc))
3789 {
3790#ifdef LOG_ENABLED
3791 RTSGSEG Seg;
3792 Seg.pvSeg = &pThis->abBody[0];
3793 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
3794 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
3795#endif
3796
3797 switch (pThis->PktHdr.Fields.u16SubType)
3798 {
3799 case KD_PACKET_HDR_SUB_TYPE_RESET:
3800 {
3801 dbgcKdCtxDetectGstOs(pThis);
3802
3803 pThis->idPktNext = 0;
3804 rc = dbgcKdCtxPktSendReset(pThis);
3805 if (RT_SUCCESS(rc))
3806 {
3807 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3808 if (rc == VWRN_DBGF_ALREADY_HALTED)
3809 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3810 }
3811 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
3812 break;
3813 }
3814 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
3815 {
3816 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3817 rc = dbgcKdCtxPktManipulate64Process(pThis);
3818 break;
3819 }
3820 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
3821 case KD_PACKET_HDR_SUB_TYPE_RESEND:
3822 {
3823 /* Don't do anything. */
3824 rc = VINF_SUCCESS;
3825 break;
3826 }
3827 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO:
3828 {
3829 if (pThis->fInVBoxDbg)
3830 {
3831 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3832 /* Get the string and execute it. */
3833 PCKDPACKETDEBUGIO pPktDbgIo = (PCKDPACKETDEBUGIO)&pThis->abBody[0];
3834 if ( pPktDbgIo->u32Type == KD_PACKET_DEBUG_IO_GET_STRING
3835 && pPktDbgIo->u.Prompt.cbReturn <= sizeof(pThis->abBody) - sizeof(*pPktDbgIo) - 1)
3836 {
3837 if (pPktDbgIo->u.Prompt.cbReturn)
3838 {
3839 /* Terminate return value. */
3840 pThis->abBody[sizeof(*pPktDbgIo) + pPktDbgIo->u.Prompt.cbReturn] = '\0';
3841
3842 const char *pszCmd = (const char *)&pThis->abBody[sizeof(*pPktDbgIo)];
3843 /* Filter out 'exit' which is handled here directly and exits the debug loop. */
3844 if (!strcmp(pszCmd, "exit"))
3845 pThis->fInVBoxDbg = false;
3846 else
3847 {
3848 rc = pThis->Dbgc.CmdHlp.pfnExec(&pThis->Dbgc.CmdHlp, pszCmd);
3849 if (RT_SUCCESS(rc))
3850 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3851 512 /*cbResponseMax*/);
3852 else
3853 LogRel(("DBGC/Kd: Executing command \"%s\" failed with rc=%Rrc\n", pszCmd, rc));
3854 }
3855 }
3856 else
3857 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3858 512 /*cbResponseMax*/);
3859 }
3860 else
3861 LogRel(("DBGC/Kd: Received invalid DEBUG_IO packet from remote end, ignoring\n"));
3862 }
3863 else
3864 LogRel(("DBGC/Kd: Received out of band DEBUG_IO packet from remote end, ignoring\n"));
3865 break;
3866 }
3867 default:
3868 rc = VERR_NOT_IMPLEMENTED;
3869 }
3870 }
3871 }
3872 else
3873 {
3874 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3875 rc = dbgcKdCtxPktSendResend(pThis);
3876 }
3877
3878 if (pThis->fBreakinRecv)
3879 {
3880 pThis->fBreakinRecv = false;
3881 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3882 if (rc == VWRN_DBGF_ALREADY_HALTED)
3883 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3884 }
3885
3886 /* Next packet. */
3887 dbgcKdCtxPktRecvReset(pThis);
3888 return rc;
3889}
3890
3891
3892/**
3893 * Processes the received data based on the current state.
3894 *
3895 * @returns VBox status code.
3896 * @param pThis The KD context.
3897 */
3898static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
3899{
3900 int rc = VINF_SUCCESS;
3901
3902 switch (pThis->enmState)
3903 {
3904 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
3905 {
3906 /* Does it look like a valid packet start?. */
3907 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
3908 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
3909 {
3910 pThis->pbRecv = &pThis->PktHdr.ab[1];
3911 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3912 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
3913 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
3914 }
3915 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3916 {
3917 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3918 if (rc == VWRN_DBGF_ALREADY_HALTED)
3919 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3920 dbgcKdCtxPktRecvReset(pThis);
3921 }
3922 else
3923 dbgcKdCtxPktRecvReset(pThis); /* Reset and continue. */
3924 break;
3925 }
3926 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
3927 {
3928 /*
3929 * If the first and second byte differ there might be a single breakin
3930 * packet byte received and this is actually the start of a new packet.
3931 */
3932 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
3933 {
3934 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3935 {
3936 /* Halt the VM and rearrange the packet receiving state machine. */
3937 LogFlow(("DbgKd: Halting VM!\n"));
3938
3939 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3940 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
3941 pThis->pbRecv = &pThis->PktHdr.ab[1];
3942 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3943 }
3944 else
3945 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
3946 }
3947 else
3948 {
3949 /* Normal packet receive continues with the rest of the header. */
3950 pThis->pbRecv = &pThis->PktHdr.ab[2];
3951 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
3952 pThis->enmState = KDRECVSTATE_PACKET_HDR;
3953 }
3954 break;
3955 }
3956 case KDRECVSTATE_PACKET_HDR:
3957 {
3958 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
3959 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
3960 {
3961 /* Start receiving the body. */
3962 if (pThis->PktHdr.Fields.cbBody)
3963 {
3964 pThis->pbRecv = &pThis->abBody[0];
3965 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
3966 pThis->enmState = KDRECVSTATE_PACKET_BODY;
3967 }
3968 else /* No body means no trailer byte it looks like. */
3969 rc = dbgcKdCtxPktProcess(pThis);
3970 }
3971 else
3972 rc = VERR_NET_PROTOCOL_ERROR;
3973 break;
3974 }
3975 case KDRECVSTATE_PACKET_BODY:
3976 {
3977 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
3978 pThis->bTrailer = 0;
3979 pThis->pbRecv = &pThis->bTrailer;
3980 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
3981 break;
3982 }
3983 case KDRECVSTATE_PACKET_TRAILER:
3984 {
3985 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
3986 rc = dbgcKdCtxPktProcess(pThis);
3987 else
3988 rc = VERR_NET_PROTOCOL_ERROR;
3989 break;
3990 }
3991 default:
3992 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
3993 }
3994
3995 return rc;
3996}
3997
3998
3999/**
4000 * Receive data and processes complete packets.
4001 *
4002 * @returns Status code.
4003 * @param pThis The KD context.
4004 */
4005static int dbgcKdCtxRecv(PKDCTX pThis)
4006{
4007 int rc = VINF_SUCCESS;
4008
4009 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
4010
4011 if (pThis->cbRecvLeft)
4012 {
4013 size_t cbRead = 0;
4014 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
4015 if (RT_SUCCESS(rc))
4016 {
4017 pThis->tsRecvLast = RTTimeMilliTS();
4018 pThis->cbRecvLeft -= cbRead;
4019 pThis->pbRecv += cbRead;
4020 if (!pThis->cbRecvLeft)
4021 rc = dbgcKdCtxRecvDataProcess(pThis);
4022 }
4023 }
4024
4025 LogFlowFunc(("returns rc=%Rrc\n", rc));
4026 return rc;
4027}
4028
4029
4030/**
4031 * Processes debugger events.
4032 *
4033 * @returns VBox status code.
4034 * @param pThis The KD context data.
4035 * @param pEvent Pointer to event data.
4036 */
4037static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
4038{
4039 /*
4040 * Process the event.
4041 */
4042 PDBGC pDbgc = &pThis->Dbgc;
4043 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
4044 pThis->Dbgc.iArg = 0;
4045 int rc = VINF_SUCCESS;
4046 VMCPUID idCpuOld = pDbgc->idCpu;
4047 pDbgc->idCpu = pEvent->idCpu;
4048 switch (pEvent->enmType)
4049 {
4050 /*
4051 * The first part is events we have initiated with commands.
4052 */
4053 case DBGFEVENT_HALT_DONE:
4054 {
4055 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
4056 break;
4057 }
4058
4059 /*
4060 * The second part is events which can occur at any time.
4061 */
4062 case DBGFEVENT_FATAL_ERROR:
4063 {
4064 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
4065 dbgcGetEventCtx(pEvent->enmCtx));
4066 if (RT_SUCCESS(rc))
4067 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4068 break;
4069 }
4070
4071 case DBGFEVENT_BREAKPOINT:
4072 case DBGFEVENT_BREAKPOINT_IO:
4073 case DBGFEVENT_BREAKPOINT_MMIO:
4074 case DBGFEVENT_BREAKPOINT_HYPER:
4075 {
4076 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.hBp);
4077 switch (rc)
4078 {
4079 case VERR_DBGC_BP_NOT_FOUND:
4080 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
4081 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
4082 break;
4083
4084 case VINF_DBGC_BP_NO_COMMAND:
4085 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
4086 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
4087 break;
4088
4089 case VINF_BUFFER_OVERFLOW:
4090 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
4091 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
4092 break;
4093
4094 default:
4095 break;
4096 }
4097 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL))
4098 {
4099 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4100
4101 /* Set the resume flag to ignore the breakpoint when resuming execution. */
4102 if ( RT_SUCCESS(rc)
4103 && pEvent->enmType == DBGFEVENT_BREAKPOINT)
4104 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
4105 }
4106
4107 /* Figure out the breakpoint and set the triggered flag for emulation of DR6. */
4108 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
4109 {
4110 if (pThis->aHwBp[i].hDbgfBp == pEvent->u.Bp.hBp)
4111 {
4112 pThis->aHwBp[i].fTriggered = true;
4113 break;
4114 }
4115 }
4116
4117 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
4118 break;
4119 }
4120
4121 case DBGFEVENT_STEPPED:
4122 case DBGFEVENT_STEPPED_HYPER:
4123 {
4124 pThis->fSingleStepped = true; /* For emulation of DR6. */
4125 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
4126 break;
4127 }
4128
4129 case DBGFEVENT_ASSERTION_HYPER:
4130 {
4131 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4132 "\ndbgf event: Hypervisor Assertion! (%s)\n"
4133 "%s"
4134 "%s"
4135 "\n",
4136 dbgcGetEventCtx(pEvent->enmCtx),
4137 pEvent->u.Assert.pszMsg1,
4138 pEvent->u.Assert.pszMsg2);
4139 if (RT_SUCCESS(rc))
4140 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4141 break;
4142 }
4143
4144 case DBGFEVENT_DEV_STOP:
4145 {
4146 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4147 "\n"
4148 "dbgf event: DBGFSTOP (%s)\n"
4149 "File: %s\n"
4150 "Line: %d\n"
4151 "Function: %s\n",
4152 dbgcGetEventCtx(pEvent->enmCtx),
4153 pEvent->u.Src.pszFile,
4154 pEvent->u.Src.uLine,
4155 pEvent->u.Src.pszFunction);
4156 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
4157 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4158 "Message: %s\n",
4159 pEvent->u.Src.pszMessage);
4160 if (RT_SUCCESS(rc))
4161 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4162 break;
4163 }
4164
4165
4166 case DBGFEVENT_INVALID_COMMAND:
4167 {
4168 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
4169 break;
4170 }
4171
4172 case DBGFEVENT_POWERING_OFF:
4173 {
4174 pThis->Dbgc.fReady = false;
4175 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, false);
4176 rc = VERR_GENERAL_FAILURE;
4177 break;
4178 }
4179
4180 default:
4181 {
4182 /*
4183 * Probably a generic event. Look it up to find its name.
4184 */
4185 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
4186 if (pEvtDesc)
4187 {
4188 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
4189 {
4190 Assert(pEvtDesc->pszDesc);
4191 Assert(pEvent->u.Generic.cArgs == 1);
4192 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
4193 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
4194 }
4195 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
4196 {
4197 Assert(pEvent->u.Generic.cArgs >= 5);
4198 char szDetails[512];
4199 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
4200 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
4201 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
4202 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
4203 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
4204 szDetails);
4205 }
4206 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
4207 || pEvent->u.Generic.cArgs > 1
4208 || ( pEvent->u.Generic.cArgs == 1
4209 && pEvent->u.Generic.auArgs[0] != 0))
4210 {
4211 if (pEvtDesc->pszDesc)
4212 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
4213 pEvtDesc->pszName, pEvtDesc->pszDesc);
4214 else
4215 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
4216 if (pEvent->u.Generic.cArgs <= 1)
4217 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
4218 else
4219 {
4220 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
4221 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
4222 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
4223 }
4224 }
4225 else
4226 {
4227 if (pEvtDesc->pszDesc)
4228 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
4229 pEvtDesc->pszName, pEvtDesc->pszDesc);
4230 else
4231 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
4232 }
4233 }
4234 else
4235 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
4236 break;
4237 }
4238 }
4239
4240 pDbgc->idCpu = idCpuOld;
4241 return rc;
4242}
4243
4244
4245/**
4246 * Handle a receive timeout.
4247 *
4248 * @returns VBox status code.
4249 * @param pThis Pointer to the KD context.
4250 */
4251static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
4252{
4253 int rc = VINF_SUCCESS;
4254
4255 LogFlowFunc(("pThis=%p\n", pThis));
4256
4257 /*
4258 * If a single breakin packet byte was received but the header is otherwise incomplete
4259 * the VM is halted and a state change will be sent in the event processing loop.
4260 */
4261 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
4262 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
4263 {
4264 LogFlow(("DbgKd: Halting VM!\n"));
4265 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
4266 }
4267 else /* Send a reset packet */ /** @todo Figure out the semantics in this case exactly. */
4268 rc = dbgcKdCtxPktSendReset(pThis);
4269
4270 dbgcKdCtxPktRecvReset(pThis);
4271
4272 LogFlowFunc(("rc=%Rrc\n", rc));
4273 return rc;
4274}
4275
4276
4277/**
4278 * @copydoc DBGC::pfnOutput
4279 */
4280static DECLCALLBACK(int) dbgcKdOutput(void *pvUser, const char *pachChars, size_t cbChars)
4281{
4282 PKDCTX pThis = (PKDCTX)pvUser;
4283
4284 return dbgcKdCtxDebugIoStrSend(pThis, pThis->Dbgc.idCpu, pachChars, cbChars);
4285}
4286
4287
4288/**
4289 * Run the debugger console.
4290 *
4291 * @returns VBox status code.
4292 * @param pThis Pointer to the KD context.
4293 */
4294static int dbgcKdRun(PKDCTX pThis)
4295{
4296 /*
4297 * We're ready for commands now.
4298 */
4299 pThis->Dbgc.fReady = true;
4300 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, true);
4301
4302 /*
4303 * Main Debugger Loop.
4304 *
4305 * This loop will either block on waiting for input or on waiting on
4306 * debug events. If we're forwarding the log we cannot wait for long
4307 * before we must flush the log.
4308 */
4309 int rc;
4310 for (;;)
4311 {
4312 rc = VERR_SEM_OUT_OF_TURN;
4313 if (pThis->Dbgc.pUVM)
4314 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
4315
4316 if (RT_SUCCESS(rc))
4317 {
4318 /*
4319 * Wait for a debug event.
4320 */
4321 DBGFEVENT Evt;
4322 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
4323 if (RT_SUCCESS(rc))
4324 {
4325 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
4326 if (RT_FAILURE(rc))
4327 break;
4328 }
4329 else if (rc != VERR_TIMEOUT)
4330 break;
4331
4332 /*
4333 * Check for input.
4334 */
4335 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 0))
4336 {
4337 rc = dbgcKdCtxRecv(pThis);
4338 if (RT_FAILURE(rc))
4339 break;
4340 }
4341 }
4342 else if (rc == VERR_SEM_OUT_OF_TURN)
4343 {
4344 /*
4345 * Wait for input.
4346 */
4347 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 1000))
4348 rc = dbgcKdCtxRecv(pThis);
4349 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
4350 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
4351 rc = dbgcKdCtxRecvTimeout(pThis);
4352
4353 if (RT_FAILURE(rc))
4354 break;
4355 }
4356 else
4357 break;
4358 }
4359
4360 return rc;
4361}
4362
4363
4364/**
4365 * Creates a KD context instance with the given backend.
4366 *
4367 * @returns VBox status code.
4368 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
4369 * @param pIo Pointer to the I/O callback table.
4370 * @param fFlags Flags controlling the behavior.
4371 */
4372static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PCDBGCIO pIo, unsigned fFlags)
4373{
4374 /*
4375 * Validate input.
4376 */
4377 AssertPtrReturn(pIo, VERR_INVALID_POINTER);
4378 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
4379
4380 /*
4381 * Allocate and initialize.
4382 */
4383 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
4384 if (!pThis)
4385 return VERR_NO_MEMORY;
4386
4387 dbgcInitCmdHlp(&pThis->Dbgc);
4388 /*
4389 * This is compied from the native debug console (will be used for monitor commands)
4390 * in DBGCConsole.cpp. Try to keep both functions in sync.
4391 */
4392 pThis->Dbgc.pIo = pIo;
4393 pThis->Dbgc.pfnOutput = dbgcKdOutput;
4394 pThis->Dbgc.pvOutputUser = pThis;
4395 pThis->Dbgc.pVM = NULL;
4396 pThis->Dbgc.pUVM = NULL;
4397 pThis->Dbgc.idCpu = 0;
4398 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
4399 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
4400 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
4401 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
4402 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
4403 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
4404 //pThis->Dbgc.fLog = false;
4405 pThis->Dbgc.fRegTerse = true;
4406 pThis->Dbgc.fStepTraceRegs = true;
4407 //pThis->Dbgc.cPagingHierarchyDumps = 0;
4408 //pThis->Dbgc.DisasmPos = {0};
4409 //pThis->Dbgc.SourcePos = {0};
4410 //pThis->Dbgc.DumpPos = {0};
4411 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
4412 //pThis->Dbgc.cbDumpElement = 0;
4413 //pThis->Dbgc.cVars = 0;
4414 //pThis->Dbgc.paVars = NULL;
4415 //pThis->Dbgc.pPlugInHead = NULL;
4416 //pThis->Dbgc.pFirstBp = NULL;
4417 //pThis->Dbgc.abSearch = {0};
4418 //pThis->Dbgc.cbSearch = 0;
4419 pThis->Dbgc.cbSearchUnit = 1;
4420 pThis->Dbgc.cMaxSearchHits = 1;
4421 //pThis->Dbgc.SearchAddr = {0};
4422 //pThis->Dbgc.cbSearchRange = 0;
4423
4424 //pThis->Dbgc.uInputZero = 0;
4425 //pThis->Dbgc.iRead = 0;
4426 //pThis->Dbgc.iWrite = 0;
4427 //pThis->Dbgc.cInputLines = 0;
4428 //pThis->Dbgc.fInputOverflow = false;
4429 pThis->Dbgc.fReady = true;
4430 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
4431 //pThis->Dbgc.iArg = 0;
4432 //pThis->Dbgc.rcOutput = 0;
4433 //pThis->Dbgc.rcCmd = 0;
4434
4435 //pThis->Dbgc.pszHistoryFile = NULL;
4436 //pThis->Dbgc.pszGlobalInitScript = NULL;
4437 //pThis->Dbgc.pszLocalInitScript = NULL;
4438
4439 dbgcEvalInit();
4440
4441 pThis->fBreakinRecv = false;
4442 pThis->fInVBoxDbg = false;
4443 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
4444 pThis->pIfWinNt = NULL;
4445 pThis->f32Bit = false;
4446 dbgcKdCtxPktRecvReset(pThis);
4447
4448 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
4449 {
4450 PKDCTXHWBP pBp = &pThis->aHwBp[i];
4451 pBp->hDbgfBp = NIL_DBGFBP;
4452 }
4453
4454 dbgcKdCtxHwBpReset(pThis);
4455
4456 *ppKdCtx = pThis;
4457 return VINF_SUCCESS;
4458}
4459
4460
4461/**
4462 * Destroys the given KD context.
4463 *
4464 * @param pThis The KD context to destroy.
4465 */
4466static void dbgcKdCtxDestroy(PKDCTX pThis)
4467{
4468 AssertPtr(pThis);
4469
4470 pThis->pIfWinNt = NULL;
4471
4472 /* Detach from the VM. */
4473 if (pThis->Dbgc.pUVM)
4474 DBGFR3Detach(pThis->Dbgc.pUVM);
4475
4476 /* Free config strings. */
4477 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
4478 pThis->Dbgc.pszGlobalInitScript = NULL;
4479 RTStrFree(pThis->Dbgc.pszLocalInitScript);
4480 pThis->Dbgc.pszLocalInitScript = NULL;
4481 RTStrFree(pThis->Dbgc.pszHistoryFile);
4482 pThis->Dbgc.pszHistoryFile = NULL;
4483
4484 /* Finally, free the instance memory. */
4485 RTMemFree(pThis);
4486}
4487
4488
4489DECL_HIDDEN_CALLBACK(int) dbgcKdStubRunloop(PUVM pUVM, PCDBGCIO pIo, unsigned fFlags)
4490{
4491 /*
4492 * Validate input.
4493 */
4494 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
4495 PVM pVM = NULL;
4496 if (pUVM)
4497 {
4498 pVM = VMR3GetVM(pUVM);
4499 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
4500 }
4501
4502 /*
4503 * Allocate and initialize instance data
4504 */
4505 PKDCTX pThis;
4506 int rc = dbgcKdCtxCreate(&pThis, pIo, fFlags);
4507 if (RT_FAILURE(rc))
4508 return rc;
4509 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
4510 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
4511
4512 /*
4513 * Attach to the specified VM.
4514 */
4515 if (RT_SUCCESS(rc) && pUVM)
4516 {
4517 rc = DBGFR3Attach(pUVM);
4518 if (RT_SUCCESS(rc))
4519 {
4520 pThis->Dbgc.pVM = pVM;
4521 pThis->Dbgc.pUVM = pUVM;
4522 pThis->Dbgc.idCpu = 0;
4523 }
4524 else
4525 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
4526 }
4527
4528 /*
4529 * Load plugins.
4530 */
4531 if (RT_SUCCESS(rc))
4532 {
4533 if (pVM)
4534 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
4535 dbgcEventInit(&pThis->Dbgc);
4536
4537 /*
4538 * Run the debugger main loop.
4539 */
4540 rc = dbgcKdRun(pThis);
4541 dbgcEventTerm(&pThis->Dbgc);
4542 }
4543
4544 /*
4545 * Cleanup console debugger session.
4546 */
4547 dbgcKdCtxDestroy(pThis);
4548 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
4549}
Note: See TracBrowser for help on using the repository browser.

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