VirtualBox

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

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

Debugger/DBGCRemoteKd: Emulate DR<n> registers in order to transparently support hardware breakpoints from WinDbg (lightly tested) [build fix]

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