VirtualBox

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

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

Debugger/DBGCRemoteKd: Implement switch current processor request

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