VirtualBox

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

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

Debugger/DBGCRemoteKd: Start supporting 32bit guests [build fix]

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