VirtualBox

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

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

Debugger/DBGCRemoteKd: Implement search memory request

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 158.8 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 86244 2020-09-23 15:35:16Z 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/** @todo */
1116/** Search memory for a pattern request. */
1117#define KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY UINT32_C(0x00003156)
1118/** @todo */
1119/** Clear all internal breakpoints request. */
1120#define KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT UINT32_C(0x0000315a)
1121/** Fill memory. */
1122#define KD_PACKET_MANIPULATE_REQ_FILL_MEMORY UINT32_C(0x0000315b)
1123/** Query memory properties. */
1124#define KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY UINT32_C(0x0000315c)
1125/** @todo */
1126/** Get context extended request. */
1127#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX UINT32_C(0x0000315f)
1128/** @todo */
1129/** Maximum available request (exclusive). */
1130#define KD_PACKET_MANIPULATE_REQ_MAX UINT32_C(0x00003161)
1131/** @} */
1132
1133/**
1134 * KD stub receive state.
1135 */
1136typedef enum KDRECVSTATE
1137{
1138 /** Invalid state. */
1139 KDRECVSTATE_INVALID = 0,
1140 /** Receiving the first byte of the packet header. */
1141 KDRECVSTATE_PACKET_HDR_FIRST_BYTE,
1142 /** Receiving the second byte of the packet header. */
1143 KDRECVSTATE_PACKET_HDR_SECOND_BYTE,
1144 /** Receiving the header. */
1145 KDRECVSTATE_PACKET_HDR,
1146 /** Receiving the packet body. */
1147 KDRECVSTATE_PACKET_BODY,
1148 /** Receiving the trailing byte. */
1149 KDRECVSTATE_PACKET_TRAILER,
1150 /** Blow up the enum to 32bits for easier alignment of members in structs. */
1151 KDRECVSTATE_32BIT_HACK = 0x7fffffff
1152} KDRECVSTATE;
1153
1154
1155/**
1156 * KD emulated hardware breakpoint.
1157 */
1158typedef struct KDCTXHWBP
1159{
1160 /** The DBGF breakpoint handle if active, UINT32_MAX if not active. */
1161 uint32_t iDbgfBp;
1162 /** The linear address of the breakpoint if active. */
1163 RTGCPTR GCPtrBp;
1164 /** Access type of the breakpoint, see X86_DR7_RW_*. */
1165 uint8_t fAcc;
1166 /** Length flags of the breakpoint. */
1167 uint8_t fLen;
1168 /** Flag whether it is a local breakpoint. */
1169 bool fLocal;
1170 /** Flag whether it is a global breakpoint. */
1171 bool fGlobal;
1172 /** Flag whether the breakpoint has triggered since the last time of the reset. */
1173 bool fTriggered;
1174} KDCTXHWBP;
1175/** Pointer to an emulated hardware breakpoint. */
1176typedef KDCTXHWBP *PKDCTXHWBP;
1177/** Pointer to a const emulated hardware breakpoint. */
1178typedef const KDCTXHWBP *PCKDCTXHWBP;
1179
1180
1181/**
1182 * KD context data.
1183 */
1184typedef struct KDCTX
1185{
1186 /** Internal debugger console data. */
1187 DBGC Dbgc;
1188 /** Number of bytes received left for the current state. */
1189 size_t cbRecvLeft;
1190 /** Pointer where to write the next received data. */
1191 uint8_t *pbRecv;
1192 /** The current state when receiving a new packet. */
1193 KDRECVSTATE enmState;
1194 /** The timeout waiting for new data. */
1195 RTMSINTERVAL msRecvTimeout;
1196 /** Timestamp when we last received data from the remote end. */
1197 uint64_t tsRecvLast;
1198 /** Packet header being received. */
1199 union
1200 {
1201 KDPACKETHDR Fields;
1202 uint8_t ab[16];
1203 } PktHdr;
1204 /** The next packet ID to send. */
1205 uint32_t idPktNext;
1206 /** Offset into the body receive buffer. */
1207 size_t offBodyRecv;
1208 /** Body data. */
1209 uint8_t abBody[_4K];
1210 /** The trailer byte storage. */
1211 uint8_t bTrailer;
1212 /** Flag whether a breakin packet was received since the last time it was reset. */
1213 bool fBreakinRecv;
1214 /** Flag whether we entered the native VBox hypervisor through a bugcheck request. */
1215 bool fInVBoxDbg;
1216
1217 /** Emulated hardware breakpoint handling. */
1218 KDCTXHWBP aHwBp[4];
1219 /** Flag whether a single step completed since last time this was cleared. */
1220 bool fSingleStepped;
1221
1222 /** Pointer to the OS digger WinNt interface if a matching guest was detected. */
1223 PDBGFOSIWINNT pIfWinNt;
1224 /** Flag whether the detected guest is 32bit (false if 64bit). */
1225 bool f32Bit;
1226} KDCTX;
1227/** Pointer to the KD context data. */
1228typedef KDCTX *PKDCTX;
1229/** Pointer to const KD context data. */
1230typedef const KDCTX *PCKDCTX;
1231/** Pointer to a KD context data pointer. */
1232typedef PKDCTX *PPKDCTX;
1233
1234
1235/** Creates a possibly sign extended guest context pointer which is required for 32bit targets. */
1236#define KD_PTR_CREATE(a_pThis, a_GCPtr) ((a_pThis)->f32Bit && ((a_GCPtr) & RT_BIT_32(31)) ? (a_GCPtr) | UINT64_C(0xffffffff00000000) : (a_GCPtr))
1237/** Returns the value of a possibly sign extended guest context pointer received for 32bit targets. */
1238#define KD_PTR_GET(a_pThis, a_GCPtr) ((a_pThis)->f32Bit ? (a_GCPtr) & ~UINT64_C(0xffffffff00000000) : (a_GCPtr))
1239
1240
1241/*********************************************************************************************************************************
1242* Internal Functions *
1243*********************************************************************************************************************************/
1244
1245static void dbgcKdCtxMsgSend(PKDCTX pThis, bool fWarning, const char *pszMsg);
1246
1247
1248#ifdef LOG_ENABLED
1249/**
1250 * Returns a human readable string of the given packet sub type.
1251 *
1252 * @returns Pointer to sub type string.
1253 * @param u16SubType The sub type to convert to a string.
1254 */
1255static const char *dbgcKdPktDumpSubTypeToStr(uint16_t u16SubType)
1256{
1257 switch (u16SubType)
1258 {
1259 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32: return "StateChange32";
1260 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE: return "Manipulate";
1261 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO: return "DebugIo";
1262 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE: return "Ack";
1263 case KD_PACKET_HDR_SUB_TYPE_RESEND: return "Resend";
1264 case KD_PACKET_HDR_SUB_TYPE_RESET: return "Reset";
1265 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64: return "StateChange64";
1266 case KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN: return "PollBreakin";
1267 case KD_PACKET_HDR_SUB_TYPE_TRACE_IO: return "TraceIo";
1268 case KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST: return "ControlRequest";
1269 case KD_PACKET_HDR_SUB_TYPE_FILE_IO: return "FileIo";
1270 default: break;
1271 }
1272
1273 return "<UNKNOWN>";
1274}
1275
1276
1277/**
1278 * Returns a human readable string of the given manipulate request ID.
1279 *
1280 * @returns nothing.
1281 * @param idReq Request ID (API number in KD speak).
1282 */
1283static const char *dbgcKdPktDumpManipulateReqToStr(uint32_t idReq)
1284{
1285 switch (idReq)
1286 {
1287 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM: return "ReadVirtMem";
1288 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM: return "WriteVirtMem";
1289 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT: return "GetContext";
1290 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT: return "SetContext";
1291 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT: return "WriteBkpt";
1292 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT: return "RestoreBkpt";
1293 case KD_PACKET_MANIPULATE_REQ_CONTINUE: return "Continue";
1294 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE: return "ReadCtrlSpace";
1295 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE: return "WriteCtrlSpace";
1296 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE: return "ReadIoSpace";
1297 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE: return "WriteIoSpace";
1298 case KD_PACKET_MANIPULATE_REQ_REBOOT: return "Reboot";
1299 case KD_PACKET_MANIPULATE_REQ_CONTINUE2: return "Continue2";
1300 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM: return "ReadPhysMem";
1301 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM: return "WritePhysMem";
1302 case KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS: return "QuerySpecCalls";
1303 case KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS: return "SetSpecCalls";
1304 case KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS: return "ClrSpecCalls";
1305 case KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT: return "SetIntBkpt";
1306 case KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT: return "GetIntBkpt";
1307 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX: return "ReadIoSpaceEx";
1308 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX: return "WriteIoSpaceEx";
1309 case KD_PACKET_MANIPULATE_REQ_GET_VERSION: return "GetVersion";
1310 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT: return "ClrAllIntBkpt";
1311 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX: return "GetContextEx";
1312 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY: return "QueryMemory";
1313 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK: return "CauseBugCheck";
1314 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY: return "SearchMemory";
1315 default: break;
1316 }
1317
1318 return "<UNKNOWN>";
1319}
1320
1321
1322/**
1323 * Dumps the content of a manipulate packet.
1324 *
1325 * @returns nothing.
1326 * @param pSgBuf S/G buffer containing the manipulate packet payload.
1327 */
1328static void dbgcKdPktDumpManipulate(PRTSGBUF pSgBuf)
1329{
1330 KDPACKETMANIPULATEHDR Hdr;
1331 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, &Hdr, sizeof(Hdr));
1332
1333 if (cbCopied == sizeof(Hdr))
1334 {
1335 const char *pszReq = dbgcKdPktDumpManipulateReqToStr(Hdr.idReq);
1336
1337 Log3((" MANIPULATE(%#x (%s), %#x, %u, %#x)\n",
1338 Hdr.idReq, pszReq, Hdr.u16CpuLvl, Hdr.idCpu, Hdr.u32NtStatus));
1339
1340 switch (Hdr.idReq)
1341 {
1342 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
1343 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
1344 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
1345 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
1346 {
1347 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1348 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferMem64, sizeof(XferMem64));
1349 if (cbCopied == sizeof(XferMem64))
1350 {
1351 Log3((" u64PtrTarget: %RX64\n"
1352 " cbXferReq: %RX32\n"
1353 " cbXfered: %RX32\n",
1354 XferMem64.u64PtrTarget, XferMem64.cbXferReq, XferMem64.cbXfered));
1355 }
1356 else
1357 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferMem64), cbCopied));
1358 break;
1359 }
1360 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
1361 {
1362 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
1363 cbCopied = RTSgBufCopyToBuf(pSgBuf, &RestoreBkpt64, sizeof(RestoreBkpt64));
1364 if (cbCopied == sizeof(RestoreBkpt64))
1365 Log3((" u32HndBkpt: %RX32\n", RestoreBkpt64.u32HndBkpt));
1366 else
1367 Log3((" Payload to small, expected %u, got %zu\n", sizeof(RestoreBkpt64), cbCopied));
1368 break;
1369 }
1370 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
1371 {
1372 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
1373 cbCopied = RTSgBufCopyToBuf(pSgBuf, &WriteBkpt64, sizeof(WriteBkpt64));
1374 if (cbCopied == sizeof(WriteBkpt64))
1375 Log3((" u64PtrBkpt: %RX64\n"
1376 " u32HndBkpt: %RX32\n",
1377 WriteBkpt64.u64PtrBkpt, WriteBkpt64.u32HndBkpt));
1378 else
1379 Log3((" Payload to small, expected %u, got %zu\n", sizeof(WriteBkpt64), cbCopied));
1380 break;
1381 }
1382 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
1383 {
1384 KDPACKETMANIPULATE_CONTINUE Continue;
1385 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1386 if (cbCopied == sizeof(Continue))
1387 Log3((" u32NtContSts: %RX32\n", Continue.u32NtContSts));
1388 else
1389 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1390 break;
1391 }
1392 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
1393 {
1394 KDPACKETMANIPULATE_CONTINUE2 Continue;
1395 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1396 if (cbCopied == sizeof(Continue))
1397 Log3((" u32NtContSts: %RX32\n"
1398 " fTrace: %RX32\n",
1399 Continue.u32NtContSts, Continue.fTrace));
1400 else
1401 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1402 break;
1403 }
1404 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
1405 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
1406 {
1407 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
1408 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferCtrlSpace64, sizeof(XferCtrlSpace64));
1409 if (cbCopied == sizeof(XferCtrlSpace64))
1410 {
1411 Log3((" u64IdXfer: %RX64\n"
1412 " cbXferReq: %RX32\n"
1413 " cbXfered: %RX32\n",
1414 XferCtrlSpace64.u64IdXfer, XferCtrlSpace64.cbXferReq, XferCtrlSpace64.cbXfered));
1415 }
1416 else
1417 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferCtrlSpace64), cbCopied));
1418 break;
1419 }
1420 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
1421 {
1422 KDPACKETMANIPULATE_CONTEXTEX GetContextEx;
1423 cbCopied = RTSgBufCopyToBuf(pSgBuf, &GetContextEx, sizeof(GetContextEx));
1424 if (cbCopied == sizeof(GetContextEx))
1425 {
1426 Log3((" offStart: %RX32\n"
1427 " cbXferReq: %RX32\n"
1428 " cbXfered: %RX32\n",
1429 GetContextEx.offStart, GetContextEx.cbXfer, GetContextEx.cbXfered));
1430 }
1431 else
1432 Log3((" Payload to small, expected %u, got %zu\n", sizeof(GetContextEx), cbCopied));
1433 break;
1434 }
1435 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
1436 {
1437 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
1438 cbCopied = RTSgBufCopyToBuf(pSgBuf, &QueryMemory, sizeof(QueryMemory));
1439 if (cbCopied == sizeof(QueryMemory))
1440 {
1441 Log3((" u64GCPtr: %RX64\n"
1442 " u32AddrSpace: %RX32\n"
1443 " u32Flags: %RX32\n",
1444 QueryMemory.u64GCPtr, QueryMemory.u32AddrSpace, QueryMemory.u32Flags));
1445 }
1446 else
1447 Log3((" Payload to small, expected %u, got %zu\n", sizeof(QueryMemory), cbCopied));
1448 break;
1449 }
1450 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
1451 {
1452 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
1453 cbCopied = RTSgBufCopyToBuf(pSgBuf, &SearchMemory, sizeof(SearchMemory));
1454 if (cbCopied == sizeof(SearchMemory))
1455 {
1456 Log3((" u64GCPtr: %RX64\n"
1457 " cbSearch: %RX64\n"
1458 " cbPattern: %RX32\n",
1459 SearchMemory.u64GCPtr, SearchMemory.cbSearch, SearchMemory.cbPattern));
1460 }
1461 else
1462 Log3((" Payload to small, expected %u, got %zu\n", sizeof(SearchMemory), cbCopied));
1463 break;
1464 }
1465 default:
1466 break;
1467 }
1468 }
1469 else
1470 Log3((" MANIPULATE(Header too small, expected %u, got %zu)\n", sizeof(Hdr), cbCopied));
1471}
1472
1473
1474/**
1475 * Dumps the received packet to the debug log.
1476 *
1477 * @returns VBox status code.
1478 * @param pPktHdr The packet header to dump.
1479 * @param fRx Flag whether the packet was received (false indicates an outgoing packet).
1480 */
1481static void dbgcKdPktDump(PCKDPACKETHDR pPktHdr, PCRTSGSEG paSegs, uint32_t cSegs, bool fRx)
1482{
1483 RTSGBUF SgBuf;
1484
1485 RTSgBufInit(&SgBuf, paSegs, cSegs);
1486
1487 Log3(("%s KDPKTHDR(%#x, %#x (%s), %u, %#x, %#x)\n",
1488 fRx ? "=>" : "<=",
1489 pPktHdr->u32Signature, pPktHdr->u16SubType, dbgcKdPktDumpSubTypeToStr(pPktHdr->u16SubType),
1490 pPktHdr->cbBody, pPktHdr->idPacket, pPktHdr->u32ChkSum));
1491 switch (pPktHdr->u16SubType)
1492 {
1493 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
1494 dbgcKdPktDumpManipulate(&SgBuf);
1495 break;
1496 default:
1497 break;
1498 }
1499}
1500#endif
1501
1502
1503/**
1504 * Resets the emulated hardware breakpoint state to a state similar after a reboot.
1505 *
1506 * @returns nothing.
1507 * @param pThis The KD context.
1508 */
1509static void dbgcKdCtxHwBpReset(PKDCTX pThis)
1510{
1511 pThis->fSingleStepped = false;
1512
1513 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1514 {
1515 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1516
1517 if (pBp->iDbgfBp != UINT32_MAX)
1518 {
1519 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->iDbgfBp);
1520 AssertRC(rc);
1521 }
1522
1523 pBp->iDbgfBp = UINT32_MAX;
1524 pBp->GCPtrBp = 0;
1525 pBp->fAcc = 0;
1526 pBp->fLen = 0;
1527 pBp->fLocal = false;
1528 pBp->fGlobal = false;
1529 pBp->fTriggered = false;
1530 }
1531}
1532
1533
1534/**
1535 * Updates the given breakpoint with the given properties.
1536 *
1537 * @returns VBox status code.
1538 * @param pThis The KD context.
1539 * @param pBp The breakpoint to update.
1540 * @param fAcc Access mode.
1541 * @param fLen Access length.
1542 * @param fGlobal Global breakpoint.
1543 * @param fLocal Local breakpoint.
1544 * @param GCPtrBp Linear address of the breakpoint.
1545 */
1546static int dbgcKdCtxHwBpUpdate(PKDCTX pThis, PKDCTXHWBP pBp, uint8_t fAcc, uint8_t fLen,
1547 bool fGlobal, bool fLocal, RTGCPTR GCPtrBp)
1548{
1549 int rc = VINF_SUCCESS;
1550
1551 /* Did anything actually change?. */
1552 if ( pBp->fAcc != fAcc
1553 || pBp->fLen != fLen
1554 || pBp->fGlobal != fGlobal
1555 || pBp->fLocal != fLocal
1556 || pBp->GCPtrBp != GCPtrBp)
1557 {
1558 /* Clear the old breakpoint. */
1559 if (pBp->iDbgfBp != UINT32_MAX)
1560 {
1561 rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->iDbgfBp);
1562 AssertRC(rc);
1563 pBp->iDbgfBp = UINT32_MAX;
1564 }
1565
1566 pBp->fAcc = fAcc;
1567 pBp->fLen = fLen;
1568 pBp->fGlobal = fGlobal;
1569 pBp->fLocal = fLocal;
1570 pBp->GCPtrBp = GCPtrBp;
1571 if (pBp->fGlobal || pBp->fLocal)
1572 {
1573 DBGFADDRESS AddrBp;
1574 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrBp, GCPtrBp);
1575
1576 uint8_t cb = 0;
1577 switch (pBp->fLen)
1578 {
1579 case X86_DR7_LEN_BYTE:
1580 cb = 1;
1581 break;
1582 case X86_DR7_LEN_WORD:
1583 cb = 2;
1584 break;
1585 case X86_DR7_LEN_DWORD:
1586 cb = 4;
1587 break;
1588 case X86_DR7_LEN_QWORD:
1589 cb = 8;
1590 break;
1591 default:
1592 AssertFailed();
1593 return VERR_NET_PROTOCOL_ERROR;
1594 }
1595
1596 rc = DBGFR3BpSetReg(pThis->Dbgc.pUVM, &AddrBp, 0 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/,
1597 pBp->fAcc, cb, &pBp->iDbgfBp);
1598 }
1599 }
1600
1601 return rc;
1602}
1603
1604
1605/**
1606 * Updates emulated hardware breakpoints based on the written DR7 value.
1607 *
1608 * @returns VBox status code.
1609 * @param pThis The KD context.
1610 * @param uDr7 The DR7 value which is written.
1611 */
1612static int dbgcKdCtxHwBpDr7Update(PKDCTX pThis, uint32_t uDr7)
1613{
1614 int rc = VINF_SUCCESS;
1615
1616 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1617 {
1618 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1619 uint8_t fAcc = X86_DR7_GET_RW(uDr7, i);
1620 uint8_t fLen = X86_DR7_GET_LEN(uDr7, i);
1621 bool fGlobal = (uDr7 & RT_BIT_32(1 + i * 2)) ? true : false;
1622 bool fLocal = (uDr7 & RT_BIT_32(i * 2)) ? true : false;
1623
1624 int rc2 = dbgcKdCtxHwBpUpdate(pThis, pBp, fAcc, fLen, fGlobal, fLocal, pThis->aHwBp[i].GCPtrBp);
1625 if ( RT_FAILURE(rc2)
1626 && RT_SUCCESS(rc))
1627 rc = rc2;
1628 }
1629
1630 return rc;
1631}
1632
1633
1634/**
1635 * Updates the linear guest pointer for the given hardware breakpoint.
1636 *
1637 * @returns VBox status code.
1638 * @param pThis The KD context.
1639 * @param pBp The breakpoint to update.
1640 * @param GCPtrBp The linear breakpoint address.
1641 */
1642DECLINLINE(int) dbgcKdCtxHwBpGCPtrUpdate(PKDCTX pThis, PKDCTXHWBP pBp, RTGCPTR GCPtrBp)
1643{
1644 return dbgcKdCtxHwBpUpdate(pThis, pBp, pBp->fAcc, pBp->fLen, pBp->fGlobal, pBp->fLocal, GCPtrBp);
1645}
1646
1647
1648/**
1649 * Calculates the DR7 value based on the emulated hardware breakpoint state and returns it.
1650 *
1651 * @returns The emulated DR7 value.
1652 * @param pThis The KD context.
1653 */
1654static uint32_t dbgcKdCtxHwBpDr7Get(PKDCTX pThis)
1655{
1656 uint32_t uDr7 = 0;
1657
1658 uDr7 |= X86_DR7_RW(0, pThis->aHwBp[0].fAcc);
1659 uDr7 |= X86_DR7_RW(1, pThis->aHwBp[1].fAcc);
1660 uDr7 |= X86_DR7_RW(2, pThis->aHwBp[2].fAcc);
1661 uDr7 |= X86_DR7_RW(3, pThis->aHwBp[3].fAcc);
1662
1663 uDr7 |= X86_DR7_LEN(0, pThis->aHwBp[0].fLen);
1664 uDr7 |= X86_DR7_LEN(1, pThis->aHwBp[1].fLen);
1665 uDr7 |= X86_DR7_LEN(2, pThis->aHwBp[2].fLen);
1666 uDr7 |= X86_DR7_LEN(3, pThis->aHwBp[3].fLen);
1667
1668 uDr7 |= pThis->aHwBp[0].fGlobal ? X86_DR7_G(0) : 0;
1669 uDr7 |= pThis->aHwBp[1].fGlobal ? X86_DR7_G(1) : 0;
1670 uDr7 |= pThis->aHwBp[2].fGlobal ? X86_DR7_G(2) : 0;
1671 uDr7 |= pThis->aHwBp[3].fGlobal ? X86_DR7_G(3) : 0;
1672
1673 uDr7 |= pThis->aHwBp[0].fLocal ? X86_DR7_L(0) : 0;
1674 uDr7 |= pThis->aHwBp[1].fLocal ? X86_DR7_L(1) : 0;
1675 uDr7 |= pThis->aHwBp[2].fLocal ? X86_DR7_L(2) : 0;
1676 uDr7 |= pThis->aHwBp[3].fLocal ? X86_DR7_L(3) : 0;
1677
1678 return uDr7;
1679}
1680
1681
1682/**
1683 * Updates emulated hardware breakpoints based on the written DR6 value.
1684 *
1685 * @returns nothing.
1686 * @param pThis The KD context.
1687 * @param uDr6 The DR7 value which is written.
1688 */
1689static void dbgcKdCtxHwBpDr6Update(PKDCTX pThis, uint32_t uDr6)
1690{
1691 pThis->aHwBp[0].fTriggered = (uDr6 & X86_DR6_B0) ? true : false;
1692 pThis->aHwBp[1].fTriggered = (uDr6 & X86_DR6_B1) ? true : false;
1693 pThis->aHwBp[2].fTriggered = (uDr6 & X86_DR6_B2) ? true : false;
1694 pThis->aHwBp[3].fTriggered = (uDr6 & X86_DR6_B3) ? true : false;
1695 pThis->fSingleStepped = (uDr6 & X86_DR6_BS) ? true : false;
1696}
1697
1698
1699/**
1700 * Calculates the DR6 value based on the emulated hardware breakpoint state and returns it.
1701 *
1702 * @returns The emulated DR6 value.
1703 * @param pThis The KD context.
1704 */
1705static uint32_t dbgcKdCtxHwBpDr6Get(PKDCTX pThis)
1706{
1707 uint32_t uDr6 = 0;
1708
1709 if (pThis->aHwBp[0].fTriggered)
1710 uDr6 |= X86_DR6_B0;
1711 if (pThis->aHwBp[1].fTriggered)
1712 uDr6 |= X86_DR6_B1;
1713 if (pThis->aHwBp[2].fTriggered)
1714 uDr6 |= X86_DR6_B2;
1715 if (pThis->aHwBp[3].fTriggered)
1716 uDr6 |= X86_DR6_B3;
1717 if (pThis->fSingleStepped)
1718 uDr6 |= X86_DR6_BS;
1719
1720 return uDr6;
1721}
1722
1723
1724/**
1725 * Wrapper for the I/O interface write callback.
1726 *
1727 * @returns Status code.
1728 * @param pThis The KD context.
1729 * @param pvPkt The packet data to send.
1730 * @param cbPkt Size of the packet in bytes.
1731 */
1732DECLINLINE(int) dbgcKdCtxWrite(PKDCTX pThis, const void *pvPkt, size_t cbPkt)
1733{
1734 return pThis->Dbgc.pBack->pfnWrite(pThis->Dbgc.pBack, pvPkt, cbPkt, NULL /*pcbWritten*/);
1735}
1736
1737
1738/**
1739 * Fills in the given 64bit NT context structure with the requested values.
1740 *
1741 * @returns VBox status code.
1742 * @param pThis The KD context.
1743 * @param idCpu The CPU to query the context for.
1744 * @param pNtCtx The NT context structure to fill in.
1745 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1746 */
1747static int dbgcKdCtxQueryNtCtx64(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1748{
1749 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1750
1751 pNtCtx->fContext = NTCONTEXT_F_AMD64;
1752 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pNtCtx->u32RegMxCsr);
1753
1754 if ( RT_SUCCESS(rc)
1755 && fCtxFlags & NTCONTEXT_F_CONTROL)
1756 {
1757 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u16SegCs);
1758 if (RT_SUCCESS(rc))
1759 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u16SegSs);
1760 if (RT_SUCCESS(rc))
1761 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RIP, &pNtCtx->u64RegRip);
1762 if (RT_SUCCESS(rc))
1763 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSP, &pNtCtx->u64RegRsp);
1764 if (RT_SUCCESS(rc))
1765 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBP, &pNtCtx->u64RegRbp);
1766 if (RT_SUCCESS(rc))
1767 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1768 if (RT_SUCCESS(rc))
1769 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1770 }
1771
1772 if ( RT_SUCCESS(rc)
1773 && fCtxFlags & NTCONTEXT_F_INTEGER)
1774 {
1775 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RAX, &pNtCtx->u64RegRax);
1776 if (RT_SUCCESS(rc))
1777 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RCX, &pNtCtx->u64RegRcx);
1778 if (RT_SUCCESS(rc))
1779 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDX, &pNtCtx->u64RegRdx);
1780 if (RT_SUCCESS(rc))
1781 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBX, &pNtCtx->u64RegRbx);
1782 if (RT_SUCCESS(rc))
1783 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSI, &pNtCtx->u64RegRsi);
1784 if (RT_SUCCESS(rc))
1785 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDI, &pNtCtx->u64RegRdi);
1786 if (RT_SUCCESS(rc))
1787 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R8, &pNtCtx->u64RegR8);
1788 if (RT_SUCCESS(rc))
1789 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R9, &pNtCtx->u64RegR9);
1790 if (RT_SUCCESS(rc))
1791 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R10, &pNtCtx->u64RegR10);
1792 if (RT_SUCCESS(rc))
1793 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R11, &pNtCtx->u64RegR11);
1794 if (RT_SUCCESS(rc))
1795 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R12, &pNtCtx->u64RegR12);
1796 if (RT_SUCCESS(rc))
1797 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R13, &pNtCtx->u64RegR13);
1798 if (RT_SUCCESS(rc))
1799 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R14, &pNtCtx->u64RegR14);
1800 if (RT_SUCCESS(rc))
1801 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R15, &pNtCtx->u64RegR15);
1802 if (RT_SUCCESS(rc))
1803 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1804 }
1805
1806 if ( RT_SUCCESS(rc)
1807 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1808 {
1809 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u16SegDs);
1810 if (RT_SUCCESS(rc))
1811 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u16SegEs);
1812 if (RT_SUCCESS(rc))
1813 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u16SegFs);
1814 if (RT_SUCCESS(rc))
1815 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u16SegGs);
1816 if (RT_SUCCESS(rc))
1817 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1818 }
1819
1820 if ( RT_SUCCESS(rc)
1821 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1822 {
1823 /** @todo. */
1824 }
1825
1826 if ( RT_SUCCESS(rc)
1827 && fCtxFlags & NTCONTEXT_F_DEBUG)
1828 {
1829 /** @todo */
1830 }
1831
1832 return rc;
1833}
1834
1835
1836/**
1837 * Fills in the given 32bit NT context structure with the requested values.
1838 *
1839 * @returns VBox status code.
1840 * @param pThis The KD context.
1841 * @param idCpu The CPU to query the context for.
1842 * @param pNtCtx The NT context structure to fill in.
1843 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1844 */
1845static int dbgcKdCtxQueryNtCtx32(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT32 pNtCtx, uint32_t fCtxFlags)
1846{
1847 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1848
1849 pNtCtx->fContext = NTCONTEXT_F_X86;
1850
1851 int rc = VINF_SUCCESS;
1852 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1853 {
1854 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u32SegCs);
1855 if (RT_SUCCESS(rc))
1856 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u32SegSs);
1857 if (RT_SUCCESS(rc))
1858 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EIP, &pNtCtx->u32RegEip);
1859 if (RT_SUCCESS(rc))
1860 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESP, &pNtCtx->u32RegEsp);
1861 if (RT_SUCCESS(rc))
1862 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBP, &pNtCtx->u32RegEbp);
1863 if (RT_SUCCESS(rc))
1864 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1865 if (RT_SUCCESS(rc))
1866 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1867 }
1868
1869 if ( RT_SUCCESS(rc)
1870 && fCtxFlags & NTCONTEXT_F_INTEGER)
1871 {
1872 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EAX, &pNtCtx->u32RegEax);
1873 if (RT_SUCCESS(rc))
1874 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ECX, &pNtCtx->u32RegEcx);
1875 if (RT_SUCCESS(rc))
1876 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDX, &pNtCtx->u32RegEdx);
1877 if (RT_SUCCESS(rc))
1878 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBX, &pNtCtx->u32RegEbx);
1879 if (RT_SUCCESS(rc))
1880 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESI, &pNtCtx->u32RegEsi);
1881 if (RT_SUCCESS(rc))
1882 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDI, &pNtCtx->u32RegEdi);
1883 if (RT_SUCCESS(rc))
1884 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1885 }
1886
1887 if ( RT_SUCCESS(rc)
1888 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1889 {
1890 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u32SegDs);
1891 if (RT_SUCCESS(rc))
1892 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u32SegEs);
1893 if (RT_SUCCESS(rc))
1894 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u32SegFs);
1895 if (RT_SUCCESS(rc))
1896 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u32SegGs);
1897 if (RT_SUCCESS(rc))
1898 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1899 }
1900
1901 if ( RT_SUCCESS(rc)
1902 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1903 {
1904 /** @todo. */
1905 }
1906
1907 if ( RT_SUCCESS(rc)
1908 && fCtxFlags & NTCONTEXT_F_DEBUG)
1909 {
1910 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pNtCtx->u32RegDr0);
1911 if (RT_SUCCESS(rc))
1912 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pNtCtx->u32RegDr1);
1913 if (RT_SUCCESS(rc))
1914 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pNtCtx->u32RegDr3);
1915 if (RT_SUCCESS(rc))
1916 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pNtCtx->u32RegDr6);
1917 if (RT_SUCCESS(rc))
1918 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pNtCtx->u32RegDr7);
1919 if (RT_SUCCESS(rc))
1920 pNtCtx->fContext |= NTCONTEXT_F_DEBUG;
1921 }
1922
1923 return rc;
1924}
1925
1926
1927#define KD_REG_INIT(a_pszName, a_enmType, a_ValMember, a_Val) \
1928 do \
1929 { \
1930 aRegsSet[idxReg].pszName = a_pszName; \
1931 aRegsSet[idxReg].enmType = a_enmType; \
1932 aRegsSet[idxReg].Val.a_ValMember = a_Val; \
1933 idxReg++; \
1934 } while (0)
1935#define KD_REG_INIT_DTR(a_pszName, a_Base, a_Limit) \
1936 do \
1937 { \
1938 aRegsSet[idxReg].pszName = a_pszName; \
1939 aRegsSet[idxReg].enmType = DBGFREGVALTYPE_DTR; \
1940 aRegsSet[idxReg].Val.dtr.u64Base = a_Base; \
1941 aRegsSet[idxReg].Val.dtr.u32Limit = a_Limit; \
1942 idxReg++; \
1943 } while (0)
1944#define KD_REG_INIT_U16(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U16, u16, a_Val)
1945#define KD_REG_INIT_U32(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U32, u32, a_Val)
1946#define KD_REG_INIT_U64(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U64, u64, a_Val)
1947
1948
1949/**
1950 * Writes the indicated values from the given context structure to the guests register set.
1951 *
1952 * @returns VBox status code.
1953 * @param pThis The KD context.
1954 * @param idCpu The CPU to query the context for.
1955 * @param pNtCtx The NT context structure to set.
1956 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to set.
1957 */
1958static int dbgcKdCtxSetNtCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1959{
1960 uint32_t idxReg = 0;
1961 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1962
1963 KD_REG_INIT_U32("mxcsr", pNtCtx->u32RegMxCsr);
1964
1965 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1966 {
1967#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1968 KD_REG_INIT_U16("cs", pNtCtx->u16SegCs);
1969 KD_REG_INIT_U16("ss", pNtCtx->u16SegSs);
1970#endif
1971 KD_REG_INIT_U64("rip", pNtCtx->u64RegRip);
1972 KD_REG_INIT_U64("rsp", pNtCtx->u64RegRsp);
1973 KD_REG_INIT_U64("rbp", pNtCtx->u64RegRbp);
1974 KD_REG_INIT_U32("rflags", pNtCtx->u32RegEflags);
1975 }
1976
1977 if (fCtxFlags & NTCONTEXT_F_INTEGER)
1978 {
1979 KD_REG_INIT_U64("rax", pNtCtx->u64RegRax);
1980 KD_REG_INIT_U64("rcx", pNtCtx->u64RegRcx);
1981 KD_REG_INIT_U64("rdx", pNtCtx->u64RegRdx);
1982 KD_REG_INIT_U64("rbx", pNtCtx->u64RegRbx);
1983 KD_REG_INIT_U64("rsi", pNtCtx->u64RegRsi);
1984 KD_REG_INIT_U64("rdi", pNtCtx->u64RegRdi);
1985 KD_REG_INIT_U64("r8", pNtCtx->u64RegR8);
1986 KD_REG_INIT_U64("r9", pNtCtx->u64RegR9);
1987 KD_REG_INIT_U64("r10", pNtCtx->u64RegR10);
1988 KD_REG_INIT_U64("r11", pNtCtx->u64RegR11);
1989 KD_REG_INIT_U64("r12", pNtCtx->u64RegR12);
1990 KD_REG_INIT_U64("r13", pNtCtx->u64RegR13);
1991 KD_REG_INIT_U64("r14", pNtCtx->u64RegR14);
1992 KD_REG_INIT_U64("r15", pNtCtx->u64RegR15);
1993 }
1994
1995 if (fCtxFlags & NTCONTEXT_F_SEGMENTS)
1996 {
1997#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1998 KD_REG_INIT_U16("ds", pNtCtx->u16SegDs);
1999 KD_REG_INIT_U16("es", pNtCtx->u16SegEs);
2000 KD_REG_INIT_U16("fs", pNtCtx->u16SegFs);
2001 KD_REG_INIT_U16("gs", pNtCtx->u16SegGs);
2002#endif
2003 }
2004
2005 if (fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
2006 {
2007 /** @todo. */
2008 }
2009
2010 if (fCtxFlags & NTCONTEXT_F_DEBUG)
2011 dbgcKdCtxMsgSend(pThis, true /*fWarning*/, "Setting local DR registers does not work!");
2012
2013 return DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2014}
2015
2016
2017/**
2018 * Fills in the given 64bit NT kernel context structure with the requested values.
2019 *
2020 * @returns VBox status code.
2021 * @param pThis The KD context.
2022 * @param idCpu The CPU to query the context for.
2023 * @param pKNtCtx The NT context structure to fill in.
2024 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
2025 */
2026static int dbgcKdCtxQueryNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT64 pKNtCtx, uint32_t fCtxFlags)
2027{
2028 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2029
2030 int rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u64RegCr0);
2031 if (RT_SUCCESS(rc))
2032 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u64RegCr2);
2033 if (RT_SUCCESS(rc))
2034 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u64RegCr3);
2035 if (RT_SUCCESS(rc))
2036 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u64RegCr4);
2037 if (RT_SUCCESS(rc))
2038 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR8, &pKNtCtx->u64RegCr8);
2039 if (RT_SUCCESS(rc))
2040 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2041 if (RT_SUCCESS(rc))
2042 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u64PtrBase);
2043 if (RT_SUCCESS(rc))
2044 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2045 if (RT_SUCCESS(rc))
2046 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u64PtrBase);
2047 if (RT_SUCCESS(rc))
2048 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2049 if (RT_SUCCESS(rc))
2050 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2051 if (RT_SUCCESS(rc))
2052 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pKNtCtx->u32RegMxCsr);
2053
2054 if (RT_SUCCESS(rc))
2055 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_GS_BASE, &pKNtCtx->u64MsrGsBase);
2056 if (RT_SUCCESS(rc))
2057 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_KERNEL_GS_BASE, &pKNtCtx->u64MsrKernelGsBase);
2058 if (RT_SUCCESS(rc))
2059 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K6_STAR, &pKNtCtx->u64MsrStar);
2060 if (RT_SUCCESS(rc))
2061 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_LSTAR, &pKNtCtx->u64MsrLstar);
2062 if (RT_SUCCESS(rc))
2063 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_CSTAR, &pKNtCtx->u64MsrCstar);
2064 if (RT_SUCCESS(rc))
2065 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_SF_MASK, &pKNtCtx->u64MsrSfMask);
2066 /** @todo XCR0 */
2067
2068 /* Get the emulated DR register state. */
2069 pKNtCtx->u64RegDr0 = pThis->aHwBp[0].GCPtrBp;
2070 pKNtCtx->u64RegDr1 = pThis->aHwBp[1].GCPtrBp;
2071 pKNtCtx->u64RegDr2 = pThis->aHwBp[2].GCPtrBp;
2072 pKNtCtx->u64RegDr3 = pThis->aHwBp[3].GCPtrBp;
2073 pKNtCtx->u64RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2074 pKNtCtx->u64RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2075
2076 if (RT_SUCCESS(rc))
2077 rc = dbgcKdCtxQueryNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, fCtxFlags);
2078
2079 return rc;
2080}
2081
2082
2083/**
2084 * Fills in the given 32bit NT kernel context structure with the requested values.
2085 *
2086 * @returns VBox status code.
2087 * @param pThis The KD context.
2088 * @param idCpu The CPU to query the context for.
2089 * @param pKNtCtx The NT context structure to fill in.
2090 */
2091static int dbgcKdCtxQueryNtKCtx32(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT32 pKNtCtx)
2092{
2093 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2094
2095 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u32RegCr0);
2096 if (RT_SUCCESS(rc))
2097 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u32RegCr2);
2098 if (RT_SUCCESS(rc))
2099 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u32RegCr3);
2100 if (RT_SUCCESS(rc))
2101 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u32RegCr4);
2102
2103 if (RT_SUCCESS(rc))
2104 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2105 if (RT_SUCCESS(rc))
2106 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u32PtrBase);
2107 if (RT_SUCCESS(rc))
2108 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2109 if (RT_SUCCESS(rc))
2110 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u32PtrBase);
2111 if (RT_SUCCESS(rc))
2112 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2113 if (RT_SUCCESS(rc))
2114 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2115
2116 /* Get the emulated DR register state. */
2117 pKNtCtx->u32RegDr0 = (uint32_t)pThis->aHwBp[0].GCPtrBp;
2118 pKNtCtx->u32RegDr1 = (uint32_t)pThis->aHwBp[1].GCPtrBp;
2119 pKNtCtx->u32RegDr2 = (uint32_t)pThis->aHwBp[2].GCPtrBp;
2120 pKNtCtx->u32RegDr3 = (uint32_t)pThis->aHwBp[3].GCPtrBp;
2121 pKNtCtx->u32RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2122 pKNtCtx->u32RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2123
2124 return rc;
2125}
2126
2127
2128/**
2129 * Fills in the given 64bit NT kernel context structure with the requested values.
2130 *
2131 * @returns VBox status code.
2132 * @param pThis The KD context.
2133 * @param idCpu The CPU to query the context for.
2134 * @param pKNtCtx The NT context structure to fill in.
2135 * @param cbSet How many bytes of the context are valid.
2136 */
2137static int dbgcKdCtxSetNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTKCONTEXT64 pKNtCtx, size_t cbSet)
2138{
2139 AssertReturn(cbSet >= RT_UOFFSETOF(NTKCONTEXT64, Ctx), VERR_INVALID_PARAMETER);
2140
2141 uint32_t idxReg = 0;
2142 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
2143
2144 KD_REG_INIT_U64("cr0", pKNtCtx->u64RegCr0);
2145 KD_REG_INIT_U64("cr2", pKNtCtx->u64RegCr2);
2146 KD_REG_INIT_U64("cr3", pKNtCtx->u64RegCr3);
2147 KD_REG_INIT_U64("cr4", pKNtCtx->u64RegCr4);
2148 KD_REG_INIT_U64("cr8", pKNtCtx->u64RegCr8);
2149
2150 KD_REG_INIT_DTR("gdtr", pKNtCtx->Gdtr.u64PtrBase, pKNtCtx->Gdtr.u16Limit);
2151 KD_REG_INIT_DTR("idtr", pKNtCtx->Idtr.u64PtrBase, pKNtCtx->Idtr.u16Limit);
2152
2153#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2154 KD_REG_INIT_U16("tr", pKNtCtx->u16RegTr);
2155 KD_REG_INIT_U16("ldtr", pKNtCtx->u16RegLdtr);
2156#endif
2157 KD_REG_INIT_U32("mxcsr", pKNtCtx->u32RegMxCsr);
2158
2159 KD_REG_INIT_U64("msr_gs_base", pKNtCtx->u64MsrGsBase);
2160 KD_REG_INIT_U64("krnl_gs_base", pKNtCtx->u64MsrKernelGsBase);
2161 KD_REG_INIT_U64("star", pKNtCtx->u64MsrStar);
2162 KD_REG_INIT_U64("lstar", pKNtCtx->u64MsrLstar);
2163 KD_REG_INIT_U64("cstar", pKNtCtx->u64MsrCstar);
2164 KD_REG_INIT_U64("sf_mask", pKNtCtx->u64MsrSfMask);
2165
2166 int rc = DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2167 if ( RT_SUCCESS(rc)
2168 && cbSet > RT_UOFFSETOF(NTKCONTEXT64, Ctx)) /** @todo Probably wrong. */
2169 rc = dbgcKdCtxSetNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, pKNtCtx->Ctx.fContext);
2170
2171 if (RT_SUCCESS(rc))
2172 {
2173 /* Update emulated hardware breakpoint state. */
2174 dbgcKdCtxHwBpDr6Update(pThis, (uint32_t)pKNtCtx->u64RegDr6);
2175 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pKNtCtx->u64RegDr7);
2176 if (RT_SUCCESS(rc))
2177 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[0], pKNtCtx->u64RegDr0);
2178 if (RT_SUCCESS(rc))
2179 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[1], pKNtCtx->u64RegDr1);
2180 if (RT_SUCCESS(rc))
2181 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[2], pKNtCtx->u64RegDr2);
2182 if (RT_SUCCESS(rc))
2183 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[3], pKNtCtx->u64RegDr3);
2184 }
2185
2186 return rc;
2187}
2188
2189#undef KD_REG_INIT_64
2190#undef KD_REG_INIT_32
2191#undef KD_REG_INIT_16
2192#undef KD_REG_INIT_DTR
2193#undef KD_REG_INIT
2194
2195
2196/**
2197 * Validates the given KD packet header.
2198 *
2199 * @returns Flag whether the packet header is valid, false if invalid.
2200 * @param pPktHdr The packet header to validate.
2201 */
2202static bool dbgcKdPktHdrValidate(PCKDPACKETHDR pPktHdr)
2203{
2204 if ( pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_DATA
2205 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_CONTROL
2206 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_BREAKIN)
2207 return false;
2208
2209 if (pPktHdr->u16SubType >= KD_PACKET_HDR_SUB_TYPE_MAX)
2210 return false;
2211
2212 uint32_t idPacket = pPktHdr->idPacket & UINT32_C(0xfffffffe);
2213 if ( idPacket != KD_PACKET_HDR_ID_INITIAL
2214 && idPacket != KD_PACKET_HDR_ID_RESET
2215 && idPacket != 0 /* Happens on the very first packet */)
2216 return false;
2217
2218 return true;
2219}
2220
2221
2222/**
2223 * Generates a checksum from the given buffer.
2224 *
2225 * @returns Generated checksum.
2226 * @param pv The data to generate a checksum from.
2227 * @param cb Number of bytes to checksum.
2228 */
2229static uint32_t dbgcKdPktChkSumGen(const void *pv, size_t cb)
2230{
2231 const uint8_t *pb = (const uint8_t *)pv;
2232 uint32_t u32ChkSum = 0;
2233
2234 while (cb--)
2235 u32ChkSum += *pb++;
2236
2237 return u32ChkSum;
2238}
2239
2240
2241/**
2242 * Generates a checksum from the given segments.
2243 *
2244 * @returns Generated checksum.
2245 * @param paSegs Pointer to the array of segments containing the data.
2246 * @param cSegs Number of segments.
2247 * @param pcbChkSum Where to store the number of bytes checksummed, optional.
2248 */
2249static uint32_t dbgcKdPktChkSumGenSg(PCRTSGSEG paSegs, uint32_t cSegs, size_t *pcbChkSum)
2250{
2251 size_t cbChkSum = 0;
2252 uint32_t u32ChkSum = 0;
2253
2254 for (uint32_t i = 0; i < cSegs; i++)
2255 {
2256 u32ChkSum += dbgcKdPktChkSumGen(paSegs[i].pvSeg, paSegs[i].cbSeg);
2257 cbChkSum += paSegs[i].cbSeg;
2258 }
2259
2260 if (pcbChkSum)
2261 *pcbChkSum = cbChkSum;
2262
2263 return u32ChkSum;
2264}
2265
2266
2267/**
2268 * Waits for an acknowledgment.
2269 *
2270 * @returns VBox status code.
2271 * @param pThis The KD context.
2272 * @param msWait Maximum number of milliseconds to wait for an acknowledge.
2273 * @param pfResend Where to store the resend requested flag on success.
2274 */
2275static int dbgcKdCtxPktWaitForAck(PKDCTX pThis, RTMSINTERVAL msWait, bool *pfResend)
2276{
2277 KDPACKETHDR PktAck;
2278 uint8_t *pbCur = (uint8_t *)&PktAck;
2279 size_t cbLeft = sizeof(PktAck);
2280 uint64_t tsStartMs = RTTimeMilliTS();
2281 int rc = VINF_SUCCESS;
2282
2283 LogFlowFunc(("pThis=%p msWait=%u pfResend=%p\n", pThis, msWait, pfResend));
2284
2285 RT_ZERO(PktAck);
2286
2287 /* There might be breakin packets in the queue, read until we get something else. */
2288 while ( msWait
2289 && RT_SUCCESS(rc))
2290 {
2291 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
2292 {
2293 size_t cbRead = 0;
2294 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, 1, &cbRead);
2295 if ( RT_SUCCESS(rc)
2296 && cbRead == 1)
2297 {
2298 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2299 msWait -= RT_MIN(msWait, tsSpanMs);
2300 tsStartMs = RTTimeMilliTS();
2301
2302 if (*pbCur == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2303 pThis->fBreakinRecv = true;
2304 else
2305 {
2306 pbCur++;
2307 cbLeft--;
2308 break;
2309 }
2310 }
2311 }
2312 else
2313 rc = VERR_TIMEOUT;
2314 }
2315
2316 if ( RT_SUCCESS(rc)
2317 && !msWait)
2318 rc = VERR_TIMEOUT;
2319
2320 if (RT_SUCCESS(rc))
2321 {
2322 while ( msWait
2323 && RT_SUCCESS(rc)
2324 && cbLeft)
2325 {
2326 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
2327 {
2328 size_t cbRead = 0;
2329 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, cbLeft, &cbRead);
2330 if (RT_SUCCESS(rc))
2331 {
2332 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2333 msWait -= RT_MIN(msWait, tsSpanMs);
2334 tsStartMs = RTTimeMilliTS();
2335
2336 cbLeft -= cbRead;
2337 pbCur += cbRead;
2338 }
2339 }
2340 else
2341 rc = VERR_TIMEOUT;
2342 }
2343
2344 if (RT_SUCCESS(rc))
2345 {
2346 if (PktAck.u32Signature == KD_PACKET_HDR_SIGNATURE_CONTROL)
2347 {
2348 if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE)
2349 rc = VINF_SUCCESS;
2350 else if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_RESEND)
2351 {
2352 *pfResend = true;
2353 rc = VINF_SUCCESS;
2354 }
2355 else
2356 rc = VERR_NET_PROTOCOL_ERROR;
2357 }
2358 else
2359 rc = VERR_NET_PROTOCOL_ERROR;
2360 }
2361 }
2362
2363 LogFlowFunc(("returns rc=%Rrc *pfResend=%RTbool\n", rc, *pfResend));
2364 return rc;
2365}
2366
2367
2368/**
2369 * Sends the given packet header and optional segmented body (the trailing byte is sent automatically).
2370 *
2371 * @returns VBox status code.
2372 * @param pThis The KD context.
2373 * @param u32Signature The signature to send.
2374 * @param u16SubType The sub type to send.
2375 * @param paSegs Pointer to the array of segments to send in the body, optional.
2376 * @param cSegs Number of segments.
2377 * @param fAck Flag whether to wait for an acknowledge.
2378 */
2379static int dbgcKdCtxPktSendSg(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2380 PCRTSGSEG paSegs, uint32_t cSegs, bool fAck)
2381{
2382 int rc = VINF_SUCCESS;
2383 uint32_t cRetriesLeft = 3;
2384 uint8_t bTrailer = KD_PACKET_TRAILING_BYTE;
2385 KDPACKETHDR Hdr;
2386
2387 size_t cbChkSum = 0;
2388 uint32_t u32ChkSum = dbgcKdPktChkSumGenSg(paSegs, cSegs, &cbChkSum);
2389
2390 Hdr.u32Signature = u32Signature;
2391 Hdr.u16SubType = u16SubType;
2392 Hdr.cbBody = (uint16_t)cbChkSum;
2393 Hdr.idPacket = pThis->idPktNext;
2394 Hdr.u32ChkSum = u32ChkSum;
2395
2396#ifdef LOG_ENABLED
2397 dbgcKdPktDump(&Hdr, paSegs, cSegs, false /*fRx*/);
2398#endif
2399
2400 while (cRetriesLeft--)
2401 {
2402 bool fResend = false;
2403
2404 rc = dbgcKdCtxWrite(pThis, &Hdr, sizeof(Hdr));
2405 if ( RT_SUCCESS(rc)
2406 && paSegs
2407 && cSegs)
2408 {
2409 for (uint32_t i = 0; i < cSegs && RT_SUCCESS(rc); i++)
2410 rc = dbgcKdCtxWrite(pThis, paSegs[i].pvSeg, paSegs[i].cbSeg);
2411
2412 if (RT_SUCCESS(rc))
2413 rc = dbgcKdCtxWrite(pThis, &bTrailer, sizeof(bTrailer));
2414 }
2415
2416 if (RT_SUCCESS(rc))
2417 {
2418 if (fAck)
2419 rc = dbgcKdCtxPktWaitForAck(pThis, 10 * 1000, &fResend);
2420
2421 if ( RT_SUCCESS(rc)
2422 && !fResend)
2423 break;
2424 }
2425 }
2426
2427 return rc;
2428}
2429
2430
2431/**
2432 * Sends the given packet header and optional body (the trailing byte is sent automatically).
2433 *
2434 * @returns VBox status code.
2435 * @param pThis The KD context.
2436 * @param u32Signature The signature to send.
2437 * @param u16SubType The sub type to send.
2438 * @param pvBody The body to send, optional.
2439 * @param cbBody Body size in bytes.
2440 * @param fAck Flag whether to wait for an acknowledge.
2441 */
2442DECLINLINE(int) dbgcKdCtxPktSend(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2443 const void *pvBody, size_t cbBody,
2444 bool fAck)
2445{
2446 RTSGSEG Seg;
2447
2448 Seg.pvSeg = (void *)pvBody;
2449 Seg.cbSeg = cbBody;
2450 return dbgcKdCtxPktSendSg(pThis, u32Signature, u16SubType, cbBody ? &Seg : NULL, cbBody ? 1 : 0, fAck);
2451}
2452
2453
2454/**
2455 * Sends a resend packet answer.
2456 *
2457 * @returns VBox status code.
2458 * @param pThis The KD context.
2459 */
2460DECLINLINE(int) dbgcKdCtxPktSendResend(PKDCTX pThis)
2461{
2462 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESEND,
2463 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2464}
2465
2466
2467/**
2468 * Sends a resend packet answer.
2469 *
2470 * @returns VBox status code.
2471 * @param pThis The KD context.
2472 */
2473DECLINLINE(int) dbgcKdCtxPktSendReset(PKDCTX pThis)
2474{
2475 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2476 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESET,
2477 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2478}
2479
2480
2481/**
2482 * Sends an acknowledge packet answer.
2483 *
2484 * @returns VBox status code.
2485 * @param pThis The KD context.
2486 */
2487DECLINLINE(int) dbgcKdCtxPktSendAck(PKDCTX pThis)
2488{
2489 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE,
2490 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2491}
2492
2493
2494/**
2495 * Resets the packet receive state machine.
2496 *
2497 * @returns nothing.
2498 * @param pThis The KD context.
2499 */
2500static void dbgcKdCtxPktRecvReset(PKDCTX pThis)
2501{
2502 pThis->enmState = KDRECVSTATE_PACKET_HDR_FIRST_BYTE;
2503 pThis->pbRecv = &pThis->PktHdr.ab[0];
2504 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[0]);
2505 pThis->msRecvTimeout = RT_INDEFINITE_WAIT;
2506 pThis->tsRecvLast = RTTimeMilliTS();
2507}
2508
2509
2510/**
2511 * Sends a Debug I/O string packet.
2512 *
2513 * @returns VBox status code.
2514 * @param pThis The KD context data.
2515 * @param idCpu The CPU ID generating this packet.
2516 * @param pachChars The characters to send (ASCII).
2517 * @param cbChars Number of characters to send.
2518 */
2519static int dbgcKdCtxDebugIoStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachChars, size_t cbChars)
2520{
2521 KDPACKETDEBUGIO DebugIo;
2522 RT_ZERO(DebugIo);
2523
2524 /* Fix your damn log strings if this exceeds 4GB... */
2525 if (cbChars != (uint32_t)cbChars)
2526 return VERR_BUFFER_OVERFLOW;
2527
2528 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2529 DebugIo.u16CpuLvl = 0x6;
2530 DebugIo.idCpu = (uint16_t)idCpu;
2531 DebugIo.u.Str.cbStr = (uint32_t)cbChars;
2532
2533 RTSGSEG aRespSegs[2];
2534
2535 aRespSegs[0].pvSeg = &DebugIo;
2536 aRespSegs[0].cbSeg = sizeof(DebugIo);
2537 aRespSegs[1].pvSeg = (void *)pachChars;
2538 aRespSegs[1].cbSeg = cbChars;
2539
2540 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2541 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2542 if (RT_SUCCESS(rc))
2543 pThis->idPktNext ^= 0x1;
2544
2545 return rc;
2546}
2547
2548
2549/**
2550 * Sends a message to the remotes end.
2551 *
2552 * @returns nothing.
2553 * @param pThis The KD context data.
2554 * @param fWarning Flag whether this is a warning or an informational message.
2555 * @param pszMsg The message to send.
2556 */
2557static void dbgcKdCtxMsgSend(PKDCTX pThis, bool fWarning, const char *pszMsg)
2558{
2559 size_t cchMsg = strlen(pszMsg);
2560
2561 KDPACKETDEBUGIO DebugIo;
2562 RT_ZERO(DebugIo);
2563
2564 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2565 DebugIo.u16CpuLvl = 0x6;
2566 DebugIo.idCpu = 0;
2567
2568 RTSGSEG aRespSegs[5];
2569
2570 aRespSegs[0].pvSeg = &DebugIo;
2571 aRespSegs[0].cbSeg = sizeof(DebugIo);
2572 aRespSegs[1].pvSeg = (void *)"VBoxDbg ";
2573 aRespSegs[1].cbSeg = sizeof("VBoxDbg ") - 1;
2574 if (fWarning)
2575 {
2576 aRespSegs[2].pvSeg = (void *)"WARNING ";
2577 aRespSegs[2].cbSeg = sizeof("WARNING ") - 1;
2578 }
2579 else
2580 {
2581 aRespSegs[2].pvSeg = (void *)"INFO ";
2582 aRespSegs[2].cbSeg = sizeof("INFO ") - 1;
2583 }
2584 aRespSegs[3].pvSeg = (void *)pszMsg;
2585 aRespSegs[3].cbSeg = cchMsg;
2586 aRespSegs[4].pvSeg = (void *)"\r\n";
2587 aRespSegs[4].cbSeg = 2;
2588
2589 DebugIo.u.Str.cbStr = (uint32_t)( aRespSegs[1].cbSeg
2590 + aRespSegs[2].cbSeg
2591 + aRespSegs[3].cbSeg
2592 + aRespSegs[4].cbSeg);
2593
2594 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2595 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2596 if (RT_SUCCESS(rc))
2597 pThis->idPktNext ^= 0x1;
2598}
2599
2600
2601/**
2602 * Queries some user input from the remotes end.
2603 *
2604 * @returns VBox status code.
2605 * @param pThis The KD context data.
2606 * @param idCpu The CPU ID generating this packet.
2607 * @param pachPrompt The prompt to send (ASCII).
2608 * @param cbPrompt Number of characters to send for the prompt.
2609 * @param cbResponseMax Maximum size for the response.
2610 */
2611static int dbgcKdCtxDebugIoGetStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachPrompt, size_t cbPrompt,
2612 size_t cbResponseMax)
2613{
2614 KDPACKETDEBUGIO DebugIo;
2615 RT_ZERO(DebugIo);
2616
2617 /* Fix your damn log strings if this exceeds 4GB... */
2618 if ( cbPrompt != (uint32_t)cbPrompt
2619 || cbResponseMax != (uint32_t)cbResponseMax)
2620 return VERR_BUFFER_OVERFLOW;
2621
2622 DebugIo.u32Type = KD_PACKET_DEBUG_IO_GET_STRING;
2623 DebugIo.u16CpuLvl = 0x6;
2624 DebugIo.idCpu = (uint16_t)idCpu;
2625 DebugIo.u.Prompt.cbPrompt = (uint32_t)cbPrompt;
2626 DebugIo.u.Prompt.cbReturn = (uint32_t)cbResponseMax;
2627
2628 RTSGSEG aRespSegs[2];
2629
2630 aRespSegs[0].pvSeg = &DebugIo;
2631 aRespSegs[0].cbSeg = sizeof(DebugIo);
2632 aRespSegs[1].pvSeg = (void *)pachPrompt;
2633 aRespSegs[1].cbSeg = cbPrompt;
2634
2635 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2636 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2637 if (RT_SUCCESS(rc))
2638 pThis->idPktNext ^= 0x1;
2639
2640 return rc;
2641}
2642
2643
2644/**
2645 * Sends a state change event packet.
2646 *
2647 * @returns VBox status code.
2648 * @param pThis The KD context data.
2649 * @param enmType The event type.
2650 */
2651static int dbgcKdCtxStateChangeSend(PKDCTX pThis, DBGFEVENTTYPE enmType)
2652{
2653 LogFlowFunc(("pThis=%p enmType=%u\n", pThis, enmType));
2654
2655 /* Select the record to send based on the CPU mode. */
2656 int rc = VINF_SUCCESS;
2657 KDPACKETSTATECHANGE64 StateChange64;
2658 RT_ZERO(StateChange64);
2659
2660 StateChange64.u32StateNew = KD_PACKET_STATE_CHANGE_EXCEPTION;
2661 StateChange64.u16CpuLvl = 0x6; /** @todo Figure this one out. */
2662 StateChange64.idCpu = pThis->Dbgc.idCpu;
2663 StateChange64.cCpus = (uint16_t)DBGFR3CpuGetCount(pThis->Dbgc.pUVM);
2664 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RIP, &StateChange64.u64RipThread);
2665 if (RT_SUCCESS(rc))
2666 {
2667 DBGFADDRESS AddrRip;
2668 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRip, StateChange64.u64RipThread);
2669
2670 StateChange64.u64RipThread = KD_PTR_CREATE(pThis, StateChange64.u64RipThread);
2671
2672 /** @todo Properly fill in the exception record. */
2673 switch (enmType)
2674 {
2675 case DBGFEVENT_HALT_DONE:
2676 case DBGFEVENT_BREAKPOINT:
2677 case DBGFEVENT_BREAKPOINT_IO:
2678 case DBGFEVENT_BREAKPOINT_MMIO:
2679 case DBGFEVENT_BREAKPOINT_HYPER:
2680 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_BKPT;
2681 break;
2682 case DBGFEVENT_STEPPED:
2683 case DBGFEVENT_STEPPED_HYPER:
2684 pThis->fSingleStepped = true; /* For emulation of DR6. */
2685 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_SINGLE_STEP;
2686 break;
2687 default:
2688 AssertMsgFailed(("Invalid DBGF event type for state change %d!\n", enmType));
2689 }
2690
2691 StateChange64.u.Exception.ExcpRec.cExcpParms = 3;
2692 StateChange64.u.Exception.u32FirstChance = 0x1;
2693
2694 /** @todo Properly fill in the control report. */
2695 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR6, &StateChange64.uCtrlReport.Amd64.u64RegDr6);
2696 if (RT_SUCCESS(rc))
2697 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR7, &StateChange64.uCtrlReport.Amd64.u64RegDr7);
2698 if (RT_SUCCESS(rc))
2699 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RFLAGS, &StateChange64.uCtrlReport.Amd64.u32RegEflags);
2700 if (RT_SUCCESS(rc))
2701 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_CS, &StateChange64.uCtrlReport.Amd64.u16SegCs);
2702 if (RT_SUCCESS(rc))
2703 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DS, &StateChange64.uCtrlReport.Amd64.u16SegDs);
2704 if (RT_SUCCESS(rc))
2705 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_ES, &StateChange64.uCtrlReport.Amd64.u16SegEs);
2706 if (RT_SUCCESS(rc))
2707 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_FS, &StateChange64.uCtrlReport.Amd64.u16SegFs);
2708
2709 /* Read instruction bytes. */
2710 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
2711 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
2712 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
2713 if (RT_SUCCESS(rc))
2714 {
2715 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2716 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
2717 &StateChange64, sizeof(StateChange64), false /*fAck*/);
2718 }
2719 }
2720
2721 LogFlowFunc(("returns %Rrc\n", rc));
2722 return rc;
2723}
2724
2725
2726/**
2727 * Processes a get version 64 request.
2728 *
2729 * @returns VBox status code.
2730 * @param pThis The KD context.
2731 * @param pPktManip The manipulate packet request.
2732 */
2733static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2734{
2735 KDPACKETMANIPULATE64 Resp;
2736 RT_ZERO(Resp);
2737
2738 /* Fill in the generic part. */
2739 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
2740 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2741 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
2742 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
2743
2744 /* Build our own response in case there is no Windows interface available. */
2745 uint32_t NtBuildNumber = 0x0f2800; /* Used when there is no NT interface available, which probably breaks symbol loading. */
2746 bool f32Bit = false;
2747 if (pThis->pIfWinNt)
2748 {
2749 int rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM,
2750 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
2751 &NtBuildNumber, &f32Bit);
2752 if (RT_SUCCESS(rc))
2753 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, &Resp.u.GetVersion.u64PtrKernBase,
2754 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2755 }
2756
2757 /* Fill in the request specific part. */
2758 Resp.u.GetVersion.u16VersMaj = NtBuildNumber >> 16;
2759 Resp.u.GetVersion.u16VersMin = NtBuildNumber & UINT32_C(0xffff);
2760 Resp.u.GetVersion.u8VersProtocol = 0x6; /* From a Windows 10 guest. */
2761 Resp.u.GetVersion.u8VersKdSecondary = pThis->f32Bit ? 0 : 0x2; /* amd64 has a versioned context (0 and 1 are obsolete). */
2762 Resp.u.GetVersion.fFlags = KD_PACKET_MANIPULATE64_GET_VERSION_F_MP;
2763 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
2764 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
2765 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_MAX - KD_PACKET_MANIPULATE_REQ_MIN;
2766 Resp.u.GetVersion.u64PtrDebuggerDataList = 0;
2767
2768 if (f32Bit)
2769 {
2770 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_I386;
2771 Resp.u.GetVersion.u64PtrKernBase = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrKernBase);
2772 Resp.u.GetVersion.u64PtrPsLoadedModuleList = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2773 }
2774 else
2775 {
2776 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
2777 Resp.u.GetVersion.fFlags |= KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64;
2778 }
2779
2780 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2781 &Resp, sizeof(Resp), true /*fAck*/);
2782}
2783
2784
2785/**
2786 * Processes a read memory 64 request.
2787 *
2788 * @returns VBox status code.
2789 * @param pThis The KD context.
2790 * @param pPktManip The manipulate packet request.
2791 */
2792static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2793{
2794 KDPACKETMANIPULATEHDR RespHdr;
2795 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2796 uint8_t abMem[_4K];
2797 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2798
2799 DBGFADDRESS AddrRead;
2800 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
2801 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
2802 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2803 else
2804 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2805
2806 RTSGSEG aRespSegs[3];
2807 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2808 RespHdr.idReq = pPktManip->Hdr.idReq;
2809 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2810 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2811 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2812
2813 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2814 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2815 XferMem64.cbXfered = (uint32_t)cbRead;
2816
2817 aRespSegs[0].pvSeg = &RespHdr;
2818 aRespSegs[0].cbSeg = sizeof(RespHdr);
2819 aRespSegs[1].pvSeg = &XferMem64;
2820 aRespSegs[1].cbSeg = sizeof(XferMem64);
2821
2822 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
2823 if (RT_SUCCESS(rc))
2824 {
2825 cSegs++;
2826 aRespSegs[2].pvSeg = &abMem[0];
2827 aRespSegs[2].cbSeg = cbRead;
2828 }
2829 else
2830 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2831
2832 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2833 &aRespSegs[0], cSegs, true /*fAck*/);
2834}
2835
2836
2837/**
2838 * Processes a write memory 64 request.
2839 *
2840 * @returns VBox status code.
2841 * @param pThis The KD context.
2842 * @param pPktManip The manipulate packet request.
2843 */
2844static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2845{
2846 KDPACKETMANIPULATEHDR RespHdr;
2847 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2848 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2849
2850 DBGFADDRESS AddrWrite;
2851 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2852 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
2853 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
2854 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2855 else
2856 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2857
2858 RTSGSEG aRespSegs[2];
2859 uint32_t cSegs = 2;
2860 RespHdr.idReq = pPktManip->Hdr.idReq;
2861 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2862 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2863 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2864
2865 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2866 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2867 XferMem64.cbXfered = (uint32_t)cbWrite;
2868
2869 aRespSegs[0].pvSeg = &RespHdr;
2870 aRespSegs[0].cbSeg = sizeof(RespHdr);
2871 aRespSegs[1].pvSeg = &XferMem64;
2872 aRespSegs[1].cbSeg = sizeof(XferMem64);
2873
2874 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
2875 if (RT_FAILURE(rc))
2876 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2877
2878 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2879 &aRespSegs[0], cSegs, true /*fAck*/);
2880}
2881
2882
2883/**
2884 * Processes a continue request.
2885 *
2886 * @returns VBox status code.
2887 * @param pThis The KD context.
2888 * @param pPktManip The manipulate packet request.
2889 */
2890static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2891{
2892 RT_NOREF(pPktManip);
2893 int rc = VINF_SUCCESS;
2894
2895 /* No response, just resume. */
2896 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2897 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2898
2899 return rc;
2900}
2901
2902
2903/**
2904 * Processes a continue request.
2905 *
2906 * @returns VBox status code.
2907 * @param pThis The KD context.
2908 * @param pPktManip The manipulate packet request.
2909 */
2910static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2911{
2912 int rc = VINF_SUCCESS;
2913
2914 /* Update DR7. */
2915 if (pThis->f32Bit)
2916 rc = dbgcKdCtxHwBpDr7Update(pThis, pPktManip->u.Continue2.u.x86.u32RegDr7);
2917 else
2918 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pPktManip->u.Continue2.u.amd64.u64RegDr7);
2919
2920 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
2921 if (pPktManip->u.Continue2.fTrace)
2922 {
2923 PDBGFADDRESS pStackPop = NULL;
2924 RTGCPTR cbStackPop = 0;
2925 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
2926 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
2927 }
2928 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2929 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2930
2931 return rc;
2932}
2933
2934
2935/**
2936 * Processes a set context request.
2937 *
2938 * @returns VBox status code.
2939 * @param pThis The KD context.
2940 * @param pPktManip The manipulate packet request.
2941 */
2942static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2943{
2944 KDPACKETMANIPULATEHDR RespHdr;
2945 KDPACKETMANIPULATE_SETCONTEXT SetContext;
2946 RT_ZERO(RespHdr); RT_ZERO(SetContext);
2947
2948 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2949
2950 RTSGSEG aRespSegs[2];
2951 uint32_t cSegs = 2;
2952 RespHdr.idReq = pPktManip->Hdr.idReq;
2953 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2954 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2955 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2956
2957 /** @todo What do these flags mean? Can't be the context state to set because the valid one is
2958 * in NTCONTEXT64::fContext (observed with WinDbg). */
2959 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
2960
2961 aRespSegs[0].pvSeg = &RespHdr;
2962 aRespSegs[0].cbSeg = sizeof(RespHdr);
2963 aRespSegs[1].pvSeg = &SetContext;
2964 aRespSegs[1].cbSeg = sizeof(SetContext);
2965
2966 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, pNtCtx->fContext);
2967 if (RT_FAILURE(rc))
2968 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2969
2970 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2971 &aRespSegs[0], cSegs, true /*fAck*/);
2972}
2973
2974
2975/**
2976 * Processes a read control space 64 request.
2977 *
2978 * @returns VBox status code.
2979 * @param pThis The KD context.
2980 * @param pPktManip The manipulate packet request.
2981 */
2982static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2983{
2984 KDPACKETMANIPULATEHDR RespHdr;
2985 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2986 uint8_t abResp[sizeof(NTKCONTEXT64)];
2987 uint32_t cbData = 0;
2988 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2989 RT_ZERO(abResp);
2990
2991 RTSGSEG aRespSegs[3];
2992 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2993 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
2994 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2995 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2996 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2997
2998 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
2999 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3000
3001 aRespSegs[0].pvSeg = &RespHdr;
3002 aRespSegs[0].cbSeg = sizeof(RespHdr);
3003 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3004 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3005
3006 int rc = VINF_SUCCESS;
3007 if (pThis->f32Bit)
3008 {
3009 if (pPktManip->u.XferCtrlSpace.u64IdXfer == sizeof(NTCONTEXT32))
3010 {
3011 /* Queries the kernel context. */
3012 rc = dbgcKdCtxQueryNtKCtx32(pThis, RespHdr.idCpu, (PNTKCONTEXT32)&abResp[0]);
3013 if (RT_SUCCESS(rc))
3014 cbData = sizeof(NTKCONTEXT32);
3015 }
3016 }
3017 else
3018 {
3019 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3020 {
3021 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3022 {
3023 if (pThis->pIfWinNt)
3024 {
3025 RTGCUINTPTR GCPtrKpcr = 0;
3026
3027 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
3028 &GCPtrKpcr, NULL /*pKpcrb*/);
3029 if (RT_SUCCESS(rc))
3030 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
3031 }
3032
3033 cbData = sizeof(RTGCUINTPTR);
3034 break;
3035 }
3036 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3037 {
3038 if (pThis->pIfWinNt)
3039 {
3040 RTGCUINTPTR GCPtrKpcrb = 0;
3041
3042 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
3043 NULL /*pKpcr*/, &GCPtrKpcrb);
3044 if (RT_SUCCESS(rc))
3045 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
3046 }
3047
3048 cbData = sizeof(RTGCUINTPTR);
3049 break;
3050 }
3051 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3052 {
3053 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
3054 if (RT_SUCCESS(rc))
3055 cbData = sizeof(NTKCONTEXT64);
3056 break;
3057 }
3058 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3059 {
3060 if (pThis->pIfWinNt)
3061 {
3062 RTGCUINTPTR GCPtrCurThrd = 0;
3063
3064 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
3065 &GCPtrCurThrd);
3066 if (RT_SUCCESS(rc))
3067 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
3068 }
3069
3070 cbData = sizeof(RTGCUINTPTR);
3071 break;
3072 }
3073 default:
3074 rc = VERR_NOT_SUPPORTED;
3075 break;
3076 }
3077 }
3078
3079 if ( RT_SUCCESS(rc)
3080 && cbData)
3081 {
3082 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
3083
3084 cSegs++;
3085 aRespSegs[2].pvSeg = &abResp[0];
3086 aRespSegs[2].cbSeg = cbData;
3087 }
3088 else if (RT_FAILURE(rc))
3089 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3090
3091 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3092 &aRespSegs[0], cSegs, true /*fAck*/);
3093}
3094
3095
3096/**
3097 * Processes a write control space 64 request.
3098 *
3099 * @returns VBox status code.
3100 * @param pThis The KD context.
3101 * @param pPktManip The manipulate packet request.
3102 */
3103static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3104{
3105 KDPACKETMANIPULATEHDR RespHdr;
3106 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
3107 uint32_t cbData = 0;
3108 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3109
3110 RTSGSEG aRespSegs[2];
3111 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
3112 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3113 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3114 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3115
3116 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3117 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3118
3119 aRespSegs[0].pvSeg = &RespHdr;
3120 aRespSegs[0].cbSeg = sizeof(RespHdr);
3121 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3122 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3123
3124 int rc = VINF_SUCCESS;
3125 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3126 {
3127 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3128 {
3129 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3130 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
3131 if (RT_SUCCESS(rc))
3132 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
3133 break;
3134 }
3135 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3136 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3137 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3138 default:
3139 rc = VERR_NOT_SUPPORTED;
3140 break;
3141 }
3142
3143 if (RT_FAILURE(rc))
3144 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3145 else
3146 XferCtrlSpace64.cbXfered = cbData;
3147
3148 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3149 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3150}
3151
3152
3153/**
3154 * Processes a restore breakpoint 64 request.
3155 *
3156 * @returns VBox status code.
3157 * @param pThis The KD context.
3158 * @param pPktManip The manipulate packet request.
3159 */
3160static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3161{
3162 KDPACKETMANIPULATEHDR RespHdr;
3163 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
3164 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
3165
3166 RTSGSEG aRespSegs[2];
3167 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
3168 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3169 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3170 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3171
3172 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
3173
3174 aRespSegs[0].pvSeg = &RespHdr;
3175 aRespSegs[0].cbSeg = sizeof(RespHdr);
3176 aRespSegs[1].pvSeg = &RestoreBkpt64;
3177 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
3178
3179 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
3180 if (RT_SUCCESS(rc))
3181 {
3182 rc = dbgcBpDelete(&pThis->Dbgc, pPktManip->u.RestoreBkpt.u32HndBkpt);
3183 AssertRC(rc);
3184 }
3185 else if (rc != VERR_DBGF_BP_NOT_FOUND)
3186 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3187
3188 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3189 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3190}
3191
3192
3193/**
3194 * Processes a write breakpoint 64 request.
3195 *
3196 * @returns VBox status code.
3197 * @param pThis The KD context.
3198 * @param pPktManip The manipulate packet request.
3199 */
3200static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3201{
3202 KDPACKETMANIPULATEHDR RespHdr;
3203 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
3204 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
3205
3206 RTSGSEG aRespSegs[2];
3207 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
3208 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3209 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3210 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3211
3212 aRespSegs[0].pvSeg = &RespHdr;
3213 aRespSegs[0].cbSeg = sizeof(RespHdr);
3214 aRespSegs[1].pvSeg = &WriteBkpt64;
3215 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
3216
3217 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
3218
3219 DBGFADDRESS BpAddr;
3220 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, KD_PTR_GET(pThis, pPktManip->u.WriteBkpt.u64PtrBkpt));
3221 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
3222 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
3223 if (RT_SUCCESS(rc))
3224 {
3225 rc = dbgcBpAdd(&pThis->Dbgc, WriteBkpt64.u32HndBkpt, NULL /*pszCmd*/);
3226 if (RT_FAILURE(rc))
3227 DBGFR3BpClear(pThis->Dbgc.pUVM, WriteBkpt64.u32HndBkpt);
3228 }
3229 else
3230 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3231
3232 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3233 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3234}
3235
3236
3237/**
3238 * Processes a get context extended 64 request.
3239 *
3240 * @returns VBox status code.
3241 * @param pThis The KD context.
3242 * @param pPktManip The manipulate packet request.
3243 */
3244static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3245{
3246 KDPACKETMANIPULATEHDR RespHdr;
3247 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
3248 union
3249 {
3250 NTCONTEXT64 v64;
3251 NTCONTEXT32 v32;
3252 } NtCtx;
3253 RT_ZERO(RespHdr); RT_ZERO(ContextEx); RT_ZERO(NtCtx);
3254
3255 RTSGSEG aRespSegs[3];
3256 uint32_t cSegs = 2;
3257 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
3258 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3259 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3260 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3261
3262 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
3263 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
3264 ContextEx.cbXfered = 0;
3265
3266 aRespSegs[0].pvSeg = &RespHdr;
3267 aRespSegs[0].cbSeg = sizeof(RespHdr);
3268 aRespSegs[1].pvSeg = &ContextEx;
3269 aRespSegs[1].cbSeg = sizeof(ContextEx);
3270
3271 int rc = VINF_SUCCESS;
3272 uint32_t cbCtx = pThis->f32Bit ? sizeof(NtCtx.v32) : sizeof(NtCtx.v64);
3273 if (pThis->f32Bit)
3274 dbgcKdCtxQueryNtCtx32(pThis, pPktManip->Hdr.idCpu, &NtCtx.v32, NTCONTEXT32_F_FULL);
3275 else
3276 dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx.v64, NTCONTEXT64_F_FULL);
3277 if ( RT_SUCCESS(rc)
3278 && pPktManip->u.ContextEx.offStart < cbCtx)
3279 {
3280 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3281 ContextEx.cbXfered = RT_MIN(cbCtx - ContextEx.offStart, ContextEx.cbXfer);
3282
3283 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
3284 aRespSegs[2].cbSeg = ContextEx.cbXfered;
3285 cSegs++;
3286 }
3287
3288 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3289 &aRespSegs[0], cSegs, true /*fAck*/);
3290}
3291
3292
3293/**
3294 * Processes a query memory 64 request.
3295 *
3296 * @returns VBox status code.
3297 * @param pThis The KD context.
3298 * @param pPktManip The manipulate packet request.
3299 */
3300static int dbgcKdCtxPktManipulate64QueryMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3301{
3302 KDPACKETMANIPULATEHDR RespHdr;
3303 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
3304 RT_ZERO(RespHdr); RT_ZERO(QueryMemory);
3305
3306 RTSGSEG aRespSegs[2];
3307 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY;
3308 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3309 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3310 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3311
3312 /** @todo Need DBGF API to query protection and privilege level from guest page tables. */
3313 QueryMemory.u64GCPtr = pPktManip->u.QueryMemory.u64GCPtr;
3314 QueryMemory.u32AddrSpace = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_KERNEL;
3315 QueryMemory.u32Flags = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_READ
3316 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_WRITE
3317 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_EXEC;
3318
3319 aRespSegs[0].pvSeg = &RespHdr;
3320 aRespSegs[0].cbSeg = sizeof(RespHdr);
3321 aRespSegs[1].pvSeg = &QueryMemory;
3322 aRespSegs[1].cbSeg = sizeof(QueryMemory);
3323
3324 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3325 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3326}
3327
3328
3329/**
3330 * Processes a search memory 64 request.
3331 *
3332 * @returns VBox status code.
3333 * @param pThis The KD context.
3334 * @param pPktManip The manipulate packet request.
3335 */
3336static int dbgcKdCtxPktManipulate64SearchMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3337{
3338 KDPACKETMANIPULATEHDR RespHdr;
3339 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
3340 RT_ZERO(RespHdr); RT_ZERO(SearchMemory);
3341
3342 RTSGSEG aRespSegs[2];
3343 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY;
3344 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3345 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3346 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3347
3348 SearchMemory.u64GCPtr = pPktManip->u.SearchMemory.u64GCPtr;
3349 SearchMemory.cbSearch = pPktManip->u.SearchMemory.cbSearch;
3350 SearchMemory.cbPattern = pPktManip->u.SearchMemory.cbPattern;
3351
3352 /* Validate the pattern length and start searching. */
3353 if (pPktManip->u.SearchMemory.cbPattern < sizeof(pThis->abBody) - sizeof(*pPktManip))
3354 {
3355 DBGFADDRESS StartAddress;
3356 DBGFADDRESS HitAddress;
3357 VMCPUID idCpu = pPktManip->Hdr.idCpu;
3358 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &StartAddress, pPktManip->u.SearchMemory.u64GCPtr);
3359
3360 /** @todo WindDbg sends CPU ID 32 sometimes, maybe that means continue search on last used CPU?. */
3361 if (idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM))
3362 idCpu = pThis->Dbgc.idCpu;
3363
3364 int rc = DBGFR3MemScan(pThis->Dbgc.pUVM, idCpu, &StartAddress, pPktManip->u.SearchMemory.cbSearch, 1,
3365 &pThis->abBody[sizeof(*pPktManip)], pPktManip->u.SearchMemory.cbPattern, &HitAddress);
3366 if (RT_SUCCESS(rc))
3367 SearchMemory.u64GCPtr = HitAddress.FlatPtr;
3368 else if (rc == VERR_DBGF_MEM_NOT_FOUND)
3369 RespHdr.u32NtStatus = NTSTATUS_NOT_FOUND;
3370 else
3371 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3372 }
3373 else
3374 RespHdr.u32NtStatus = NTSTATUS_BUFFER_OVERFLOW;
3375
3376 aRespSegs[0].pvSeg = &RespHdr;
3377 aRespSegs[0].cbSeg = sizeof(RespHdr);
3378 aRespSegs[1].pvSeg = &SearchMemory;
3379 aRespSegs[1].cbSeg = sizeof(SearchMemory);
3380
3381 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3382 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3383}
3384
3385
3386/**
3387 * Processes a cause bugcheck 64 request.
3388 *
3389 * @returns VBox status code.
3390 * @param pThis The KD context.
3391 * @param pPktManip The manipulate packet request.
3392 *
3393 * @note We abuse this request to initiate a native VBox debugger command prompt from the remote end
3394 * (There is monitor/Rcmd equivalent like with GDB unfortunately).
3395 */
3396static int dbgcKdCtxPktManipulate64CauseBugCheck(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3397{
3398 RT_NOREF(pPktManip);
3399 pThis->fInVBoxDbg = true;
3400 return dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3401 512 /*cbResponseMax*/);
3402}
3403
3404
3405/**
3406 * Processes a manipulate packet.
3407 *
3408 * @returns VBox status code.
3409 * @param pThis The KD context.
3410 */
3411static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
3412{
3413 int rc = VINF_SUCCESS;
3414 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
3415
3416 switch (pPktManip->Hdr.idReq)
3417 {
3418 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
3419 {
3420 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
3421 break;
3422 }
3423 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
3424 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
3425 {
3426 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
3427 break;
3428 }
3429 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
3430 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
3431 {
3432 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
3433 break;
3434 }
3435 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
3436 {
3437 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
3438 break;
3439 }
3440 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
3441 {
3442 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
3443 break;
3444 }
3445 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
3446 {
3447 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
3448 break;
3449 }
3450 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
3451 {
3452 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
3453 break;
3454 }
3455 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
3456 {
3457 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
3458 break;
3459 }
3460 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
3461 {
3462 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
3463 break;
3464 }
3465 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
3466 {
3467 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
3468 break;
3469 }
3470 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
3471 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
3472 break;
3473 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
3474 {
3475 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
3476 break;
3477 }
3478 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
3479 {
3480 rc = dbgcKdCtxPktManipulate64QueryMemory(pThis, pPktManip);
3481 break;
3482 }
3483 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
3484 {
3485 rc = dbgcKdCtxPktManipulate64SearchMemory(pThis, pPktManip);
3486 break;
3487 }
3488 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK:
3489 {
3490 rc = dbgcKdCtxPktManipulate64CauseBugCheck(pThis, pPktManip);
3491 break;
3492 }
3493 case KD_PACKET_MANIPULATE_REQ_REBOOT:
3494 {
3495 rc = VMR3Reset(pThis->Dbgc.pUVM); /* Doesn't expect an answer here. */
3496 if ( RT_SUCCESS(rc)
3497 && DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3498 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3499 break;
3500 }
3501 default:
3502 KDPACKETMANIPULATEHDR RespHdr;
3503 RT_ZERO(RespHdr);
3504
3505 RespHdr.idReq = pPktManip->Hdr.idReq;
3506 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3507 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3508 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
3509 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3510 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3511 break;
3512 }
3513
3514 return rc;
3515}
3516
3517
3518/**
3519 * Tries to detect the guest OS running in the VM looking specifically for the Windows NT kind.
3520 *
3521 * @returns Nothing.
3522 * @param pThis The KD context.
3523 */
3524static void dbgcKdCtxDetectGstOs(PKDCTX pThis)
3525{
3526 pThis->pIfWinNt = NULL;
3527
3528 /* Try detecting a Windows NT guest. */
3529 char szName[64];
3530 int rc = DBGFR3OSDetect(pThis->Dbgc.pUVM, szName, sizeof(szName));
3531 if (RT_SUCCESS(rc))
3532 {
3533 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pThis->Dbgc.pUVM, DBGFOSINTERFACE_WINNT);
3534 if (pThis->pIfWinNt)
3535 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3536 else
3537 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3538 }
3539 else
3540 {
3541 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3542 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3543 }
3544
3545 if (pThis->pIfWinNt)
3546 {
3547 rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM,
3548 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
3549 NULL /*puBuildNumber*/, &pThis->f32Bit);
3550 AssertRC(rc);
3551 }
3552 else
3553 {
3554 /*
3555 * Try to detect bitness based on the current CPU mode which might fool us (32bit process running
3556 * inside of 64bit host).
3557 */
3558 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
3559 if (enmMode == CPUMMODE_PROTECTED)
3560 pThis->f32Bit = true;
3561 else if (enmMode == CPUMMODE_LONG)
3562 pThis->f32Bit = false;
3563 else
3564 LogRel(("DBGC/Kd: Heh, trying to debug real mode code with WinDbg are we? Good luck with that...\n"));
3565 }
3566}
3567
3568
3569/**
3570 * Processes a fully received packet.
3571 *
3572 * @returns VBox status code.
3573 * @param pThis The KD context.
3574 */
3575static int dbgcKdCtxPktProcess(PKDCTX pThis)
3576{
3577 int rc = VINF_SUCCESS;
3578
3579 pThis->fBreakinRecv = false;
3580
3581 /* Verify checksum. */
3582 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
3583 {
3584 /** @todo Check packet id. */
3585 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
3586 {
3587 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3588 rc = dbgcKdCtxPktSendAck(pThis);
3589 }
3590 if (RT_SUCCESS(rc))
3591 {
3592#ifdef LOG_ENABLED
3593 RTSGSEG Seg;
3594 Seg.pvSeg = &pThis->abBody[0];
3595 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
3596 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
3597#endif
3598
3599 switch (pThis->PktHdr.Fields.u16SubType)
3600 {
3601 case KD_PACKET_HDR_SUB_TYPE_RESET:
3602 {
3603 dbgcKdCtxDetectGstOs(pThis);
3604
3605 pThis->idPktNext = 0;
3606 rc = dbgcKdCtxPktSendReset(pThis);
3607 if (RT_SUCCESS(rc))
3608 {
3609 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3610 if (rc == VWRN_DBGF_ALREADY_HALTED)
3611 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3612 }
3613 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
3614 break;
3615 }
3616 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
3617 {
3618 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3619 rc = dbgcKdCtxPktManipulate64Process(pThis);
3620 break;
3621 }
3622 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
3623 case KD_PACKET_HDR_SUB_TYPE_RESEND:
3624 {
3625 /* Don't do anything. */
3626 rc = VINF_SUCCESS;
3627 break;
3628 }
3629 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO:
3630 {
3631 if (pThis->fInVBoxDbg)
3632 {
3633 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3634 /* Get the string and execute it. */
3635 PCKDPACKETDEBUGIO pPktDbgIo = (PCKDPACKETDEBUGIO)&pThis->abBody[0];
3636 if ( pPktDbgIo->u32Type == KD_PACKET_DEBUG_IO_GET_STRING
3637 && pPktDbgIo->u.Prompt.cbReturn <= sizeof(pThis->abBody) - sizeof(*pPktDbgIo) - 1)
3638 {
3639 if (pPktDbgIo->u.Prompt.cbReturn)
3640 {
3641 /* Terminate return value. */
3642 pThis->abBody[sizeof(*pPktDbgIo) + pPktDbgIo->u.Prompt.cbReturn] = '\0';
3643
3644 const char *pszCmd = (const char *)&pThis->abBody[sizeof(*pPktDbgIo)];
3645 /* Filter out 'exit' which is handled here directly and exits the debug loop. */
3646 if (!strcmp(pszCmd, "exit"))
3647 pThis->fInVBoxDbg = false;
3648 else
3649 {
3650 rc = pThis->Dbgc.CmdHlp.pfnExec(&pThis->Dbgc.CmdHlp, pszCmd);
3651 if (RT_SUCCESS(rc))
3652 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3653 512 /*cbResponseMax*/);
3654 else
3655 LogRel(("DBGC/Kd: Executing command \"%s\" failed with rc=%Rrc\n", pszCmd, rc));
3656 }
3657 }
3658 else
3659 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3660 512 /*cbResponseMax*/);
3661 }
3662 else
3663 LogRel(("DBGC/Kd: Received invalid DEBUG_IO packet from remote end, ignoring\n"));
3664 }
3665 else
3666 LogRel(("DBGC/Kd: Received out of band DEBUG_IO packet from remote end, ignoring\n"));
3667 break;
3668 }
3669 default:
3670 rc = VERR_NOT_IMPLEMENTED;
3671 }
3672 }
3673 }
3674 else
3675 {
3676 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3677 rc = dbgcKdCtxPktSendResend(pThis);
3678 }
3679
3680 if (pThis->fBreakinRecv)
3681 {
3682 pThis->fBreakinRecv = false;
3683 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3684 if (rc == VWRN_DBGF_ALREADY_HALTED)
3685 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3686 }
3687
3688 /* Next packet. */
3689 dbgcKdCtxPktRecvReset(pThis);
3690 return rc;
3691}
3692
3693
3694/**
3695 * Processes the received data based on the current state.
3696 *
3697 * @returns VBox status code.
3698 * @param pThis The KD context.
3699 */
3700static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
3701{
3702 int rc = VINF_SUCCESS;
3703
3704 switch (pThis->enmState)
3705 {
3706 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
3707 {
3708 /* Does it look like a valid packet start?. */
3709 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
3710 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
3711 {
3712 pThis->pbRecv = &pThis->PktHdr.ab[1];
3713 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3714 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
3715 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
3716 }
3717 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3718 {
3719 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3720 if (rc == VWRN_DBGF_ALREADY_HALTED)
3721 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3722 dbgcKdCtxPktRecvReset(pThis);
3723 }
3724 /* else: Ignore and continue. */
3725 break;
3726 }
3727 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
3728 {
3729 /*
3730 * If the first and second byte differ there might be a single breakin
3731 * packet byte received and this is actually the start of a new packet.
3732 */
3733 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
3734 {
3735 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3736 {
3737 /* Halt the VM and rearrange the packet receiving state machine. */
3738 LogFlow(("DbgKd: Halting VM!\n"));
3739
3740 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3741 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
3742 pThis->pbRecv = &pThis->PktHdr.ab[1];
3743 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3744 }
3745 else
3746 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
3747 }
3748 else
3749 {
3750 /* Normal packet receive continues with the rest of the header. */
3751 pThis->pbRecv = &pThis->PktHdr.ab[2];
3752 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
3753 pThis->enmState = KDRECVSTATE_PACKET_HDR;
3754 }
3755 break;
3756 }
3757 case KDRECVSTATE_PACKET_HDR:
3758 {
3759 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
3760 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
3761 {
3762 /* Start receiving the body. */
3763 if (pThis->PktHdr.Fields.cbBody)
3764 {
3765 pThis->pbRecv = &pThis->abBody[0];
3766 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
3767 pThis->enmState = KDRECVSTATE_PACKET_BODY;
3768 }
3769 else /* No body means no trailer byte it looks like. */
3770 rc = dbgcKdCtxPktProcess(pThis);
3771 }
3772 else
3773 rc = VERR_NET_PROTOCOL_ERROR;
3774 break;
3775 }
3776 case KDRECVSTATE_PACKET_BODY:
3777 {
3778 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
3779 pThis->bTrailer = 0;
3780 pThis->pbRecv = &pThis->bTrailer;
3781 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
3782 break;
3783 }
3784 case KDRECVSTATE_PACKET_TRAILER:
3785 {
3786 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
3787 rc = dbgcKdCtxPktProcess(pThis);
3788 else
3789 rc = VERR_NET_PROTOCOL_ERROR;
3790 break;
3791 }
3792 default:
3793 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
3794 }
3795
3796 return rc;
3797}
3798
3799
3800/**
3801 * Receive data and processes complete packets.
3802 *
3803 * @returns Status code.
3804 * @param pThis The KD context.
3805 */
3806static int dbgcKdCtxRecv(PKDCTX pThis)
3807{
3808 int rc = VINF_SUCCESS;
3809
3810 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
3811
3812 if (pThis->cbRecvLeft)
3813 {
3814 size_t cbRead = 0;
3815 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
3816 if (RT_SUCCESS(rc))
3817 {
3818 pThis->tsRecvLast = RTTimeMilliTS();
3819 pThis->cbRecvLeft -= cbRead;
3820 pThis->pbRecv += cbRead;
3821 if (!pThis->cbRecvLeft)
3822 rc = dbgcKdCtxRecvDataProcess(pThis);
3823 }
3824 }
3825
3826 LogFlowFunc(("returns rc=%Rrc\n", rc));
3827 return rc;
3828}
3829
3830
3831/**
3832 * Processes debugger events.
3833 *
3834 * @returns VBox status code.
3835 * @param pThis The KD context data.
3836 * @param pEvent Pointer to event data.
3837 */
3838static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
3839{
3840 /*
3841 * Process the event.
3842 */
3843 PDBGC pDbgc = &pThis->Dbgc;
3844 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
3845 pThis->Dbgc.iArg = 0;
3846 int rc = VINF_SUCCESS;
3847 VMCPUID idCpuOld = pDbgc->idCpu;
3848 pDbgc->idCpu = pEvent->idCpu;
3849 switch (pEvent->enmType)
3850 {
3851 /*
3852 * The first part is events we have initiated with commands.
3853 */
3854 case DBGFEVENT_HALT_DONE:
3855 {
3856 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3857 break;
3858 }
3859
3860 /*
3861 * The second part is events which can occur at any time.
3862 */
3863 case DBGFEVENT_FATAL_ERROR:
3864 {
3865 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
3866 dbgcGetEventCtx(pEvent->enmCtx));
3867 if (RT_SUCCESS(rc))
3868 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3869 break;
3870 }
3871
3872 case DBGFEVENT_BREAKPOINT:
3873 case DBGFEVENT_BREAKPOINT_IO:
3874 case DBGFEVENT_BREAKPOINT_MMIO:
3875 case DBGFEVENT_BREAKPOINT_HYPER:
3876 {
3877 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp);
3878 switch (rc)
3879 {
3880 case VERR_DBGC_BP_NOT_FOUND:
3881 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
3882 pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
3883 break;
3884
3885 case VINF_DBGC_BP_NO_COMMAND:
3886 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
3887 pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
3888 break;
3889
3890 case VINF_BUFFER_OVERFLOW:
3891 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
3892 pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
3893 break;
3894
3895 default:
3896 break;
3897 }
3898 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL))
3899 {
3900 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3901
3902 /* Set the resume flag to ignore the breakpoint when resuming execution. */
3903 if ( RT_SUCCESS(rc)
3904 && pEvent->enmType == DBGFEVENT_BREAKPOINT)
3905 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
3906 }
3907
3908 /* Figure out the breakpoint and set the triggered flag for emulation of DR6. */
3909 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
3910 {
3911 if (pThis->aHwBp[i].iDbgfBp == pEvent->u.Bp.iBp)
3912 {
3913 pThis->aHwBp[i].fTriggered = true;
3914 break;
3915 }
3916 }
3917
3918 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3919 break;
3920 }
3921
3922 case DBGFEVENT_STEPPED:
3923 case DBGFEVENT_STEPPED_HYPER:
3924 {
3925 pThis->fSingleStepped = true; /* For emulation of DR6. */
3926 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3927 break;
3928 }
3929
3930 case DBGFEVENT_ASSERTION_HYPER:
3931 {
3932 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3933 "\ndbgf event: Hypervisor Assertion! (%s)\n"
3934 "%s"
3935 "%s"
3936 "\n",
3937 dbgcGetEventCtx(pEvent->enmCtx),
3938 pEvent->u.Assert.pszMsg1,
3939 pEvent->u.Assert.pszMsg2);
3940 if (RT_SUCCESS(rc))
3941 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3942 break;
3943 }
3944
3945 case DBGFEVENT_DEV_STOP:
3946 {
3947 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3948 "\n"
3949 "dbgf event: DBGFSTOP (%s)\n"
3950 "File: %s\n"
3951 "Line: %d\n"
3952 "Function: %s\n",
3953 dbgcGetEventCtx(pEvent->enmCtx),
3954 pEvent->u.Src.pszFile,
3955 pEvent->u.Src.uLine,
3956 pEvent->u.Src.pszFunction);
3957 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
3958 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3959 "Message: %s\n",
3960 pEvent->u.Src.pszMessage);
3961 if (RT_SUCCESS(rc))
3962 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3963 break;
3964 }
3965
3966
3967 case DBGFEVENT_INVALID_COMMAND:
3968 {
3969 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
3970 break;
3971 }
3972
3973 case DBGFEVENT_POWERING_OFF:
3974 {
3975 pThis->Dbgc.fReady = false;
3976 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, false);
3977 rc = VERR_GENERAL_FAILURE;
3978 break;
3979 }
3980
3981 default:
3982 {
3983 /*
3984 * Probably a generic event. Look it up to find its name.
3985 */
3986 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
3987 if (pEvtDesc)
3988 {
3989 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
3990 {
3991 Assert(pEvtDesc->pszDesc);
3992 Assert(pEvent->u.Generic.cArgs == 1);
3993 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
3994 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
3995 }
3996 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
3997 {
3998 Assert(pEvent->u.Generic.cArgs >= 5);
3999 char szDetails[512];
4000 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
4001 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
4002 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
4003 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
4004 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
4005 szDetails);
4006 }
4007 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
4008 || pEvent->u.Generic.cArgs > 1
4009 || ( pEvent->u.Generic.cArgs == 1
4010 && pEvent->u.Generic.auArgs[0] != 0))
4011 {
4012 if (pEvtDesc->pszDesc)
4013 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
4014 pEvtDesc->pszName, pEvtDesc->pszDesc);
4015 else
4016 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
4017 if (pEvent->u.Generic.cArgs <= 1)
4018 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
4019 else
4020 {
4021 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
4022 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
4023 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
4024 }
4025 }
4026 else
4027 {
4028 if (pEvtDesc->pszDesc)
4029 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
4030 pEvtDesc->pszName, pEvtDesc->pszDesc);
4031 else
4032 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
4033 }
4034 }
4035 else
4036 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
4037 break;
4038 }
4039 }
4040
4041 pDbgc->idCpu = idCpuOld;
4042 return rc;
4043}
4044
4045
4046/**
4047 * Handle a receive timeout.
4048 *
4049 * @returns VBox status code.
4050 * @param pThis Pointer to the KD context.
4051 */
4052static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
4053{
4054 int rc = VINF_SUCCESS;
4055
4056 LogFlowFunc(("pThis=%p\n", pThis));
4057
4058 /*
4059 * If a single breakin packet byte was received but the header is otherwise incomplete
4060 * the VM is halted and a state change will be sent in the event processing loop.
4061 */
4062 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
4063 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
4064 {
4065 LogFlow(("DbgKd: Halting VM!\n"));
4066 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
4067 }
4068 else /* Send a reset packet (@todo Figure out the semantics in this case exactly). */
4069 rc = dbgcKdCtxPktSendReset(pThis);
4070
4071 dbgcKdCtxPktRecvReset(pThis);
4072
4073 LogFlowFunc(("rc=%Rrc\n", rc));
4074 return rc;
4075}
4076
4077
4078/**
4079 * @copydoc DBGC::pfnOutput
4080 */
4081static DECLCALLBACK(int) dbgcKdOutput(void *pvUser, const char *pachChars, size_t cbChars)
4082{
4083 PKDCTX pThis = (PKDCTX)pvUser;
4084
4085 return dbgcKdCtxDebugIoStrSend(pThis, pThis->Dbgc.idCpu, pachChars, cbChars);
4086}
4087
4088
4089/**
4090 * Run the debugger console.
4091 *
4092 * @returns VBox status code.
4093 * @param pThis Pointer to the KD context.
4094 */
4095int dbgcKdRun(PKDCTX pThis)
4096{
4097 /*
4098 * We're ready for commands now.
4099 */
4100 pThis->Dbgc.fReady = true;
4101 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, true);
4102
4103 /*
4104 * Main Debugger Loop.
4105 *
4106 * This loop will either block on waiting for input or on waiting on
4107 * debug events. If we're forwarding the log we cannot wait for long
4108 * before we must flush the log.
4109 */
4110 int rc;
4111 for (;;)
4112 {
4113 rc = VERR_SEM_OUT_OF_TURN;
4114 if (pThis->Dbgc.pUVM)
4115 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
4116
4117 if (RT_SUCCESS(rc))
4118 {
4119 /*
4120 * Wait for a debug event.
4121 */
4122 DBGFEVENT Evt;
4123 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
4124 if (RT_SUCCESS(rc))
4125 {
4126 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
4127 if (RT_FAILURE(rc))
4128 break;
4129 }
4130 else if (rc != VERR_TIMEOUT)
4131 break;
4132
4133 /*
4134 * Check for input.
4135 */
4136 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 0))
4137 {
4138 rc = dbgcKdCtxRecv(pThis);
4139 if (RT_FAILURE(rc))
4140 break;
4141 }
4142 }
4143 else if (rc == VERR_SEM_OUT_OF_TURN)
4144 {
4145 /*
4146 * Wait for input.
4147 */
4148 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 1000))
4149 {
4150 rc = dbgcKdCtxRecv(pThis);
4151 if (RT_FAILURE(rc))
4152 break;
4153 }
4154 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
4155 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
4156 rc = dbgcKdCtxRecvTimeout(pThis);
4157 }
4158 else
4159 break;
4160 }
4161
4162 return rc;
4163}
4164
4165
4166/**
4167 * Creates a KD context instance with the given backend.
4168 *
4169 * @returns VBox status code.
4170 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
4171 * @param pBack The backend to use for I/O.
4172 * @param fFlags Flags controlling the behavior.
4173 */
4174static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PDBGCBACK pBack, unsigned fFlags)
4175{
4176 /*
4177 * Validate input.
4178 */
4179 AssertPtrReturn(pBack, VERR_INVALID_POINTER);
4180 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
4181
4182 /*
4183 * Allocate and initialize.
4184 */
4185 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
4186 if (!pThis)
4187 return VERR_NO_MEMORY;
4188
4189 dbgcInitCmdHlp(&pThis->Dbgc);
4190 /*
4191 * This is compied from the native debug console (will be used for monitor commands)
4192 * in DBGCConsole.cpp. Try to keep both functions in sync.
4193 */
4194 pThis->Dbgc.pBack = pBack;
4195 pThis->Dbgc.pfnOutput = dbgcKdOutput;
4196 pThis->Dbgc.pvOutputUser = pThis;
4197 pThis->Dbgc.pVM = NULL;
4198 pThis->Dbgc.pUVM = NULL;
4199 pThis->Dbgc.idCpu = 0;
4200 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
4201 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
4202 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
4203 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
4204 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
4205 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
4206 //pThis->Dbgc.fLog = false;
4207 pThis->Dbgc.fRegTerse = true;
4208 pThis->Dbgc.fStepTraceRegs = true;
4209 //pThis->Dbgc.cPagingHierarchyDumps = 0;
4210 //pThis->Dbgc.DisasmPos = {0};
4211 //pThis->Dbgc.SourcePos = {0};
4212 //pThis->Dbgc.DumpPos = {0};
4213 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
4214 //pThis->Dbgc.cbDumpElement = 0;
4215 //pThis->Dbgc.cVars = 0;
4216 //pThis->Dbgc.paVars = NULL;
4217 //pThis->Dbgc.pPlugInHead = NULL;
4218 //pThis->Dbgc.pFirstBp = NULL;
4219 //pThis->Dbgc.abSearch = {0};
4220 //pThis->Dbgc.cbSearch = 0;
4221 pThis->Dbgc.cbSearchUnit = 1;
4222 pThis->Dbgc.cMaxSearchHits = 1;
4223 //pThis->Dbgc.SearchAddr = {0};
4224 //pThis->Dbgc.cbSearchRange = 0;
4225
4226 //pThis->Dbgc.uInputZero = 0;
4227 //pThis->Dbgc.iRead = 0;
4228 //pThis->Dbgc.iWrite = 0;
4229 //pThis->Dbgc.cInputLines = 0;
4230 //pThis->Dbgc.fInputOverflow = false;
4231 pThis->Dbgc.fReady = true;
4232 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
4233 //pThis->Dbgc.iArg = 0;
4234 //pThis->Dbgc.rcOutput = 0;
4235 //pThis->Dbgc.rcCmd = 0;
4236
4237 //pThis->Dbgc.pszHistoryFile = NULL;
4238 //pThis->Dbgc.pszGlobalInitScript = NULL;
4239 //pThis->Dbgc.pszLocalInitScript = NULL;
4240
4241 dbgcEvalInit();
4242
4243 pThis->fBreakinRecv = false;
4244 pThis->fInVBoxDbg = false;
4245 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
4246 pThis->pIfWinNt = NULL;
4247 pThis->f32Bit = false;
4248 dbgcKdCtxPktRecvReset(pThis);
4249
4250 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
4251 {
4252 PKDCTXHWBP pBp = &pThis->aHwBp[i];
4253 pBp->iDbgfBp = UINT32_MAX;
4254 }
4255
4256 dbgcKdCtxHwBpReset(pThis);
4257
4258 *ppKdCtx = pThis;
4259 return VINF_SUCCESS;
4260}
4261
4262
4263/**
4264 * Destroys the given KD context.
4265 *
4266 * @returns nothing.
4267 * @param pThis The KD context to destroy.
4268 */
4269static void dbgcKdCtxDestroy(PKDCTX pThis)
4270{
4271 AssertPtr(pThis);
4272
4273 pThis->pIfWinNt = NULL;
4274
4275 /* Detach from the VM. */
4276 if (pThis->Dbgc.pUVM)
4277 DBGFR3Detach(pThis->Dbgc.pUVM);
4278
4279 /* Free config strings. */
4280 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
4281 pThis->Dbgc.pszGlobalInitScript = NULL;
4282 RTStrFree(pThis->Dbgc.pszLocalInitScript);
4283 pThis->Dbgc.pszLocalInitScript = NULL;
4284 RTStrFree(pThis->Dbgc.pszHistoryFile);
4285 pThis->Dbgc.pszHistoryFile = NULL;
4286
4287 /* Finally, free the instance memory. */
4288 RTMemFree(pThis);
4289}
4290
4291
4292DECLHIDDEN(int) dbgcKdStubCreate(PUVM pUVM, PDBGCBACK pBack, unsigned fFlags)
4293{
4294 /*
4295 * Validate input.
4296 */
4297 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
4298 PVM pVM = NULL;
4299 if (pUVM)
4300 {
4301 pVM = VMR3GetVM(pUVM);
4302 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
4303 }
4304
4305 /*
4306 * Allocate and initialize instance data
4307 */
4308 PKDCTX pThis;
4309 int rc = dbgcKdCtxCreate(&pThis, pBack, fFlags);
4310 if (RT_FAILURE(rc))
4311 return rc;
4312 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
4313 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
4314
4315 /*
4316 * Attach to the specified VM.
4317 */
4318 if (RT_SUCCESS(rc) && pUVM)
4319 {
4320 rc = DBGFR3Attach(pUVM);
4321 if (RT_SUCCESS(rc))
4322 {
4323 pThis->Dbgc.pVM = pVM;
4324 pThis->Dbgc.pUVM = pUVM;
4325 pThis->Dbgc.idCpu = 0;
4326 }
4327 else
4328 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
4329 }
4330
4331 /*
4332 * Load plugins.
4333 */
4334 if (RT_SUCCESS(rc))
4335 {
4336 if (pVM)
4337 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
4338 dbgcEventInit(&pThis->Dbgc);
4339
4340 /*
4341 * Run the debugger main loop.
4342 */
4343 rc = dbgcKdRun(pThis);
4344 dbgcEventTerm(&pThis->Dbgc);
4345 }
4346
4347 /*
4348 * Cleanup console debugger session.
4349 */
4350 dbgcKdCtxDestroy(pThis);
4351 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
4352}
4353
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