VirtualBox

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

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

VMM/DBGF,Debugger: Removed the !defined(VBOX_WITH_LOTS_OF_DBGF_BPS) code. bugref:9837

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