VirtualBox

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

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

Debugger/DBGCRemoteKd: Implement support for the DEBUG_IO packets to send strings to the remotes console

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 133.4 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 86180 2020-09-20 09:33:40Z 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 * Manipulate request packet header (Same for 32bit and 64bit).
916 */
917typedef struct KDPACKETMANIPULATEHDR
918{
919 /** The request to execute. */
920 uint32_t idReq;
921 /** The processor level to execute the request on. */
922 uint16_t u16CpuLvl;
923 /** The processor ID to execute the request on. */
924 uint16_t idCpu;
925 /** Return status code. */
926 uint32_t u32NtStatus;
927 /** Alignment. */
928 uint32_t u32Alignment;
929} KDPACKETMANIPULATEHDR;
930AssertCompileSize(KDPACKETMANIPULATEHDR, 3 * 4 + 2 * 2);
931/** Pointer to a manipulate request packet header. */
932typedef KDPACKETMANIPULATEHDR *PKDPACKETMANIPULATEHDR;
933/** Pointer to a const manipulate request packet header. */
934typedef const KDPACKETMANIPULATEHDR *PCPKDPACKETMANIPULATEHDR;
935
936
937/**
938 * 64bit manipulate state request packet.
939 */
940typedef struct KDPACKETMANIPULATE64
941{
942 /** Header. */
943 KDPACKETMANIPULATEHDR Hdr;
944 /** Request payloads. */
945 union
946 {
947 /** Get Version. */
948 KDPACKETMANIPULATE_GETVERSION64 GetVersion;
949 /** Read/Write memory. */
950 KDPACKETMANIPULATE_XFERMEM64 XferMem;
951 /** Continue. */
952 KDPACKETMANIPULATE_CONTINUE Continue;
953 /** Continue2. */
954 KDPACKETMANIPULATE_CONTINUE2 Continue2;
955 /** Set context. */
956 KDPACKETMANIPULATE_SETCONTEXT SetContext;
957 /** Read/Write control space. */
958 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace;
959 /** Restore breakpoint. */
960 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt;
961 /** Write breakpoint. */
962 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt;
963 /** Context extended. */
964 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
965 } u;
966} KDPACKETMANIPULATE64;
967AssertCompileSize(KDPACKETMANIPULATE64, 16 + 40);
968/** Pointer to a 64bit manipulate state request packet. */
969typedef KDPACKETMANIPULATE64 *PKDPACKETMANIPULATE64;
970/** Pointer to a const 64bit manipulate state request packet. */
971typedef const KDPACKETMANIPULATE64 *PCKDPACKETMANIPULATE64;
972
973/** @name Manipulate requests.
974 * @{ */
975/** Minimum available request. */
976#define KD_PACKET_MANIPULATE_REQ_MIN UINT32_C(0x00003130)
977/** Read virtual memory request. */
978#define KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM KD_PACKET_MANIPULATE_REQ_MIN
979/** Write virtual memory request. */
980#define KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM UINT32_C(0x00003131)
981/** Get context request. */
982#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT UINT32_C(0x00003132)
983/** Set context request. */
984#define KD_PACKET_MANIPULATE_REQ_SET_CONTEXT UINT32_C(0x00003133)
985/** Write breakpoint request. */
986#define KD_PACKET_MANIPULATE_REQ_WRITE_BKPT UINT32_C(0x00003134)
987/** Restore breakpoint request. */
988#define KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT UINT32_C(0x00003135)
989/** Continue request. */
990#define KD_PACKET_MANIPULATE_REQ_CONTINUE UINT32_C(0x00003136)
991/** Read control space request. */
992#define KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE UINT32_C(0x00003137)
993/** Write control space request. */
994#define KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE UINT32_C(0x00003138)
995/** Read I/O space request. */
996#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE UINT32_C(0x00003139)
997/** Write I/O space request. */
998#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE UINT32_C(0x0000313a)
999/** Reboot request. */
1000#define KD_PACKET_MANIPULATE_REQ_REBOOT UINT32_C(0x0000313b)
1001/** continue 2nd version request. */
1002#define KD_PACKET_MANIPULATE_REQ_CONTINUE2 UINT32_C(0x0000313c)
1003/** Read physical memory request. */
1004#define KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM UINT32_C(0x0000313d)
1005/** Write physical memory request. */
1006#define KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM UINT32_C(0x0000313e)
1007/** Query special calls request. */
1008#define KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS UINT32_C(0x0000313f)
1009/** Set special calls request. */
1010#define KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS UINT32_C(0x00003140)
1011/** Clear special calls request. */
1012#define KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS UINT32_C(0x00003141)
1013/** Set internal breakpoint request. */
1014#define KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT UINT32_C(0x00003142)
1015/** Get internal breakpoint request. */
1016#define KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT UINT32_C(0x00003143)
1017/** Read I/O space extended request. */
1018#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX UINT32_C(0x00003144)
1019/** Write I/O space extended request. */
1020#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX UINT32_C(0x00003145)
1021/** Get version request. */
1022#define KD_PACKET_MANIPULATE_REQ_GET_VERSION UINT32_C(0x00003146)
1023/** @todo */
1024/** Clear all internal breakpoints request. */
1025#define KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT UINT32_C(0x0000315a)
1026/** @todo */
1027/** Get context extended request. */
1028#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX UINT32_C(0x0000315f)
1029/** @todo */
1030/** Maximum available request (exclusive). */
1031#define KD_PACKET_MANIPULATE_REQ_MAX UINT32_C(0x00003161)
1032/** @} */
1033
1034/**
1035 * KD stub receive state.
1036 */
1037typedef enum KDRECVSTATE
1038{
1039 /** Invalid state. */
1040 KDRECVSTATE_INVALID = 0,
1041 /** Receiving the first byte of the packet header. */
1042 KDRECVSTATE_PACKET_HDR_FIRST_BYTE,
1043 /** Receiving the second byte of the packet header. */
1044 KDRECVSTATE_PACKET_HDR_SECOND_BYTE,
1045 /** Receiving the header. */
1046 KDRECVSTATE_PACKET_HDR,
1047 /** Receiving the packet body. */
1048 KDRECVSTATE_PACKET_BODY,
1049 /** Receiving the trailing byte. */
1050 KDRECVSTATE_PACKET_TRAILER,
1051 /** Blow up the enum to 32bits for easier alignment of members in structs. */
1052 KDRECVSTATE_32BIT_HACK = 0x7fffffff
1053} KDRECVSTATE;
1054
1055
1056/**
1057 * KD context data.
1058 */
1059typedef struct KDCTX
1060{
1061 /** Internal debugger console data. */
1062 DBGC Dbgc;
1063 /** Number of bytes received left for the current state. */
1064 size_t cbRecvLeft;
1065 /** Pointer where to write the next received data. */
1066 uint8_t *pbRecv;
1067 /** The current state when receiving a new packet. */
1068 KDRECVSTATE enmState;
1069 /** The timeout waiting for new data. */
1070 RTMSINTERVAL msRecvTimeout;
1071 /** Timestamp when we last received data from the remote end. */
1072 uint64_t tsRecvLast;
1073 /** Packet header being received. */
1074 union
1075 {
1076 KDPACKETHDR Fields;
1077 uint8_t ab[16];
1078 } PktHdr;
1079 /** The next packet ID to send. */
1080 uint32_t idPktNext;
1081 /** Offset into the body receive buffer. */
1082 size_t offBodyRecv;
1083 /** Body data. */
1084 uint8_t abBody[_4K];
1085 /** The trailer byte storage. */
1086 uint8_t bTrailer;
1087 /** Flag whether a breakin packet was received since the last time it was reset. */
1088 bool fBreakinRecv;
1089
1090 /** Pointer to the OS digger WinNt interface if a matching guest was detected. */
1091 PDBGFOSIWINNT pIfWinNt;
1092 /** Flag whether the detected guest is 32bit (false if 64bit). */
1093 bool f32Bit;
1094} KDCTX;
1095/** Pointer to the KD context data. */
1096typedef KDCTX *PKDCTX;
1097/** Pointer to const KD context data. */
1098typedef const KDCTX *PCKDCTX;
1099/** Pointer to a KD context data pointer. */
1100typedef PKDCTX *PPKDCTX;
1101
1102
1103/** Creates a possibly sign extended guest context pointer which is required for 32bit targets. */
1104#define KD_PTR_CREATE(a_pThis, a_GCPtr) ((a_pThis)->f32Bit && ((a_GCPtr) & RT_BIT_32(31)) ? (a_GCPtr) | UINT64_C(0xffffffff00000000) : (a_GCPtr))
1105/** Returns the value of a possibly sign extended guest context pointer received for 32bit targets. */
1106#define KD_PTR_GET(a_pThis, a_GCPtr) ((a_pThis)->f32Bit ? (a_GCPtr) & ~UINT64_C(0xffffffff00000000) : (a_GCPtr))
1107
1108
1109/*********************************************************************************************************************************
1110* Internal Functions *
1111*********************************************************************************************************************************/
1112
1113
1114#ifdef LOG_ENABLED
1115/**
1116 * Returns a human readable string of the given packet sub type.
1117 *
1118 * @returns Pointer to sub type string.
1119 * @param u16SubType The sub type to convert to a string.
1120 */
1121static const char *dbgcKdPktDumpSubTypeToStr(uint16_t u16SubType)
1122{
1123 switch (u16SubType)
1124 {
1125 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32: return "StateChange32";
1126 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE: return "Manipulate";
1127 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO: return "DebugIo";
1128 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE: return "Ack";
1129 case KD_PACKET_HDR_SUB_TYPE_RESEND: return "Resend";
1130 case KD_PACKET_HDR_SUB_TYPE_RESET: return "Reset";
1131 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64: return "StateChange64";
1132 case KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN: return "PollBreakin";
1133 case KD_PACKET_HDR_SUB_TYPE_TRACE_IO: return "TraceIo";
1134 case KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST: return "ControlRequest";
1135 case KD_PACKET_HDR_SUB_TYPE_FILE_IO: return "FileIo";
1136 default: break;
1137 }
1138
1139 return "<UNKNOWN>";
1140}
1141
1142
1143/**
1144 * Returns a human readable string of the given manipulate request ID.
1145 *
1146 * @returns nothing.
1147 * @param idReq Request ID (API number in KD speak).
1148 */
1149static const char *dbgcKdPktDumpManipulateReqToStr(uint32_t idReq)
1150{
1151 switch (idReq)
1152 {
1153 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM: return "ReadVirtMem";
1154 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM: return "WriteVirtMem";
1155 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT: return "GetContext";
1156 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT: return "SetContext";
1157 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT: return "WriteBkpt";
1158 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT: return "RestoreBkpt";
1159 case KD_PACKET_MANIPULATE_REQ_CONTINUE: return "Continue";
1160 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE: return "ReadCtrlSpace";
1161 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE: return "WriteCtrlSpace";
1162 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE: return "ReadIoSpace";
1163 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE: return "WriteIoSpace";
1164 case KD_PACKET_MANIPULATE_REQ_REBOOT: return "Reboot";
1165 case KD_PACKET_MANIPULATE_REQ_CONTINUE2: return "Continue2";
1166 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM: return "ReadPhysMem";
1167 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM: return "WritePhysMem";
1168 case KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS: return "QuerySpecCalls";
1169 case KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS: return "SetSpecCalls";
1170 case KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS: return "ClrSpecCalls";
1171 case KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT: return "SetIntBkpt";
1172 case KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT: return "GetIntBkpt";
1173 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX: return "ReadIoSpaceEx";
1174 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX: return "WriteIoSpaceEx";
1175 case KD_PACKET_MANIPULATE_REQ_GET_VERSION: return "GetVersion";
1176 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT: return "ClrAllIntBkpt";
1177 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX: return "GetContextEx";
1178 default: break;
1179 }
1180
1181 return "<UNKNOWN>";
1182}
1183
1184
1185/**
1186 * Dumps the content of a manipulate packet.
1187 *
1188 * @returns nothing.
1189 * @param pSgBuf S/G buffer containing the manipulate packet payload.
1190 */
1191static void dbgcKdPktDumpManipulate(PRTSGBUF pSgBuf)
1192{
1193 KDPACKETMANIPULATEHDR Hdr;
1194 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, &Hdr, sizeof(Hdr));
1195
1196 if (cbCopied == sizeof(Hdr))
1197 {
1198 const char *pszReq = dbgcKdPktDumpManipulateReqToStr(Hdr.idReq);
1199
1200 Log3((" MANIPULATE(%#x (%s), %#x, %u, %#x)\n",
1201 Hdr.idReq, pszReq, Hdr.u16CpuLvl, Hdr.idCpu, Hdr.u32NtStatus));
1202
1203 switch (Hdr.idReq)
1204 {
1205 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
1206 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
1207 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
1208 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
1209 {
1210 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1211 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferMem64, sizeof(XferMem64));
1212 if (cbCopied == sizeof(XferMem64))
1213 {
1214 Log3((" u64PtrTarget: %RX64\n"
1215 " cbXferReq: %RX32\n"
1216 " cbXfered: %RX32\n",
1217 XferMem64.u64PtrTarget, XferMem64.cbXferReq, XferMem64.cbXfered));
1218 }
1219 else
1220 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferMem64), cbCopied));
1221 break;
1222 }
1223 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
1224 {
1225 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
1226 cbCopied = RTSgBufCopyToBuf(pSgBuf, &RestoreBkpt64, sizeof(RestoreBkpt64));
1227 if (cbCopied == sizeof(RestoreBkpt64))
1228 Log3((" u32HndBkpt: %RX32\n", RestoreBkpt64.u32HndBkpt));
1229 else
1230 Log3((" Payload to small, expected %u, got %zu\n", sizeof(RestoreBkpt64), cbCopied));
1231 break;
1232 }
1233 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
1234 {
1235 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
1236 cbCopied = RTSgBufCopyToBuf(pSgBuf, &WriteBkpt64, sizeof(WriteBkpt64));
1237 if (cbCopied == sizeof(WriteBkpt64))
1238 Log3((" u64PtrBkpt: %RX64\n"
1239 " u32HndBkpt: %RX32\n",
1240 WriteBkpt64.u64PtrBkpt, WriteBkpt64.u32HndBkpt));
1241 else
1242 Log3((" Payload to small, expected %u, got %zu\n", sizeof(WriteBkpt64), cbCopied));
1243 break;
1244 }
1245 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
1246 {
1247 KDPACKETMANIPULATE_CONTINUE Continue;
1248 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1249 if (cbCopied == sizeof(Continue))
1250 Log3((" u32NtContSts: %RX32\n", Continue.u32NtContSts));
1251 else
1252 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1253 break;
1254 }
1255 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
1256 {
1257 KDPACKETMANIPULATE_CONTINUE2 Continue;
1258 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1259 if (cbCopied == sizeof(Continue))
1260 Log3((" u32NtContSts: %RX32\n"
1261 " fTrace: %RX32\n",
1262 Continue.u32NtContSts, Continue.fTrace));
1263 else
1264 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1265 break;
1266 }
1267 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
1268 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
1269 {
1270 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
1271 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferCtrlSpace64, sizeof(XferCtrlSpace64));
1272 if (cbCopied == sizeof(XferCtrlSpace64))
1273 {
1274 Log3((" u64IdXfer: %RX64\n"
1275 " cbXferReq: %RX32\n"
1276 " cbXfered: %RX32\n",
1277 XferCtrlSpace64.u64IdXfer, XferCtrlSpace64.cbXferReq, XferCtrlSpace64.cbXfered));
1278 }
1279 else
1280 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferCtrlSpace64), cbCopied));
1281 break;
1282 }
1283 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
1284 {
1285 KDPACKETMANIPULATE_CONTEXTEX GetContextEx;
1286 cbCopied = RTSgBufCopyToBuf(pSgBuf, &GetContextEx, sizeof(GetContextEx));
1287 if (cbCopied == sizeof(GetContextEx))
1288 {
1289 Log3((" offStart: %RX32\n"
1290 " cbXferReq: %RX32\n"
1291 " cbXfered: %RX32\n",
1292 GetContextEx.offStart, GetContextEx.cbXfer, GetContextEx.cbXfered));
1293 }
1294 else
1295 Log3((" Payload to small, expected %u, got %zu\n", sizeof(GetContextEx), cbCopied));
1296 break;
1297 }
1298 default:
1299 break;
1300 }
1301 }
1302 else
1303 Log3((" MANIPULATE(Header too small, expected %u, got %zu)\n", sizeof(Hdr), cbCopied));
1304}
1305
1306
1307/**
1308 * Dumps the received packet to the debug log.
1309 *
1310 * @returns VBox status code.
1311 * @param pPktHdr The packet header to dump.
1312 * @param fRx Flag whether the packet was received (false indicates an outgoing packet).
1313 */
1314static void dbgcKdPktDump(PCKDPACKETHDR pPktHdr, PCRTSGSEG paSegs, uint32_t cSegs, bool fRx)
1315{
1316 RTSGBUF SgBuf;
1317
1318 RTSgBufInit(&SgBuf, paSegs, cSegs);
1319
1320 Log3(("%s KDPKTHDR(%#x, %#x (%s), %u, %#x, %#x)\n",
1321 fRx ? "=>" : "<=",
1322 pPktHdr->u32Signature, pPktHdr->u16SubType, dbgcKdPktDumpSubTypeToStr(pPktHdr->u16SubType),
1323 pPktHdr->cbBody, pPktHdr->idPacket, pPktHdr->u32ChkSum));
1324 switch (pPktHdr->u16SubType)
1325 {
1326 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
1327 dbgcKdPktDumpManipulate(&SgBuf);
1328 break;
1329 default:
1330 break;
1331 }
1332}
1333#endif
1334
1335
1336/**
1337 * Wrapper for the I/O interface write callback.
1338 *
1339 * @returns Status code.
1340 * @param pThis The KD context.
1341 * @param pvPkt The packet data to send.
1342 * @param cbPkt Size of the packet in bytes.
1343 */
1344DECLINLINE(int) dbgcKdCtxWrite(PKDCTX pThis, const void *pvPkt, size_t cbPkt)
1345{
1346 return pThis->Dbgc.pBack->pfnWrite(pThis->Dbgc.pBack, pvPkt, cbPkt, NULL /*pcbWritten*/);
1347}
1348
1349
1350/**
1351 * Fills in the given 64bit NT context structure with the requested values.
1352 *
1353 * @returns VBox status code.
1354 * @param pThis The KD context.
1355 * @param idCpu The CPU to query the context for.
1356 * @param pNtCtx The NT context structure to fill in.
1357 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1358 */
1359static int dbgcKdCtxQueryNtCtx64(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1360{
1361 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1362
1363 pNtCtx->fContext = NTCONTEXT_F_AMD64;
1364 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pNtCtx->u32RegMxCsr);
1365
1366 if ( RT_SUCCESS(rc)
1367 && fCtxFlags & NTCONTEXT_F_CONTROL)
1368 {
1369 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u16SegCs);
1370 if (RT_SUCCESS(rc))
1371 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u16SegSs);
1372 if (RT_SUCCESS(rc))
1373 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RIP, &pNtCtx->u64RegRip);
1374 if (RT_SUCCESS(rc))
1375 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSP, &pNtCtx->u64RegRsp);
1376 if (RT_SUCCESS(rc))
1377 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBP, &pNtCtx->u64RegRbp);
1378 if (RT_SUCCESS(rc))
1379 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1380 if (RT_SUCCESS(rc))
1381 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1382 }
1383
1384 if ( RT_SUCCESS(rc)
1385 && fCtxFlags & NTCONTEXT_F_INTEGER)
1386 {
1387 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RAX, &pNtCtx->u64RegRax);
1388 if (RT_SUCCESS(rc))
1389 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RCX, &pNtCtx->u64RegRcx);
1390 if (RT_SUCCESS(rc))
1391 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDX, &pNtCtx->u64RegRdx);
1392 if (RT_SUCCESS(rc))
1393 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBX, &pNtCtx->u64RegRbx);
1394 if (RT_SUCCESS(rc))
1395 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSI, &pNtCtx->u64RegRsi);
1396 if (RT_SUCCESS(rc))
1397 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDI, &pNtCtx->u64RegRdi);
1398 if (RT_SUCCESS(rc))
1399 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R8, &pNtCtx->u64RegR8);
1400 if (RT_SUCCESS(rc))
1401 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R9, &pNtCtx->u64RegR9);
1402 if (RT_SUCCESS(rc))
1403 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R10, &pNtCtx->u64RegR10);
1404 if (RT_SUCCESS(rc))
1405 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R11, &pNtCtx->u64RegR11);
1406 if (RT_SUCCESS(rc))
1407 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R12, &pNtCtx->u64RegR12);
1408 if (RT_SUCCESS(rc))
1409 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R13, &pNtCtx->u64RegR13);
1410 if (RT_SUCCESS(rc))
1411 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R14, &pNtCtx->u64RegR14);
1412 if (RT_SUCCESS(rc))
1413 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R15, &pNtCtx->u64RegR15);
1414 if (RT_SUCCESS(rc))
1415 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1416 }
1417
1418 if ( RT_SUCCESS(rc)
1419 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1420 {
1421 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u16SegDs);
1422 if (RT_SUCCESS(rc))
1423 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u16SegEs);
1424 if (RT_SUCCESS(rc))
1425 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u16SegFs);
1426 if (RT_SUCCESS(rc))
1427 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u16SegGs);
1428 if (RT_SUCCESS(rc))
1429 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1430 }
1431
1432 if ( RT_SUCCESS(rc)
1433 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1434 {
1435 /** @todo. */
1436 }
1437
1438 if ( RT_SUCCESS(rc)
1439 && fCtxFlags & NTCONTEXT_F_DEBUG)
1440 {
1441 /** @todo. */
1442 }
1443
1444 return rc;
1445}
1446
1447
1448/**
1449 * Fills in the given 32bit NT context structure with the requested values.
1450 *
1451 * @returns VBox status code.
1452 * @param pThis The KD context.
1453 * @param idCpu The CPU to query the context for.
1454 * @param pNtCtx The NT context structure to fill in.
1455 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1456 */
1457static int dbgcKdCtxQueryNtCtx32(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT32 pNtCtx, uint32_t fCtxFlags)
1458{
1459 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1460
1461 pNtCtx->fContext = NTCONTEXT_F_X86;
1462
1463 int rc = VINF_SUCCESS;
1464 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1465 {
1466 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u32SegCs);
1467 if (RT_SUCCESS(rc))
1468 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u32SegSs);
1469 if (RT_SUCCESS(rc))
1470 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EIP, &pNtCtx->u32RegEip);
1471 if (RT_SUCCESS(rc))
1472 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESP, &pNtCtx->u32RegEsp);
1473 if (RT_SUCCESS(rc))
1474 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBP, &pNtCtx->u32RegEbp);
1475 if (RT_SUCCESS(rc))
1476 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1477 if (RT_SUCCESS(rc))
1478 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1479 }
1480
1481 if ( RT_SUCCESS(rc)
1482 && fCtxFlags & NTCONTEXT_F_INTEGER)
1483 {
1484 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EAX, &pNtCtx->u32RegEax);
1485 if (RT_SUCCESS(rc))
1486 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ECX, &pNtCtx->u32RegEcx);
1487 if (RT_SUCCESS(rc))
1488 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDX, &pNtCtx->u32RegEdx);
1489 if (RT_SUCCESS(rc))
1490 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBX, &pNtCtx->u32RegEbx);
1491 if (RT_SUCCESS(rc))
1492 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESI, &pNtCtx->u32RegEsi);
1493 if (RT_SUCCESS(rc))
1494 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDI, &pNtCtx->u32RegEdi);
1495 if (RT_SUCCESS(rc))
1496 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1497 }
1498
1499 if ( RT_SUCCESS(rc)
1500 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1501 {
1502 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u32SegDs);
1503 if (RT_SUCCESS(rc))
1504 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u32SegEs);
1505 if (RT_SUCCESS(rc))
1506 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u32SegFs);
1507 if (RT_SUCCESS(rc))
1508 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u32SegGs);
1509 if (RT_SUCCESS(rc))
1510 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1511 }
1512
1513 if ( RT_SUCCESS(rc)
1514 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1515 {
1516 /** @todo. */
1517 }
1518
1519 if ( RT_SUCCESS(rc)
1520 && fCtxFlags & NTCONTEXT_F_DEBUG)
1521 {
1522 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pNtCtx->u32RegDr0);
1523 if (RT_SUCCESS(rc))
1524 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pNtCtx->u32RegDr1);
1525 if (RT_SUCCESS(rc))
1526 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pNtCtx->u32RegDr3);
1527 if (RT_SUCCESS(rc))
1528 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pNtCtx->u32RegDr6);
1529 if (RT_SUCCESS(rc))
1530 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pNtCtx->u32RegDr7);
1531 if (RT_SUCCESS(rc))
1532 pNtCtx->fContext |= NTCONTEXT_F_DEBUG;
1533 }
1534
1535 return rc;
1536}
1537
1538
1539#define KD_REG_INIT(a_pszName, a_enmType, a_ValMember, a_Val) \
1540 do \
1541 { \
1542 aRegsSet[idxReg].pszName = a_pszName; \
1543 aRegsSet[idxReg].enmType = a_enmType; \
1544 aRegsSet[idxReg].Val.a_ValMember = a_Val; \
1545 idxReg++; \
1546 } while (0)
1547#define KD_REG_INIT_DTR(a_pszName, a_Base, a_Limit) \
1548 do \
1549 { \
1550 aRegsSet[idxReg].pszName = a_pszName; \
1551 aRegsSet[idxReg].enmType = DBGFREGVALTYPE_DTR; \
1552 aRegsSet[idxReg].Val.dtr.u64Base = a_Base; \
1553 aRegsSet[idxReg].Val.dtr.u32Limit = a_Limit; \
1554 idxReg++; \
1555 } while (0)
1556#define KD_REG_INIT_U16(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U16, u16, a_Val)
1557#define KD_REG_INIT_U32(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U32, u32, a_Val)
1558#define KD_REG_INIT_U64(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U64, u64, a_Val)
1559
1560
1561/**
1562 * Writes the indicated values from the given context structure to the guests register set.
1563 *
1564 * @returns VBox status code.
1565 * @param pThis The KD context.
1566 * @param idCpu The CPU to query the context for.
1567 * @param pNtCtx The NT context structure to set.
1568 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to set.
1569 */
1570static int dbgcKdCtxSetNtCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1571{
1572 uint32_t idxReg = 0;
1573 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1574
1575 KD_REG_INIT_U32("mxcsr", pNtCtx->u32RegMxCsr);
1576
1577 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1578 {
1579#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1580 KD_REG_INIT_U16("cs", pNtCtx->u16SegCs);
1581 KD_REG_INIT_U16("ss", pNtCtx->u16SegSs);
1582#endif
1583 KD_REG_INIT_U64("rip", pNtCtx->u64RegRip);
1584 KD_REG_INIT_U64("rsp", pNtCtx->u64RegRsp);
1585 KD_REG_INIT_U64("rbp", pNtCtx->u64RegRbp);
1586 KD_REG_INIT_U32("rflags", pNtCtx->u32RegEflags);
1587 }
1588
1589 if (fCtxFlags & NTCONTEXT_F_INTEGER)
1590 {
1591 KD_REG_INIT_U64("rax", pNtCtx->u64RegRax);
1592 KD_REG_INIT_U64("rcx", pNtCtx->u64RegRcx);
1593 KD_REG_INIT_U64("rdx", pNtCtx->u64RegRdx);
1594 KD_REG_INIT_U64("rbx", pNtCtx->u64RegRbx);
1595 KD_REG_INIT_U64("rsi", pNtCtx->u64RegRsi);
1596 KD_REG_INIT_U64("rdi", pNtCtx->u64RegRdi);
1597 KD_REG_INIT_U64("r8", pNtCtx->u64RegR8);
1598 KD_REG_INIT_U64("r9", pNtCtx->u64RegR9);
1599 KD_REG_INIT_U64("r10", pNtCtx->u64RegR10);
1600 KD_REG_INIT_U64("r11", pNtCtx->u64RegR11);
1601 KD_REG_INIT_U64("r12", pNtCtx->u64RegR12);
1602 KD_REG_INIT_U64("r13", pNtCtx->u64RegR13);
1603 KD_REG_INIT_U64("r14", pNtCtx->u64RegR14);
1604 KD_REG_INIT_U64("r15", pNtCtx->u64RegR15);
1605 }
1606
1607 if (fCtxFlags & NTCONTEXT_F_SEGMENTS)
1608 {
1609#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1610 KD_REG_INIT_U16("ds", pNtCtx->u16SegDs);
1611 KD_REG_INIT_U16("es", pNtCtx->u16SegEs);
1612 KD_REG_INIT_U16("fs", pNtCtx->u16SegFs);
1613 KD_REG_INIT_U16("gs", pNtCtx->u16SegGs);
1614#endif
1615 }
1616
1617 if (fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1618 {
1619 /** @todo. */
1620 }
1621
1622 if (fCtxFlags & NTCONTEXT_F_DEBUG)
1623 {
1624 /** @todo. */
1625 }
1626
1627 return DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
1628}
1629
1630
1631/**
1632 * Fills in the given 64bit NT kernel context structure with the requested values.
1633 *
1634 * @returns VBox status code.
1635 * @param pThis The KD context.
1636 * @param idCpu The CPU to query the context for.
1637 * @param pKNtCtx The NT context structure to fill in.
1638 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1639 */
1640static int dbgcKdCtxQueryNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT64 pKNtCtx, uint32_t fCtxFlags)
1641{
1642 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
1643
1644 int rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u64RegCr0);
1645 if (RT_SUCCESS(rc))
1646 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u64RegCr2);
1647 if (RT_SUCCESS(rc))
1648 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u64RegCr3);
1649 if (RT_SUCCESS(rc))
1650 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u64RegCr4);
1651 if (RT_SUCCESS(rc))
1652 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR8, &pKNtCtx->u64RegCr8);
1653 if (RT_SUCCESS(rc))
1654 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pKNtCtx->u64RegDr0);
1655 if (RT_SUCCESS(rc))
1656 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pKNtCtx->u64RegDr1);
1657 if (RT_SUCCESS(rc))
1658 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR2, &pKNtCtx->u64RegDr2);
1659 if (RT_SUCCESS(rc))
1660 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pKNtCtx->u64RegDr3);
1661 if (RT_SUCCESS(rc))
1662 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pKNtCtx->u64RegDr6);
1663 if (RT_SUCCESS(rc))
1664 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pKNtCtx->u64RegDr7);
1665 if (RT_SUCCESS(rc))
1666 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
1667 if (RT_SUCCESS(rc))
1668 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u64PtrBase);
1669 if (RT_SUCCESS(rc))
1670 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
1671 if (RT_SUCCESS(rc))
1672 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u64PtrBase);
1673 if (RT_SUCCESS(rc))
1674 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
1675 if (RT_SUCCESS(rc))
1676 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
1677 if (RT_SUCCESS(rc))
1678 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pKNtCtx->u32RegMxCsr);
1679 /** @todo Debug control and stuff. */
1680
1681 if (RT_SUCCESS(rc))
1682 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_GS_BASE, &pKNtCtx->u64MsrGsBase);
1683 if (RT_SUCCESS(rc))
1684 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_KERNEL_GS_BASE, &pKNtCtx->u64MsrKernelGsBase);
1685 if (RT_SUCCESS(rc))
1686 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K6_STAR, &pKNtCtx->u64MsrStar);
1687 if (RT_SUCCESS(rc))
1688 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_LSTAR, &pKNtCtx->u64MsrLstar);
1689 if (RT_SUCCESS(rc))
1690 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_CSTAR, &pKNtCtx->u64MsrCstar);
1691 if (RT_SUCCESS(rc))
1692 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_SF_MASK, &pKNtCtx->u64MsrSfMask);
1693 /** @todo XCR0 */
1694
1695 if (RT_SUCCESS(rc))
1696 rc = dbgcKdCtxQueryNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, fCtxFlags);
1697
1698 return rc;
1699}
1700
1701
1702/**
1703 * Fills in the given 32bit NT kernel context structure with the requested values.
1704 *
1705 * @returns VBox status code.
1706 * @param pThis The KD context.
1707 * @param idCpu The CPU to query the context for.
1708 * @param pKNtCtx The NT context structure to fill in.
1709 */
1710static int dbgcKdCtxQueryNtKCtx32(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT32 pKNtCtx)
1711{
1712 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
1713
1714 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u32RegCr0);
1715 if (RT_SUCCESS(rc))
1716 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u32RegCr2);
1717 if (RT_SUCCESS(rc))
1718 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u32RegCr3);
1719 if (RT_SUCCESS(rc))
1720 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u32RegCr4);
1721
1722 if (RT_SUCCESS(rc))
1723 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pKNtCtx->u32RegDr0);
1724 if (RT_SUCCESS(rc))
1725 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pKNtCtx->u32RegDr1);
1726 if (RT_SUCCESS(rc))
1727 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR2, &pKNtCtx->u32RegDr2);
1728 if (RT_SUCCESS(rc))
1729 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pKNtCtx->u32RegDr3);
1730 if (RT_SUCCESS(rc))
1731 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pKNtCtx->u32RegDr6);
1732 if (RT_SUCCESS(rc))
1733 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pKNtCtx->u32RegDr7);
1734 if (RT_SUCCESS(rc))
1735 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
1736 if (RT_SUCCESS(rc))
1737 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u32PtrBase);
1738 if (RT_SUCCESS(rc))
1739 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
1740 if (RT_SUCCESS(rc))
1741 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u32PtrBase);
1742 if (RT_SUCCESS(rc))
1743 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
1744 if (RT_SUCCESS(rc))
1745 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
1746
1747 return rc;
1748}
1749
1750
1751/**
1752 * Fills in the given 64bit NT kernel context structure with the requested values.
1753 *
1754 * @returns VBox status code.
1755 * @param pThis The KD context.
1756 * @param idCpu The CPU to query the context for.
1757 * @param pKNtCtx The NT context structure to fill in.
1758 * @param cbSet How many bytes of the context are valid.
1759 */
1760static int dbgcKdCtxSetNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTKCONTEXT64 pKNtCtx, size_t cbSet)
1761{
1762 AssertReturn(cbSet >= RT_UOFFSETOF(NTKCONTEXT64, Ctx), VERR_INVALID_PARAMETER);
1763
1764 uint32_t idxReg = 0;
1765 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1766
1767 KD_REG_INIT_U64("cr0", pKNtCtx->u64RegCr0);
1768 KD_REG_INIT_U64("cr2", pKNtCtx->u64RegCr2);
1769 KD_REG_INIT_U64("cr3", pKNtCtx->u64RegCr3);
1770 KD_REG_INIT_U64("cr4", pKNtCtx->u64RegCr4);
1771 KD_REG_INIT_U64("cr8", pKNtCtx->u64RegCr8);
1772 KD_REG_INIT_U64("dr0", pKNtCtx->u64RegDr0);
1773 KD_REG_INIT_U64("dr1", pKNtCtx->u64RegDr1);
1774 KD_REG_INIT_U64("dr2", pKNtCtx->u64RegDr2);
1775 KD_REG_INIT_U64("dr3", pKNtCtx->u64RegDr3);
1776 KD_REG_INIT_U64("dr6", pKNtCtx->u64RegDr6);
1777 KD_REG_INIT_U64("dr7", pKNtCtx->u64RegDr7);
1778
1779 KD_REG_INIT_DTR("gdtr", pKNtCtx->Gdtr.u64PtrBase, pKNtCtx->Gdtr.u16Limit);
1780 KD_REG_INIT_DTR("idtr", pKNtCtx->Idtr.u64PtrBase, pKNtCtx->Idtr.u16Limit);
1781
1782#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1783 KD_REG_INIT_U16("tr", pKNtCtx->u16RegTr);
1784 KD_REG_INIT_U16("ldtr", pKNtCtx->u16RegLdtr);
1785#endif
1786 KD_REG_INIT_U32("mxcsr", pKNtCtx->u32RegMxCsr);
1787
1788 KD_REG_INIT_U64("msr_gs_base", pKNtCtx->u64MsrGsBase);
1789 KD_REG_INIT_U64("krnl_gs_base", pKNtCtx->u64MsrKernelGsBase);
1790 KD_REG_INIT_U64("star", pKNtCtx->u64MsrStar);
1791 KD_REG_INIT_U64("lstar", pKNtCtx->u64MsrLstar);
1792 KD_REG_INIT_U64("cstar", pKNtCtx->u64MsrCstar);
1793 KD_REG_INIT_U64("sf_mask", pKNtCtx->u64MsrSfMask);
1794
1795 int rc = DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
1796 if ( RT_SUCCESS(rc)
1797 && cbSet > RT_UOFFSETOF(NTKCONTEXT64, Ctx)) /** @todo Probably wrong. */
1798 rc = dbgcKdCtxSetNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, pKNtCtx->Ctx.fContext);
1799
1800 return rc;
1801}
1802
1803#undef KD_REG_INIT_64
1804#undef KD_REG_INIT_32
1805#undef KD_REG_INIT_16
1806#undef KD_REG_INIT_DTR
1807#undef KD_REG_INIT
1808
1809
1810/**
1811 * Validates the given KD packet header.
1812 *
1813 * @returns Flag whether the packet header is valid, false if invalid.
1814 * @param pPktHdr The packet header to validate.
1815 */
1816static bool dbgcKdPktHdrValidate(PCKDPACKETHDR pPktHdr)
1817{
1818 if ( pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_DATA
1819 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_CONTROL
1820 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_BREAKIN)
1821 return false;
1822
1823 if (pPktHdr->u16SubType >= KD_PACKET_HDR_SUB_TYPE_MAX)
1824 return false;
1825
1826 uint32_t idPacket = pPktHdr->idPacket & UINT32_C(0xfffffffe);
1827 if ( idPacket != KD_PACKET_HDR_ID_INITIAL
1828 && idPacket != KD_PACKET_HDR_ID_RESET
1829 && idPacket != 0 /* Happens on the very first packet */)
1830 return false;
1831
1832 return true;
1833}
1834
1835
1836/**
1837 * Generates a checksum from the given buffer.
1838 *
1839 * @returns Generated checksum.
1840 * @param pv The data to generate a checksum from.
1841 * @param cb Number of bytes to checksum.
1842 */
1843static uint32_t dbgcKdPktChkSumGen(const void *pv, size_t cb)
1844{
1845 const uint8_t *pb = (const uint8_t *)pv;
1846 uint32_t u32ChkSum = 0;
1847
1848 while (cb--)
1849 u32ChkSum += *pb++;
1850
1851 return u32ChkSum;
1852}
1853
1854
1855/**
1856 * Generates a checksum from the given segments.
1857 *
1858 * @returns Generated checksum.
1859 * @param paSegs Pointer to the array of segments containing the data.
1860 * @param cSegs Number of segments.
1861 * @param pcbChkSum Where to store the number of bytes checksummed, optional.
1862 */
1863static uint32_t dbgcKdPktChkSumGenSg(PCRTSGSEG paSegs, uint32_t cSegs, size_t *pcbChkSum)
1864{
1865 size_t cbChkSum = 0;
1866 uint32_t u32ChkSum = 0;
1867
1868 for (uint32_t i = 0; i < cSegs; i++)
1869 {
1870 u32ChkSum += dbgcKdPktChkSumGen(paSegs[i].pvSeg, paSegs[i].cbSeg);
1871 cbChkSum += paSegs[i].cbSeg;
1872 }
1873
1874 if (pcbChkSum)
1875 *pcbChkSum = cbChkSum;
1876
1877 return u32ChkSum;
1878}
1879
1880
1881/**
1882 * Waits for an acknowledgment.
1883 *
1884 * @returns VBox status code.
1885 * @param pThis The KD context.
1886 * @param msWait Maximum number of milliseconds to wait for an acknowledge.
1887 * @param pfResend Where to store the resend requested flag on success.
1888 */
1889static int dbgcKdCtxPktWaitForAck(PKDCTX pThis, RTMSINTERVAL msWait, bool *pfResend)
1890{
1891 KDPACKETHDR PktAck;
1892 uint8_t *pbCur = (uint8_t *)&PktAck;
1893 size_t cbLeft = sizeof(PktAck);
1894 uint64_t tsStartMs = RTTimeMilliTS();
1895 int rc = VINF_SUCCESS;
1896
1897 LogFlowFunc(("pThis=%p msWait=%u pfResend=%p\n", pThis, msWait, pfResend));
1898
1899 RT_ZERO(PktAck);
1900
1901 /* There might be breakin packets in the queue, read until we get something else. */
1902 while ( msWait
1903 && RT_SUCCESS(rc))
1904 {
1905 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
1906 {
1907 size_t cbRead = 0;
1908 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, 1, &cbRead);
1909 if ( RT_SUCCESS(rc)
1910 && cbRead == 1)
1911 {
1912 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
1913 msWait -= RT_MIN(msWait, tsSpanMs);
1914 tsStartMs = RTTimeMilliTS();
1915
1916 if (*pbCur == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
1917 pThis->fBreakinRecv = true;
1918 else
1919 {
1920 pbCur++;
1921 cbLeft--;
1922 break;
1923 }
1924 }
1925 }
1926 else
1927 rc = VERR_TIMEOUT;
1928 }
1929
1930 if ( RT_SUCCESS(rc)
1931 && !msWait)
1932 rc = VERR_TIMEOUT;
1933
1934 if (RT_SUCCESS(rc))
1935 {
1936 while ( msWait
1937 && RT_SUCCESS(rc)
1938 && cbLeft)
1939 {
1940 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
1941 {
1942 size_t cbRead = 0;
1943 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, cbLeft, &cbRead);
1944 if (RT_SUCCESS(rc))
1945 {
1946 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
1947 msWait -= RT_MIN(msWait, tsSpanMs);
1948 tsStartMs = RTTimeMilliTS();
1949
1950 cbLeft -= cbRead;
1951 pbCur += cbRead;
1952 }
1953 }
1954 else
1955 rc = VERR_TIMEOUT;
1956 }
1957
1958 if (RT_SUCCESS(rc))
1959 {
1960 if (PktAck.u32Signature == KD_PACKET_HDR_SIGNATURE_CONTROL)
1961 {
1962 if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE)
1963 rc = VINF_SUCCESS;
1964 else if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_RESEND)
1965 {
1966 *pfResend = true;
1967 rc = VINF_SUCCESS;
1968 }
1969 else
1970 rc = VERR_NET_PROTOCOL_ERROR;
1971 }
1972 else
1973 rc = VERR_NET_PROTOCOL_ERROR;
1974 }
1975 }
1976
1977 LogFlowFunc(("returns rc=%Rrc *pfResend=%RTbool\n", rc, *pfResend));
1978 return rc;
1979}
1980
1981
1982/**
1983 * Sends the given packet header and optional segmented body (the trailing byte is sent automatically).
1984 *
1985 * @returns VBox status code.
1986 * @param pThis The KD context.
1987 * @param u32Signature The signature to send.
1988 * @param u16SubType The sub type to send.
1989 * @param paSegs Pointer to the array of segments to send in the body, optional.
1990 * @param cSegs Number of segments.
1991 * @param fAck Flag whether to wait for an acknowledge.
1992 */
1993static int dbgcKdCtxPktSendSg(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
1994 PCRTSGSEG paSegs, uint32_t cSegs, bool fAck)
1995{
1996 int rc = VINF_SUCCESS;
1997 uint32_t cRetriesLeft = 3;
1998 uint8_t bTrailer = KD_PACKET_TRAILING_BYTE;
1999 KDPACKETHDR Hdr;
2000
2001 size_t cbChkSum = 0;
2002 uint32_t u32ChkSum = dbgcKdPktChkSumGenSg(paSegs, cSegs, &cbChkSum);
2003
2004 Hdr.u32Signature = u32Signature;
2005 Hdr.u16SubType = u16SubType;
2006 Hdr.cbBody = (uint16_t)cbChkSum;
2007 Hdr.idPacket = pThis->idPktNext;
2008 Hdr.u32ChkSum = u32ChkSum;
2009
2010#ifdef LOG_ENABLED
2011 dbgcKdPktDump(&Hdr, paSegs, cSegs, false /*fRx*/);
2012#endif
2013
2014 while (cRetriesLeft--)
2015 {
2016 bool fResend = false;
2017
2018 rc = dbgcKdCtxWrite(pThis, &Hdr, sizeof(Hdr));
2019 if ( RT_SUCCESS(rc)
2020 && paSegs
2021 && cSegs)
2022 {
2023 for (uint32_t i = 0; i < cSegs && RT_SUCCESS(rc); i++)
2024 rc = dbgcKdCtxWrite(pThis, paSegs[i].pvSeg, paSegs[i].cbSeg);
2025
2026 if (RT_SUCCESS(rc))
2027 rc = dbgcKdCtxWrite(pThis, &bTrailer, sizeof(bTrailer));
2028 }
2029
2030 if (RT_SUCCESS(rc))
2031 {
2032 if (fAck)
2033 rc = dbgcKdCtxPktWaitForAck(pThis, 10 * 1000, &fResend);
2034
2035 if ( RT_SUCCESS(rc)
2036 && !fResend)
2037 break;
2038 }
2039 }
2040
2041 return rc;
2042}
2043
2044
2045/**
2046 * Sends the given packet header and optional body (the trailing byte is sent automatically).
2047 *
2048 * @returns VBox status code.
2049 * @param pThis The KD context.
2050 * @param u32Signature The signature to send.
2051 * @param u16SubType The sub type to send.
2052 * @param pvBody The body to send, optional.
2053 * @param cbBody Body size in bytes.
2054 * @param fAck Flag whether to wait for an acknowledge.
2055 */
2056DECLINLINE(int) dbgcKdCtxPktSend(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2057 const void *pvBody, size_t cbBody,
2058 bool fAck)
2059{
2060 RTSGSEG Seg;
2061
2062 Seg.pvSeg = (void *)pvBody;
2063 Seg.cbSeg = cbBody;
2064 return dbgcKdCtxPktSendSg(pThis, u32Signature, u16SubType, cbBody ? &Seg : NULL, cbBody ? 1 : 0, fAck);
2065}
2066
2067
2068/**
2069 * Sends a resend packet answer.
2070 *
2071 * @returns VBox status code.
2072 * @param pThis The KD context.
2073 */
2074DECLINLINE(int) dbgcKdCtxPktSendResend(PKDCTX pThis)
2075{
2076 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESEND,
2077 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2078}
2079
2080
2081/**
2082 * Sends a resend packet answer.
2083 *
2084 * @returns VBox status code.
2085 * @param pThis The KD context.
2086 */
2087DECLINLINE(int) dbgcKdCtxPktSendReset(PKDCTX pThis)
2088{
2089 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2090 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESET,
2091 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2092}
2093
2094
2095/**
2096 * Sends an acknowledge packet answer.
2097 *
2098 * @returns VBox status code.
2099 * @param pThis The KD context.
2100 */
2101DECLINLINE(int) dbgcKdCtxPktSendAck(PKDCTX pThis)
2102{
2103 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE,
2104 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2105}
2106
2107
2108/**
2109 * Resets the packet receive state machine.
2110 *
2111 * @returns nothing.
2112 * @param pThis The KD context.
2113 */
2114static void dbgcKdCtxPktRecvReset(PKDCTX pThis)
2115{
2116 pThis->enmState = KDRECVSTATE_PACKET_HDR_FIRST_BYTE;
2117 pThis->pbRecv = &pThis->PktHdr.ab[0];
2118 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[0]);
2119 pThis->msRecvTimeout = RT_INDEFINITE_WAIT;
2120 pThis->tsRecvLast = RTTimeMilliTS();
2121}
2122
2123
2124/**
2125 * Sends a Debug I/O string packet.
2126 *
2127 * @returns VBox status code.
2128 * @param pThis The KD context data.
2129 * @param idCpu The CPU ID generating this packet.
2130 * @param pachChars The characters to send (ASCII).
2131 * @param cbChars Number of characters to send.
2132 */
2133static int dbgcKdCtxDebugIoStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachChars, size_t cbChars)
2134{
2135 KDPACKETDEBUGIO DebugIo;
2136 RT_ZERO(DebugIo);
2137
2138 /* Fix your damn log strings if this exceeds 4GB... */
2139 if (cbChars != (uint32_t)cbChars)
2140 return VERR_BUFFER_OVERFLOW;
2141
2142 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2143 DebugIo.u16CpuLvl = 0x6;
2144 DebugIo.idCpu = (uint16_t)idCpu;
2145 DebugIo.u.Str.cbStr = (uint32_t)cbChars;
2146
2147 RTSGSEG aRespSegs[2];
2148
2149 aRespSegs[0].pvSeg = &DebugIo;
2150 aRespSegs[0].cbSeg = sizeof(DebugIo);
2151 aRespSegs[1].pvSeg = (void *)pachChars;
2152 aRespSegs[1].cbSeg = cbChars;
2153
2154 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2155 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2156}
2157
2158
2159/**
2160 * Sends a state change event packet.
2161 *
2162 * @returns VBox status code.
2163 * @param pThis The KD context data.
2164 * @param enmType The event type.
2165 */
2166static int dbgcKdCtxStateChangeSend(PKDCTX pThis, DBGFEVENTTYPE enmType)
2167{
2168 LogFlowFunc(("pThis=%p enmType=%u\n", pThis, enmType));
2169
2170 /* Select the record to send based on the CPU mode. */
2171 int rc = VINF_SUCCESS;
2172 KDPACKETSTATECHANGE64 StateChange64;
2173 RT_ZERO(StateChange64);
2174
2175 StateChange64.u32StateNew = KD_PACKET_STATE_CHANGE_EXCEPTION;
2176 StateChange64.u16CpuLvl = 0x6; /** @todo Figure this one out. */
2177 StateChange64.idCpu = pThis->Dbgc.idCpu;
2178 StateChange64.cCpus = (uint16_t)DBGFR3CpuGetCount(pThis->Dbgc.pUVM);
2179 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RIP, &StateChange64.u64RipThread);
2180 if (RT_SUCCESS(rc))
2181 {
2182 DBGFADDRESS AddrRip;
2183 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRip, StateChange64.u64RipThread);
2184
2185 StateChange64.u64RipThread = KD_PTR_CREATE(pThis, StateChange64.u64RipThread);
2186
2187 /** @todo Properly fill in the exception record. */
2188 switch (enmType)
2189 {
2190 case DBGFEVENT_HALT_DONE:
2191 case DBGFEVENT_BREAKPOINT:
2192 case DBGFEVENT_BREAKPOINT_IO:
2193 case DBGFEVENT_BREAKPOINT_MMIO:
2194 case DBGFEVENT_BREAKPOINT_HYPER:
2195 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_BKPT;
2196 break;
2197 case DBGFEVENT_STEPPED:
2198 case DBGFEVENT_STEPPED_HYPER:
2199 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_SINGLE_STEP;
2200 break;
2201 default:
2202 AssertMsgFailed(("Invalid DBGF event type for state change %d!\n", enmType));
2203 }
2204
2205 StateChange64.u.Exception.ExcpRec.cExcpParms = 3;
2206 StateChange64.u.Exception.u32FirstChance = 0x1;
2207
2208 /** @todo Properly fill in the control report. */
2209 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR6, &StateChange64.uCtrlReport.Amd64.u64RegDr6);
2210 if (RT_SUCCESS(rc))
2211 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR7, &StateChange64.uCtrlReport.Amd64.u64RegDr7);
2212 if (RT_SUCCESS(rc))
2213 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RFLAGS, &StateChange64.uCtrlReport.Amd64.u32RegEflags);
2214 if (RT_SUCCESS(rc))
2215 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_CS, &StateChange64.uCtrlReport.Amd64.u16SegCs);
2216 if (RT_SUCCESS(rc))
2217 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DS, &StateChange64.uCtrlReport.Amd64.u16SegDs);
2218 if (RT_SUCCESS(rc))
2219 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_ES, &StateChange64.uCtrlReport.Amd64.u16SegEs);
2220 if (RT_SUCCESS(rc))
2221 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_FS, &StateChange64.uCtrlReport.Amd64.u16SegFs);
2222
2223 /* Read instruction bytes. */
2224 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
2225 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
2226 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
2227 if (RT_SUCCESS(rc))
2228 {
2229 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2230 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
2231 &StateChange64, sizeof(StateChange64), false /*fAck*/);
2232 }
2233 }
2234
2235 LogFlowFunc(("returns %Rrc\n", rc));
2236 return rc;
2237}
2238
2239
2240/**
2241 * Processes a get version 64 request.
2242 *
2243 * @returns VBox status code.
2244 * @param pThis The KD context.
2245 * @param pPktManip The manipulate packet request.
2246 */
2247static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2248{
2249 KDPACKETMANIPULATE64 Resp;
2250 RT_ZERO(Resp);
2251
2252 /* Fill in the generic part. */
2253 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
2254 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2255 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
2256 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
2257
2258 /* Build our own response in case there is no Windows interface available. */
2259 uint32_t NtBuildNumber = 0x0f2800; /* Used when there is no NT interface available, which probably breaks symbol loading. */
2260 bool f32Bit = false;
2261 if (pThis->pIfWinNt)
2262 {
2263 int rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM,
2264 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
2265 &NtBuildNumber, &f32Bit);
2266 if (RT_SUCCESS(rc))
2267 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, &Resp.u.GetVersion.u64PtrKernBase,
2268 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2269 }
2270
2271 /* Fill in the request specific part. */
2272 Resp.u.GetVersion.u16VersMaj = NtBuildNumber >> 16;
2273 Resp.u.GetVersion.u16VersMin = NtBuildNumber & UINT32_C(0xffff);
2274 Resp.u.GetVersion.u8VersProtocol = 0x6; /* From a Windows 10 guest. */
2275 Resp.u.GetVersion.u8VersKdSecondary = pThis->f32Bit ? 0 : 0x2; /* amd64 has a versioned context (0 and 1 are obsolete). */
2276 Resp.u.GetVersion.fFlags = KD_PACKET_MANIPULATE64_GET_VERSION_F_MP;
2277 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
2278 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
2279 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_MAX - KD_PACKET_MANIPULATE_REQ_MIN;
2280 Resp.u.GetVersion.u64PtrDebuggerDataList = 0;
2281
2282 if (f32Bit)
2283 {
2284 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_I386;
2285 Resp.u.GetVersion.u64PtrKernBase = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrKernBase);
2286 Resp.u.GetVersion.u64PtrPsLoadedModuleList = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2287 }
2288 else
2289 {
2290 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
2291 Resp.u.GetVersion.fFlags |= KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64;
2292 }
2293
2294 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2295 &Resp, sizeof(Resp), true /*fAck*/);
2296}
2297
2298
2299/**
2300 * Processes a read memory 64 request.
2301 *
2302 * @returns VBox status code.
2303 * @param pThis The KD context.
2304 * @param pPktManip The manipulate packet request.
2305 */
2306static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2307{
2308 KDPACKETMANIPULATEHDR RespHdr;
2309 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2310 uint8_t abMem[_4K];
2311 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2312
2313 DBGFADDRESS AddrRead;
2314 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
2315 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
2316 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2317 else
2318 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2319
2320 RTSGSEG aRespSegs[3];
2321 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2322 RespHdr.idReq = pPktManip->Hdr.idReq;
2323 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2324 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2325 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2326
2327 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2328 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2329 XferMem64.cbXfered = (uint32_t)cbRead;
2330
2331 aRespSegs[0].pvSeg = &RespHdr;
2332 aRespSegs[0].cbSeg = sizeof(RespHdr);
2333 aRespSegs[1].pvSeg = &XferMem64;
2334 aRespSegs[1].cbSeg = sizeof(XferMem64);
2335
2336 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
2337 if (RT_SUCCESS(rc))
2338 {
2339 cSegs++;
2340 aRespSegs[2].pvSeg = &abMem[0];
2341 aRespSegs[2].cbSeg = cbRead;
2342 }
2343 else
2344 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2345
2346 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2347 &aRespSegs[0], cSegs, true /*fAck*/);
2348}
2349
2350
2351/**
2352 * Processes a write memory 64 request.
2353 *
2354 * @returns VBox status code.
2355 * @param pThis The KD context.
2356 * @param pPktManip The manipulate packet request.
2357 */
2358static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2359{
2360 KDPACKETMANIPULATEHDR RespHdr;
2361 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2362 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2363
2364 DBGFADDRESS AddrWrite;
2365 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2366 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
2367 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
2368 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2369 else
2370 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2371
2372 RTSGSEG aRespSegs[2];
2373 uint32_t cSegs = 2;
2374 RespHdr.idReq = pPktManip->Hdr.idReq;
2375 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2376 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2377 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2378
2379 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2380 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2381 XferMem64.cbXfered = (uint32_t)cbWrite;
2382
2383 aRespSegs[0].pvSeg = &RespHdr;
2384 aRespSegs[0].cbSeg = sizeof(RespHdr);
2385 aRespSegs[1].pvSeg = &XferMem64;
2386 aRespSegs[1].cbSeg = sizeof(XferMem64);
2387
2388 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
2389 if (RT_FAILURE(rc))
2390 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2391
2392 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2393 &aRespSegs[0], cSegs, true /*fAck*/);
2394}
2395
2396
2397/**
2398 * Processes a continue request.
2399 *
2400 * @returns VBox status code.
2401 * @param pThis The KD context.
2402 * @param pPktManip The manipulate packet request.
2403 */
2404static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2405{
2406 RT_NOREF(pPktManip);
2407 int rc = VINF_SUCCESS;
2408
2409 /* No response, just resume. */
2410 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2411 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2412
2413 return rc;
2414}
2415
2416
2417/**
2418 * Processes a continue request.
2419 *
2420 * @returns VBox status code.
2421 * @param pThis The KD context.
2422 * @param pPktManip The manipulate packet request.
2423 */
2424static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2425{
2426 int rc = VINF_SUCCESS;
2427
2428 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
2429 if (pPktManip->u.Continue2.fTrace)
2430 {
2431 PDBGFADDRESS pStackPop = NULL;
2432 RTGCPTR cbStackPop = 0;
2433 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
2434 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
2435 }
2436 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2437 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2438
2439 pThis->Dbgc.CmdHlp.pfnPrintf(&pThis->Dbgc.CmdHlp, NULL, "TestTestTest\n");
2440
2441 return rc;
2442}
2443
2444
2445/**
2446 * Processes a set context request.
2447 *
2448 * @returns VBox status code.
2449 * @param pThis The KD context.
2450 * @param pPktManip The manipulate packet request.
2451 */
2452static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2453{
2454 KDPACKETMANIPULATEHDR RespHdr;
2455 KDPACKETMANIPULATE_SETCONTEXT SetContext;
2456 RT_ZERO(RespHdr); RT_ZERO(SetContext);
2457
2458 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2459
2460 RTSGSEG aRespSegs[2];
2461 uint32_t cSegs = 2;
2462 RespHdr.idReq = pPktManip->Hdr.idReq;
2463 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2464 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2465 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2466
2467 /** @todo What do these flags mean? Can't be the context state to set because the valid one is
2468 * in NTCONTEXT64::fContext (observed with WinDbg). */
2469 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
2470
2471 aRespSegs[0].pvSeg = &RespHdr;
2472 aRespSegs[0].cbSeg = sizeof(RespHdr);
2473 aRespSegs[1].pvSeg = &SetContext;
2474 aRespSegs[1].cbSeg = sizeof(SetContext);
2475
2476 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, pNtCtx->fContext);
2477 if (RT_FAILURE(rc))
2478 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2479
2480 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2481 &aRespSegs[0], cSegs, true /*fAck*/);
2482}
2483
2484
2485/**
2486 * Processes a read control space 64 request.
2487 *
2488 * @returns VBox status code.
2489 * @param pThis The KD context.
2490 * @param pPktManip The manipulate packet request.
2491 */
2492static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2493{
2494 KDPACKETMANIPULATEHDR RespHdr;
2495 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2496 uint8_t abResp[sizeof(NTKCONTEXT64)];
2497 uint32_t cbData = 0;
2498 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2499 RT_ZERO(abResp);
2500
2501 RTSGSEG aRespSegs[3];
2502 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2503 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
2504 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2505 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2506 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2507
2508 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
2509 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
2510
2511 aRespSegs[0].pvSeg = &RespHdr;
2512 aRespSegs[0].cbSeg = sizeof(RespHdr);
2513 aRespSegs[1].pvSeg = &XferCtrlSpace64;
2514 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
2515
2516 int rc = VINF_SUCCESS;
2517 if (pThis->f32Bit)
2518 {
2519 if (pPktManip->u.XferCtrlSpace.u64IdXfer == sizeof(NTCONTEXT32))
2520 {
2521 /* Queries the kernel context. */
2522 rc = dbgcKdCtxQueryNtKCtx32(pThis, RespHdr.idCpu, (PNTKCONTEXT32)&abResp[0]);
2523 if (RT_SUCCESS(rc))
2524 cbData = sizeof(NTKCONTEXT32);
2525 }
2526 }
2527 else
2528 {
2529 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
2530 {
2531 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
2532 {
2533 if (pThis->pIfWinNt)
2534 {
2535 RTGCUINTPTR GCPtrKpcr = 0;
2536
2537 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2538 &GCPtrKpcr, NULL /*pKpcrb*/);
2539 if (RT_SUCCESS(rc))
2540 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
2541 }
2542
2543 cbData = sizeof(RTGCUINTPTR);
2544 break;
2545 }
2546 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
2547 {
2548 if (pThis->pIfWinNt)
2549 {
2550 RTGCUINTPTR GCPtrKpcrb = 0;
2551
2552 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2553 NULL /*pKpcr*/, &GCPtrKpcrb);
2554 if (RT_SUCCESS(rc))
2555 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
2556 }
2557
2558 cbData = sizeof(RTGCUINTPTR);
2559 break;
2560 }
2561 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
2562 {
2563 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
2564 if (RT_SUCCESS(rc))
2565 cbData = sizeof(NTKCONTEXT64);
2566 break;
2567 }
2568 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
2569 {
2570 if (pThis->pIfWinNt)
2571 {
2572 RTGCUINTPTR GCPtrCurThrd = 0;
2573
2574 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2575 &GCPtrCurThrd);
2576 if (RT_SUCCESS(rc))
2577 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
2578 }
2579
2580 cbData = sizeof(RTGCUINTPTR);
2581 break;
2582 }
2583 default:
2584 rc = VERR_NOT_SUPPORTED;
2585 break;
2586 }
2587 }
2588
2589 if ( RT_SUCCESS(rc)
2590 && cbData)
2591 {
2592 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
2593
2594 cSegs++;
2595 aRespSegs[2].pvSeg = &abResp[0];
2596 aRespSegs[2].cbSeg = cbData;
2597 }
2598 else if (RT_FAILURE(rc))
2599 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2600
2601 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2602 &aRespSegs[0], cSegs, true /*fAck*/);
2603}
2604
2605
2606/**
2607 * Processes a write control space 64 request.
2608 *
2609 * @returns VBox status code.
2610 * @param pThis The KD context.
2611 * @param pPktManip The manipulate packet request.
2612 */
2613static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2614{
2615 KDPACKETMANIPULATEHDR RespHdr;
2616 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2617 uint32_t cbData = 0;
2618 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2619
2620 RTSGSEG aRespSegs[2];
2621 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
2622 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2623 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2624 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2625
2626 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
2627 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
2628
2629 aRespSegs[0].pvSeg = &RespHdr;
2630 aRespSegs[0].cbSeg = sizeof(RespHdr);
2631 aRespSegs[1].pvSeg = &XferCtrlSpace64;
2632 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
2633
2634 int rc = VINF_SUCCESS;
2635 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
2636 {
2637 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
2638 {
2639 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2640 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
2641 if (RT_SUCCESS(rc))
2642 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
2643 break;
2644 }
2645 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
2646 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
2647 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
2648 default:
2649 rc = VERR_NOT_SUPPORTED;
2650 break;
2651 }
2652
2653 if (RT_FAILURE(rc))
2654 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2655 else
2656 XferCtrlSpace64.cbXfered = cbData;
2657
2658 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2659 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2660}
2661
2662
2663/**
2664 * Processes a restore breakpoint 64 request.
2665 *
2666 * @returns VBox status code.
2667 * @param pThis The KD context.
2668 * @param pPktManip The manipulate packet request.
2669 */
2670static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2671{
2672 KDPACKETMANIPULATEHDR RespHdr;
2673 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
2674 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
2675
2676 RTSGSEG aRespSegs[2];
2677 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
2678 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2679 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2680 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2681
2682 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
2683
2684 aRespSegs[0].pvSeg = &RespHdr;
2685 aRespSegs[0].cbSeg = sizeof(RespHdr);
2686 aRespSegs[1].pvSeg = &RestoreBkpt64;
2687 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
2688
2689 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
2690 if ( RT_FAILURE(rc)
2691 && rc != VERR_DBGF_BP_NOT_FOUND)
2692 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2693
2694 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2695 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2696}
2697
2698
2699/**
2700 * Processes a write breakpoint 64 request.
2701 *
2702 * @returns VBox status code.
2703 * @param pThis The KD context.
2704 * @param pPktManip The manipulate packet request.
2705 */
2706static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2707{
2708 KDPACKETMANIPULATEHDR RespHdr;
2709 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
2710 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
2711
2712 RTSGSEG aRespSegs[2];
2713 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
2714 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2715 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2716 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2717
2718 aRespSegs[0].pvSeg = &RespHdr;
2719 aRespSegs[0].cbSeg = sizeof(RespHdr);
2720 aRespSegs[1].pvSeg = &WriteBkpt64;
2721 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
2722
2723 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
2724
2725 DBGFADDRESS BpAddr;
2726 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, KD_PTR_GET(pThis, pPktManip->u.WriteBkpt.u64PtrBkpt));
2727 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
2728 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
2729 if (RT_FAILURE(rc))
2730 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2731
2732 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2733 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2734}
2735
2736
2737/**
2738 * Processes a get context extended 64 request.
2739 *
2740 * @returns VBox status code.
2741 * @param pThis The KD context.
2742 * @param pPktManip The manipulate packet request.
2743 */
2744static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2745{
2746 KDPACKETMANIPULATEHDR RespHdr;
2747 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
2748 union
2749 {
2750 NTCONTEXT64 v64;
2751 NTCONTEXT32 v32;
2752 } NtCtx;
2753 RT_ZERO(RespHdr); RT_ZERO(ContextEx); RT_ZERO(NtCtx);
2754
2755 RTSGSEG aRespSegs[3];
2756 uint32_t cSegs = 2;
2757 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
2758 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2759 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2760 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2761
2762 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
2763 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
2764 ContextEx.cbXfered = 0;
2765
2766 aRespSegs[0].pvSeg = &RespHdr;
2767 aRespSegs[0].cbSeg = sizeof(RespHdr);
2768 aRespSegs[1].pvSeg = &ContextEx;
2769 aRespSegs[1].cbSeg = sizeof(ContextEx);
2770
2771 int rc = VINF_SUCCESS;
2772 uint32_t cbCtx = pThis->f32Bit ? sizeof(NtCtx.v32) : sizeof(NtCtx.v64);
2773 if (pThis->f32Bit)
2774 dbgcKdCtxQueryNtCtx32(pThis, pPktManip->Hdr.idCpu, &NtCtx.v32, NTCONTEXT32_F_FULL);
2775 else
2776 dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx.v64, NTCONTEXT64_F_FULL);
2777 if ( RT_SUCCESS(rc)
2778 && pPktManip->u.ContextEx.offStart < cbCtx)
2779 {
2780 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2781 ContextEx.cbXfered = RT_MIN(cbCtx - ContextEx.offStart, ContextEx.cbXfer);
2782
2783 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
2784 aRespSegs[2].cbSeg = ContextEx.cbXfered;
2785 cSegs++;
2786 }
2787
2788 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2789 &aRespSegs[0], cSegs, true /*fAck*/);
2790}
2791
2792
2793/**
2794 * Processes a manipulate packet.
2795 *
2796 * @returns VBox status code.
2797 * @param pThis The KD context.
2798 */
2799static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
2800{
2801 int rc = VINF_SUCCESS;
2802 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
2803
2804 switch (pPktManip->Hdr.idReq)
2805 {
2806 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
2807 {
2808 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
2809 break;
2810 }
2811 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
2812 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
2813 {
2814 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
2815 break;
2816 }
2817 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
2818 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
2819 {
2820 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
2821 break;
2822 }
2823 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
2824 {
2825 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
2826 break;
2827 }
2828 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
2829 {
2830 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
2831 break;
2832 }
2833 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
2834 {
2835 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
2836 break;
2837 }
2838 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
2839 {
2840 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
2841 break;
2842 }
2843 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
2844 {
2845 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
2846 break;
2847 }
2848 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
2849 {
2850 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
2851 break;
2852 }
2853 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
2854 {
2855 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
2856 break;
2857 }
2858 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
2859 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
2860 break;
2861 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
2862 {
2863 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
2864 break;
2865 }
2866 default:
2867 KDPACKETMANIPULATEHDR RespHdr;
2868 RT_ZERO(RespHdr);
2869
2870 RespHdr.idReq = pPktManip->Hdr.idReq;
2871 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2872 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2873 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
2874 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2875 &RespHdr, sizeof(RespHdr), true /*fAck*/);
2876 break;
2877 }
2878
2879 return rc;
2880}
2881
2882
2883/**
2884 * Processes a fully received packet.
2885 *
2886 * @returns VBox status code.
2887 * @param pThis The KD context.
2888 */
2889static int dbgcKdCtxPktProcess(PKDCTX pThis)
2890{
2891 int rc = VINF_SUCCESS;
2892
2893 pThis->fBreakinRecv = false;
2894
2895 /* Verify checksum. */
2896 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
2897 {
2898 /** @todo Check packet id. */
2899 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
2900 {
2901 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
2902 rc = dbgcKdCtxPktSendAck(pThis);
2903 }
2904 if (RT_SUCCESS(rc))
2905 {
2906#ifdef LOG_ENABLED
2907 RTSGSEG Seg;
2908 Seg.pvSeg = &pThis->abBody[0];
2909 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
2910 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
2911#endif
2912
2913 switch (pThis->PktHdr.Fields.u16SubType)
2914 {
2915 case KD_PACKET_HDR_SUB_TYPE_RESET:
2916 {
2917 pThis->idPktNext = 0;
2918 rc = dbgcKdCtxPktSendReset(pThis);
2919 if (RT_SUCCESS(rc))
2920 {
2921 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2922 if (rc == VWRN_DBGF_ALREADY_HALTED)
2923 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2924 }
2925 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
2926 break;
2927 }
2928 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
2929 {
2930 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
2931 rc = dbgcKdCtxPktManipulate64Process(pThis);
2932 break;
2933 }
2934 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
2935 case KD_PACKET_HDR_SUB_TYPE_RESEND:
2936 {
2937 /* Don't do anything. */
2938 rc = VINF_SUCCESS;
2939 break;
2940 }
2941 default:
2942 rc = VERR_NOT_IMPLEMENTED;
2943 }
2944 }
2945 }
2946 else
2947 {
2948 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
2949 rc = dbgcKdCtxPktSendResend(pThis);
2950 }
2951
2952 if (pThis->fBreakinRecv)
2953 {
2954 pThis->fBreakinRecv = false;
2955 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2956 if (rc == VWRN_DBGF_ALREADY_HALTED)
2957 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2958 }
2959
2960 /* Next packet. */
2961 dbgcKdCtxPktRecvReset(pThis);
2962 return rc;
2963}
2964
2965
2966/**
2967 * Processes the received data based on the current state.
2968 *
2969 * @returns VBox status code.
2970 * @param pThis The KD context.
2971 */
2972static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
2973{
2974 int rc = VINF_SUCCESS;
2975
2976 switch (pThis->enmState)
2977 {
2978 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
2979 {
2980 /* Does it look like a valid packet start?. */
2981 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
2982 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
2983 {
2984 pThis->pbRecv = &pThis->PktHdr.ab[1];
2985 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
2986 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
2987 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
2988 }
2989 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2990 {
2991 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2992 if (rc == VWRN_DBGF_ALREADY_HALTED)
2993 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2994 dbgcKdCtxPktRecvReset(pThis);
2995 }
2996 /* else: Ignore and continue. */
2997 break;
2998 }
2999 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
3000 {
3001 /*
3002 * If the first and second byte differ there might be a single breakin
3003 * packet byte received and this is actually the start of a new packet.
3004 */
3005 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
3006 {
3007 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3008 {
3009 /* Halt the VM and rearrange the packet receiving state machine. */
3010 LogFlow(("DbgKd: Halting VM!\n"));
3011
3012 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3013 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
3014 pThis->pbRecv = &pThis->PktHdr.ab[1];
3015 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3016 }
3017 else
3018 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
3019 }
3020 else
3021 {
3022 /* Normal packet receive continues with the rest of the header. */
3023 pThis->pbRecv = &pThis->PktHdr.ab[2];
3024 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
3025 pThis->enmState = KDRECVSTATE_PACKET_HDR;
3026 }
3027 break;
3028 }
3029 case KDRECVSTATE_PACKET_HDR:
3030 {
3031 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
3032 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
3033 {
3034 /* Start receiving the body. */
3035 if (pThis->PktHdr.Fields.cbBody)
3036 {
3037 pThis->pbRecv = &pThis->abBody[0];
3038 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
3039 pThis->enmState = KDRECVSTATE_PACKET_BODY;
3040 }
3041 else /* No body means no trailer byte it looks like. */
3042 rc = dbgcKdCtxPktProcess(pThis);
3043 }
3044 else
3045 rc = VERR_NET_PROTOCOL_ERROR;
3046 break;
3047 }
3048 case KDRECVSTATE_PACKET_BODY:
3049 {
3050 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
3051 pThis->bTrailer = 0;
3052 pThis->pbRecv = &pThis->bTrailer;
3053 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
3054 break;
3055 }
3056 case KDRECVSTATE_PACKET_TRAILER:
3057 {
3058 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
3059 rc = dbgcKdCtxPktProcess(pThis);
3060 else
3061 rc = VERR_NET_PROTOCOL_ERROR;
3062 break;
3063 }
3064 default:
3065 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
3066 }
3067
3068 return rc;
3069}
3070
3071
3072/**
3073 * Receive data and processes complete packets.
3074 *
3075 * @returns Status code.
3076 * @param pThis The KD context.
3077 */
3078static int dbgcKdCtxRecv(PKDCTX pThis)
3079{
3080 int rc = VINF_SUCCESS;
3081
3082 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
3083
3084 if (pThis->cbRecvLeft)
3085 {
3086 size_t cbRead = 0;
3087 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
3088 if (RT_SUCCESS(rc))
3089 {
3090 pThis->tsRecvLast = RTTimeMilliTS();
3091 pThis->cbRecvLeft -= cbRead;
3092 pThis->pbRecv += cbRead;
3093 if (!pThis->cbRecvLeft)
3094 rc = dbgcKdCtxRecvDataProcess(pThis);
3095 }
3096 }
3097
3098 LogFlowFunc(("returns rc=%Rrc\n", rc));
3099 return rc;
3100}
3101
3102
3103/**
3104 * Processes debugger events.
3105 *
3106 * @returns VBox status code.
3107 * @param pThis The KD context data.
3108 * @param pEvent Pointer to event data.
3109 */
3110static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
3111{
3112 /*
3113 * Process the event.
3114 */
3115 PDBGC pDbgc = &pThis->Dbgc;
3116 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
3117 pThis->Dbgc.iArg = 0;
3118 int rc = VINF_SUCCESS;
3119 VMCPUID idCpuOld = pDbgc->idCpu;
3120 pDbgc->idCpu = pEvent->idCpu;
3121 switch (pEvent->enmType)
3122 {
3123 /*
3124 * The first part is events we have initiated with commands.
3125 */
3126 case DBGFEVENT_HALT_DONE:
3127 {
3128 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3129 break;
3130 }
3131
3132 /*
3133 * The second part is events which can occur at any time.
3134 */
3135 case DBGFEVENT_FATAL_ERROR:
3136 {
3137 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
3138 dbgcGetEventCtx(pEvent->enmCtx));
3139 if (RT_SUCCESS(rc))
3140 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3141 break;
3142 }
3143
3144 case DBGFEVENT_BREAKPOINT:
3145 case DBGFEVENT_BREAKPOINT_IO:
3146 case DBGFEVENT_BREAKPOINT_MMIO:
3147 case DBGFEVENT_BREAKPOINT_HYPER:
3148 {
3149 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp);
3150 switch (rc)
3151 {
3152 case VERR_DBGC_BP_NOT_FOUND:
3153 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
3154 pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
3155 break;
3156
3157 case VINF_DBGC_BP_NO_COMMAND:
3158 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
3159 pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
3160 break;
3161
3162 case VINF_BUFFER_OVERFLOW:
3163 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
3164 pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
3165 break;
3166
3167 default:
3168 break;
3169 }
3170 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL))
3171 {
3172 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3173
3174 /* Set the resume flag to ignore the breakpoint when resuming execution. */
3175 if ( RT_SUCCESS(rc)
3176 && pEvent->enmType == DBGFEVENT_BREAKPOINT)
3177 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
3178 }
3179
3180 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3181 break;
3182 }
3183
3184 case DBGFEVENT_STEPPED:
3185 case DBGFEVENT_STEPPED_HYPER:
3186 {
3187 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3188 break;
3189 }
3190
3191 case DBGFEVENT_ASSERTION_HYPER:
3192 {
3193 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3194 "\ndbgf event: Hypervisor Assertion! (%s)\n"
3195 "%s"
3196 "%s"
3197 "\n",
3198 dbgcGetEventCtx(pEvent->enmCtx),
3199 pEvent->u.Assert.pszMsg1,
3200 pEvent->u.Assert.pszMsg2);
3201 if (RT_SUCCESS(rc))
3202 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3203 break;
3204 }
3205
3206 case DBGFEVENT_DEV_STOP:
3207 {
3208 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3209 "\n"
3210 "dbgf event: DBGFSTOP (%s)\n"
3211 "File: %s\n"
3212 "Line: %d\n"
3213 "Function: %s\n",
3214 dbgcGetEventCtx(pEvent->enmCtx),
3215 pEvent->u.Src.pszFile,
3216 pEvent->u.Src.uLine,
3217 pEvent->u.Src.pszFunction);
3218 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
3219 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3220 "Message: %s\n",
3221 pEvent->u.Src.pszMessage);
3222 if (RT_SUCCESS(rc))
3223 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3224 break;
3225 }
3226
3227
3228 case DBGFEVENT_INVALID_COMMAND:
3229 {
3230 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
3231 break;
3232 }
3233
3234 case DBGFEVENT_POWERING_OFF:
3235 {
3236 pThis->Dbgc.fReady = false;
3237 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, false);
3238 rc = VERR_GENERAL_FAILURE;
3239 break;
3240 }
3241
3242 default:
3243 {
3244 /*
3245 * Probably a generic event. Look it up to find its name.
3246 */
3247 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
3248 if (pEvtDesc)
3249 {
3250 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
3251 {
3252 Assert(pEvtDesc->pszDesc);
3253 Assert(pEvent->u.Generic.cArgs == 1);
3254 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
3255 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
3256 }
3257 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
3258 {
3259 Assert(pEvent->u.Generic.cArgs >= 5);
3260 char szDetails[512];
3261 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
3262 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
3263 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
3264 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
3265 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
3266 szDetails);
3267 }
3268 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
3269 || pEvent->u.Generic.cArgs > 1
3270 || ( pEvent->u.Generic.cArgs == 1
3271 && pEvent->u.Generic.auArgs[0] != 0))
3272 {
3273 if (pEvtDesc->pszDesc)
3274 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
3275 pEvtDesc->pszName, pEvtDesc->pszDesc);
3276 else
3277 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
3278 if (pEvent->u.Generic.cArgs <= 1)
3279 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
3280 else
3281 {
3282 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
3283 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
3284 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
3285 }
3286 }
3287 else
3288 {
3289 if (pEvtDesc->pszDesc)
3290 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
3291 pEvtDesc->pszName, pEvtDesc->pszDesc);
3292 else
3293 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
3294 }
3295 }
3296 else
3297 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
3298 break;
3299 }
3300 }
3301
3302 pDbgc->idCpu = idCpuOld;
3303 return rc;
3304}
3305
3306
3307/**
3308 * Handle a receive timeout.
3309 *
3310 * @returns VBox status code.
3311 * @param pThis Pointer to the KD context.
3312 */
3313static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
3314{
3315 int rc = VINF_SUCCESS;
3316
3317 LogFlowFunc(("pThis=%p\n", pThis));
3318
3319 /*
3320 * If a single breakin packet byte was received but the header is otherwise incomplete
3321 * the VM is halted and a state change will be sent in the event processing loop.
3322 */
3323 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
3324 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3325 {
3326 LogFlow(("DbgKd: Halting VM!\n"));
3327 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3328 }
3329 else /* Send a reset packet (@todo Figure out the semantics in this case exactly). */
3330 rc = dbgcKdCtxPktSendReset(pThis);
3331
3332 dbgcKdCtxPktRecvReset(pThis);
3333
3334 LogFlowFunc(("rc=%Rrc\n", rc));
3335 return rc;
3336}
3337
3338
3339/**
3340 * @copydoc DBGC::pfnOutput
3341 */
3342static DECLCALLBACK(int) dbgcKdOutput(void *pvUser, const char *pachChars, size_t cbChars)
3343{
3344 PKDCTX pThis = (PKDCTX)pvUser;
3345
3346 return dbgcKdCtxDebugIoStrSend(pThis, pThis->Dbgc.idCpu, pachChars, cbChars);
3347}
3348
3349
3350/**
3351 * Run the debugger console.
3352 *
3353 * @returns VBox status code.
3354 * @param pThis Pointer to the KD context.
3355 */
3356int dbgcKdRun(PKDCTX pThis)
3357{
3358 /*
3359 * We're ready for commands now.
3360 */
3361 pThis->Dbgc.fReady = true;
3362 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, true);
3363
3364 /*
3365 * Main Debugger Loop.
3366 *
3367 * This loop will either block on waiting for input or on waiting on
3368 * debug events. If we're forwarding the log we cannot wait for long
3369 * before we must flush the log.
3370 */
3371 int rc;
3372 for (;;)
3373 {
3374 rc = VERR_SEM_OUT_OF_TURN;
3375 if (pThis->Dbgc.pUVM)
3376 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
3377
3378 if (RT_SUCCESS(rc))
3379 {
3380 /*
3381 * Wait for a debug event.
3382 */
3383 DBGFEVENT Evt;
3384 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
3385 if (RT_SUCCESS(rc))
3386 {
3387 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
3388 if (RT_FAILURE(rc))
3389 break;
3390 }
3391 else if (rc != VERR_TIMEOUT)
3392 break;
3393
3394 /*
3395 * Check for input.
3396 */
3397 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 0))
3398 {
3399 rc = dbgcKdCtxRecv(pThis);
3400 if (RT_FAILURE(rc))
3401 break;
3402 }
3403 }
3404 else if (rc == VERR_SEM_OUT_OF_TURN)
3405 {
3406 /*
3407 * Wait for input.
3408 */
3409 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 1000))
3410 {
3411 rc = dbgcKdCtxRecv(pThis);
3412 if (RT_FAILURE(rc))
3413 break;
3414 }
3415 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
3416 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
3417 rc = dbgcKdCtxRecvTimeout(pThis);
3418 }
3419 else
3420 break;
3421 }
3422
3423 return rc;
3424}
3425
3426
3427/**
3428 * Creates a KD context instance with the given backend.
3429 *
3430 * @returns VBox status code.
3431 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
3432 * @param pBack The backend to use for I/O.
3433 * @param fFlags Flags controlling the behavior.
3434 */
3435static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PDBGCBACK pBack, unsigned fFlags)
3436{
3437 /*
3438 * Validate input.
3439 */
3440 AssertPtrReturn(pBack, VERR_INVALID_POINTER);
3441 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
3442
3443 /*
3444 * Allocate and initialize.
3445 */
3446 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
3447 if (!pThis)
3448 return VERR_NO_MEMORY;
3449
3450 dbgcInitCmdHlp(&pThis->Dbgc);
3451 /*
3452 * This is compied from the native debug console (will be used for monitor commands)
3453 * in DBGCConsole.cpp. Try to keep both functions in sync.
3454 */
3455 pThis->Dbgc.pBack = pBack;
3456 pThis->Dbgc.pfnOutput = dbgcKdOutput;
3457 pThis->Dbgc.pvOutputUser = pThis;
3458 pThis->Dbgc.pVM = NULL;
3459 pThis->Dbgc.pUVM = NULL;
3460 pThis->Dbgc.idCpu = 0;
3461 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
3462 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
3463 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
3464 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
3465 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
3466 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
3467 //pThis->Dbgc.fLog = false;
3468 pThis->Dbgc.fRegTerse = true;
3469 pThis->Dbgc.fStepTraceRegs = true;
3470 //pThis->Dbgc.cPagingHierarchyDumps = 0;
3471 //pThis->Dbgc.DisasmPos = {0};
3472 //pThis->Dbgc.SourcePos = {0};
3473 //pThis->Dbgc.DumpPos = {0};
3474 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
3475 //pThis->Dbgc.cbDumpElement = 0;
3476 //pThis->Dbgc.cVars = 0;
3477 //pThis->Dbgc.paVars = NULL;
3478 //pThis->Dbgc.pPlugInHead = NULL;
3479 //pThis->Dbgc.pFirstBp = NULL;
3480 //pThis->Dbgc.abSearch = {0};
3481 //pThis->Dbgc.cbSearch = 0;
3482 pThis->Dbgc.cbSearchUnit = 1;
3483 pThis->Dbgc.cMaxSearchHits = 1;
3484 //pThis->Dbgc.SearchAddr = {0};
3485 //pThis->Dbgc.cbSearchRange = 0;
3486
3487 //pThis->Dbgc.uInputZero = 0;
3488 //pThis->Dbgc.iRead = 0;
3489 //pThis->Dbgc.iWrite = 0;
3490 //pThis->Dbgc.cInputLines = 0;
3491 //pThis->Dbgc.fInputOverflow = false;
3492 pThis->Dbgc.fReady = true;
3493 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
3494 //pThis->Dbgc.iArg = 0;
3495 //pThis->Dbgc.rcOutput = 0;
3496 //pThis->Dbgc.rcCmd = 0;
3497
3498 //pThis->Dbgc.pszHistoryFile = NULL;
3499 //pThis->Dbgc.pszGlobalInitScript = NULL;
3500 //pThis->Dbgc.pszLocalInitScript = NULL;
3501
3502 dbgcEvalInit();
3503
3504 pThis->fBreakinRecv = false;
3505 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
3506 pThis->pIfWinNt = NULL;
3507 pThis->f32Bit = false;
3508 dbgcKdCtxPktRecvReset(pThis);
3509
3510 *ppKdCtx = pThis;
3511 return VINF_SUCCESS;
3512}
3513
3514
3515/**
3516 * Destroys the given KD context.
3517 *
3518 * @returns nothing.
3519 * @param pThis The KD context to destroy.
3520 */
3521static void dbgcKdCtxDestroy(PKDCTX pThis)
3522{
3523 AssertPtr(pThis);
3524
3525 pThis->pIfWinNt = NULL;
3526
3527 /* Detach from the VM. */
3528 if (pThis->Dbgc.pUVM)
3529 DBGFR3Detach(pThis->Dbgc.pUVM);
3530
3531 /* Free config strings. */
3532 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
3533 pThis->Dbgc.pszGlobalInitScript = NULL;
3534 RTStrFree(pThis->Dbgc.pszLocalInitScript);
3535 pThis->Dbgc.pszLocalInitScript = NULL;
3536 RTStrFree(pThis->Dbgc.pszHistoryFile);
3537 pThis->Dbgc.pszHistoryFile = NULL;
3538
3539 /* Finally, free the instance memory. */
3540 RTMemFree(pThis);
3541}
3542
3543
3544DECLHIDDEN(int) dbgcKdStubCreate(PUVM pUVM, PDBGCBACK pBack, unsigned fFlags)
3545{
3546 /*
3547 * Validate input.
3548 */
3549 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
3550 PVM pVM = NULL;
3551 if (pUVM)
3552 {
3553 pVM = VMR3GetVM(pUVM);
3554 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
3555 }
3556
3557 /*
3558 * Allocate and initialize instance data
3559 */
3560 PKDCTX pThis;
3561 int rc = dbgcKdCtxCreate(&pThis, pBack, fFlags);
3562 if (RT_FAILURE(rc))
3563 return rc;
3564 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
3565 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
3566
3567 /*
3568 * Attach to the specified VM.
3569 */
3570 if (RT_SUCCESS(rc) && pUVM)
3571 {
3572 rc = DBGFR3Attach(pUVM);
3573 if (RT_SUCCESS(rc))
3574 {
3575 pThis->Dbgc.pVM = pVM;
3576 pThis->Dbgc.pUVM = pUVM;
3577 pThis->Dbgc.idCpu = 0;
3578
3579 /* Try detecting a Windows NT guest. */
3580 char szName[64];
3581 rc = DBGFR3OSDetect(pUVM, szName, sizeof(szName));
3582 if (RT_SUCCESS(rc))
3583 {
3584 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pUVM, DBGFOSINTERFACE_WINNT);
3585 if (pThis->pIfWinNt)
3586 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3587 else
3588 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3589 }
3590 else
3591 {
3592 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3593 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3594 }
3595
3596 if (pThis->pIfWinNt)
3597 {
3598 rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM,
3599 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
3600 NULL /*puBuildNumber*/, &pThis->f32Bit);
3601 AssertRC(rc);
3602 }
3603 else
3604 {
3605 /*
3606 * Try to detect bitness based on the current CPU mode which might fool us (32bit process running
3607 * inside of 64bit host).
3608 */
3609 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
3610 if (enmMode == CPUMMODE_PROTECTED)
3611 pThis->f32Bit = true;
3612 else if (enmMode == CPUMMODE_LONG)
3613 pThis->f32Bit = false;
3614 else
3615 LogRel(("DBGC/Kd: Heh, trying to debug real mode code with WinDbg are we? Good luck with that...\n"));
3616 }
3617 }
3618 else
3619 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
3620 }
3621
3622 /*
3623 * Load plugins.
3624 */
3625 if (RT_SUCCESS(rc))
3626 {
3627 if (pVM)
3628 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
3629 dbgcEventInit(&pThis->Dbgc);
3630
3631 /*
3632 * Run the debugger main loop.
3633 */
3634 rc = dbgcKdRun(pThis);
3635 dbgcEventTerm(&pThis->Dbgc);
3636 }
3637
3638 /*
3639 * Cleanup console debugger session.
3640 */
3641 dbgcKdCtxDestroy(pThis);
3642 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
3643}
3644
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