VirtualBox

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

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

Debugger/DBGCRemoteKd: Stub the query memory attributes request (need a new DBGF Api for the real implementation) [typo]

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