VirtualBox

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

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

Debugger/DBGCRemoteKd: Rework get version handler to fill in the right buidld number and flags

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 117.3 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 86160 2020-09-17 17:10:14Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Windows Kd Remote Stub.
4 */
5
6/*
7 * Copyright (C) 2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <VBox/dbg.h>
23#include <VBox/vmm/dbgf.h>
24#include <VBox/vmm/vmapi.h> /* VMR3GetVM() */
25#include <VBox/vmm/hm.h> /* HMR3IsEnabled */
26#include <VBox/vmm/nem.h> /* NEMR3IsEnabled */
27#include <iprt/assertcompile.h>
28#include <iprt/cdefs.h>
29#include <iprt/err.h>
30#include <iprt/list.h>
31#include <iprt/mem.h>
32#include <iprt/sg.h>
33#include <iprt/string.h>
34#include <iprt/time.h>
35#include <iprt/x86.h>
36#include <iprt/formats/pecoff.h>
37#include <iprt/formats/mz.h>
38
39#include <stdlib.h>
40
41#include "DBGCInternal.h"
42
43
44/*********************************************************************************************************************************
45* Defined Constants And Macros *
46*********************************************************************************************************************************/
47
48/** Number of milliseconds we wait for new data to arrive when a new packet was detected. */
49#define DBGC_KD_RECV_TIMEOUT_MS UINT32_C(1000)
50
51/** NT status code - Success. */
52#define NTSTATUS_SUCCESS 0
53/** NT status code - operation unsuccesful. */
54#define NTSTATUS_UNSUCCESSFUL UINT32_C(0xc0000001)
55/** NT status code - operation not implemented. */
56#define NTSTATUS_NOT_IMPLEMENTED UINT32_C(0xc0000002)
57
58/** Offset where the KD version block pointer is stored in the KPCR.
59 * From: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kprcb/amd64.htm */
60#define KD_KPCR_VERSION_BLOCK_ADDR_OFF 0x34
61
62/*********************************************************************************************************************************
63* Structures and Typedefs *
64*********************************************************************************************************************************/
65
66/**
67 * KD packet header as sent over the wire.
68 */
69typedef struct KDPACKETHDR
70{
71 /** Packet signature (leader) - defines the type of packet. */
72 uint32_t u32Signature;
73 /** Packet (sub) type. */
74 uint16_t u16SubType;
75 /** Size of the packet body in bytes.*/
76 uint16_t cbBody;
77 /** Packet ID. */
78 uint32_t idPacket;
79 /** Checksum of the packet body. */
80 uint32_t u32ChkSum;
81} KDPACKETHDR;
82AssertCompileSize(KDPACKETHDR, 16);
83/** Pointer to a packet header. */
84typedef KDPACKETHDR *PKDPACKETHDR;
85/** Pointer to a const packet header. */
86typedef const KDPACKETHDR *PCKDPACKETHDR;
87
88/** Signature for a data packet. */
89#define KD_PACKET_HDR_SIGNATURE_DATA UINT32_C(0x30303030)
90/** First byte for a data packet header. */
91#define KD_PACKET_HDR_SIGNATURE_DATA_BYTE 0x30
92/** Signature for a control packet. */
93#define KD_PACKET_HDR_SIGNATURE_CONTROL UINT32_C(0x69696969)
94/** First byte for a control packet header. */
95#define KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE 0x69
96/** Signature for a breakin packet. */
97#define KD_PACKET_HDR_SIGNATURE_BREAKIN UINT32_C(0x62626262)
98/** First byte for a breakin packet header. */
99#define KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE 0x62
100
101/** @name Packet sub types.
102 * @{ */
103#define KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32 UINT16_C(1)
104#define KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE UINT16_C(2)
105#define KD_PACKET_HDR_SUB_TYPE_DEBUG_IO UINT16_C(3)
106#define KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE UINT16_C(4)
107#define KD_PACKET_HDR_SUB_TYPE_RESEND UINT16_C(5)
108#define KD_PACKET_HDR_SUB_TYPE_RESET UINT16_C(6)
109#define KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64 UINT16_C(7)
110#define KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN UINT16_C(8)
111#define KD_PACKET_HDR_SUB_TYPE_TRACE_IO UINT16_C(9)
112#define KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST UINT16_C(10)
113#define KD_PACKET_HDR_SUB_TYPE_FILE_IO UINT16_C(11)
114#define KD_PACKET_HDR_SUB_TYPE_MAX UINT16_C(12)
115/** @} */
116
117/** Initial packet ID value. */
118#define KD_PACKET_HDR_ID_INITIAL UINT32_C(0x80800800)
119/** Packet ID value after a resync. */
120#define KD_PACKET_HDR_ID_RESET UINT32_C(0x80800000)
121
122/** Trailing byte of a packet. */
123#define KD_PACKET_TRAILING_BYTE 0xaa
124
125
126/** Maximum number of parameters in the exception record. */
127#define KDPACKETEXCP_PARMS_MAX 15
128
129/**
130 * 64bit exception record.
131 */
132typedef struct KDPACKETEXCP64
133{
134 /** The exception code identifying the excpetion. */
135 uint32_t u32ExcpCode;
136 /** Flags associated with the exception. */
137 uint32_t u32ExcpFlags;
138 /** Pointer to a chained exception record. */
139 uint64_t u64PtrExcpRecNested;
140 /** Address where the exception occurred. */
141 uint64_t u64PtrExcpAddr;
142 /** Number of parameters in the exception information array. */
143 uint32_t cExcpParms;
144 /** Alignment. */
145 uint32_t u32Alignment;
146 /** Exception parameters array. */
147 uint64_t au64ExcpParms[KDPACKETEXCP_PARMS_MAX];
148} KDPACKETEXCP64;
149AssertCompileSize(KDPACKETEXCP64, 152);
150/** Pointer to an exception record. */
151typedef KDPACKETEXCP64 *PKDPACKETEXCP64;
152/** Pointer to a const exception record. */
153typedef const KDPACKETEXCP64 *PCKDPACKETEXCP64;
154
155
156/**
157 * amd64 NT context structure.
158 */
159typedef struct NTCONTEXT64
160{
161 /** The P[1-6]Home members. */
162 uint64_t au64PHome[6];
163 /** Context flags indicating the valid bits, see NTCONTEXT_F_XXX. */
164 uint32_t fContext;
165 /** MXCSR register. */
166 uint32_t u32RegMxCsr;
167 /** CS selector. */
168 uint16_t u16SegCs;
169 /** DS selector. */
170 uint16_t u16SegDs;
171 /** ES selector. */
172 uint16_t u16SegEs;
173 /** FS selector. */
174 uint16_t u16SegFs;
175 /** GS selector. */
176 uint16_t u16SegGs;
177 /** SS selector. */
178 uint16_t u16SegSs;
179 /** EFlags register. */
180 uint32_t u32RegEflags;
181 /** DR0 register. */
182 uint64_t u64RegDr0;
183 /** DR1 register. */
184 uint64_t u64RegDr1;
185 /** DR2 register. */
186 uint64_t u64RegDr2;
187 /** DR3 register. */
188 uint64_t u64RegDr3;
189 /** DR6 register. */
190 uint64_t u64RegDr6;
191 /** DR7 register. */
192 uint64_t u64RegDr7;
193 /** RAX register. */
194 uint64_t u64RegRax;
195 /** RCX register. */
196 uint64_t u64RegRcx;
197 /** RDX register. */
198 uint64_t u64RegRdx;
199 /** RBX register. */
200 uint64_t u64RegRbx;
201 /** RSP register. */
202 uint64_t u64RegRsp;
203 /** RBP register. */
204 uint64_t u64RegRbp;
205 /** RSI register. */
206 uint64_t u64RegRsi;
207 /** RDI register. */
208 uint64_t u64RegRdi;
209 /** R8 register. */
210 uint64_t u64RegR8;
211 /** R9 register. */
212 uint64_t u64RegR9;
213 /** R10 register. */
214 uint64_t u64RegR10;
215 /** R11 register. */
216 uint64_t u64RegR11;
217 /** R12 register. */
218 uint64_t u64RegR12;
219 /** R13 register. */
220 uint64_t u64RegR13;
221 /** R14 register. */
222 uint64_t u64RegR14;
223 /** R15 register. */
224 uint64_t u64RegR15;
225 /** RIP register. */
226 uint64_t u64RegRip;
227 /** Extended floating point save area. */
228 X86FXSTATE FxSave;
229 /** AVX(?) vector registers. */
230 RTUINT128U aRegsVec[26];
231 /** Vector control register. */
232 uint64_t u64RegVecCtrl;
233 /** Debug control. */
234 uint64_t u64DbgCtrl;
235 /** @todo */
236 uint64_t u64LastBrToRip;
237 uint64_t u64LastBrFromRip;
238 uint64_t u64LastExcpToRip;
239 uint64_t u64LastExcpFromRip;
240} NTCONTEXT64;
241AssertCompileSize(NTCONTEXT64, 1232);
242AssertCompileMemberOffset(NTCONTEXT64, FxSave, 0x100);
243AssertCompileMemberOffset(NTCONTEXT64, aRegsVec, 0x300);
244/** Pointer to an amd64 NT context. */
245typedef NTCONTEXT64 *PNTCONTEXT64;
246/** Pointer to a const amd64 NT context. */
247typedef const NTCONTEXT64 *PCNTCONTEXT64;
248
249
250/**
251 * [GI]DT descriptor.
252 */
253typedef struct NTKCONTEXTDESC64
254{
255 /** Alignment. */
256 uint16_t au16Alignment[3];
257 /** Limit. */
258 uint16_t u16Limit;
259 /** Base address. */
260 uint64_t u64PtrBase;
261} NTKCONTEXTDESC64;
262AssertCompileSize(NTKCONTEXTDESC64, 2 * 8);
263/** Pointer to an amd64 NT context. */
264typedef NTKCONTEXTDESC64 *PNTKCONTEXTDESC64;
265/** Pointer to a const amd64 NT context. */
266typedef const NTKCONTEXTDESC64 *PCNTKCONTEXTDESC64;
267
268
269/**
270 * Kernel context as queried by KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE
271 */
272typedef struct NTKCONTEXT64
273{
274 /** CR0 register. */
275 uint64_t u64RegCr0;
276 /** CR2 register. */
277 uint64_t u64RegCr2;
278 /** CR3 register. */
279 uint64_t u64RegCr3;
280 /** CR4 register. */
281 uint64_t u64RegCr4;
282 /** DR0 register. */
283 uint64_t u64RegDr0;
284 /** DR1 register. */
285 uint64_t u64RegDr1;
286 /** DR2 register. */
287 uint64_t u64RegDr2;
288 /** DR3 register. */
289 uint64_t u64RegDr3;
290 /** DR6 register. */
291 uint64_t u64RegDr6;
292 /** DR7 register. */
293 uint64_t u64RegDr7;
294 /** GDTR. */
295 NTKCONTEXTDESC64 Gdtr;
296 /** IDTR. */
297 NTKCONTEXTDESC64 Idtr;
298 /** TR register. */
299 uint16_t u16RegTr;
300 /** LDTR register. */
301 uint16_t u16RegLdtr;
302 /** MXCSR register. */
303 uint32_t u32RegMxCsr;
304 /** Debug control. */
305 uint64_t u64DbgCtrl;
306 /** @todo */
307 uint64_t u64LastBrToRip;
308 uint64_t u64LastBrFromRip;
309 uint64_t u64LastExcpToRip;
310 uint64_t u64LastExcpFromRip;
311 /** CR8 register. */
312 uint64_t u64RegCr8;
313 /** GS base MSR register. */
314 uint64_t u64MsrGsBase;
315 /** Kernel GS base MSR register. */
316 uint64_t u64MsrKernelGsBase;
317 /** STAR MSR register. */
318 uint64_t u64MsrStar;
319 /** LSTAR MSR register. */
320 uint64_t u64MsrLstar;
321 /** CSTAR MSR register. */
322 uint64_t u64MsrCstar;
323 /** SFMASK MSR register. */
324 uint64_t u64MsrSfMask;
325 /** XCR0 register. */
326 uint64_t u64RegXcr0;
327 /** Standard context. */
328 NTCONTEXT64 Ctx;
329} NTKCONTEXT64;
330AssertCompileMemberOffset(NTKCONTEXT64, Ctx, 224);
331/** Pointer to an amd64 NT context. */
332typedef NTKCONTEXT64 *PNTKCONTEXT64;
333/** Pointer to a const amd64 NT context. */
334typedef const NTKCONTEXT64 *PCNTKCONTEXT64;
335
336
337/** x86 context. */
338#define NTCONTEXT_F_X86 UINT32_C(0x00010000)
339/** AMD64 context. */
340#define NTCONTEXT_F_AMD64 UINT32_C(0x00100000)
341/** Control registers valid (CS, (R)SP, (R)IP, FLAGS and BP). */
342#define NTCONTEXT_F_CONTROL RT_BIT_32(0)
343/** Integer registers valid. */
344#define NTCONTEXT_F_INTEGER RT_BIT_32(1)
345/** Segment registers valid. */
346#define NTCONTEXT_F_SEGMENTS RT_BIT_32(2)
347/** Floating point registers valid. */
348#define NTCONTEXT_F_FLOATING_POINT RT_BIT_32(3)
349/** Debug registers valid. */
350#define NTCONTEXT_F_DEBUG RT_BIT_32(4)
351/** Extended registers valid (x86 only). */
352#define NTCONTEXT_F_EXTENDED RT_BIT_32(5)
353/** Full x86 context valid. */
354#define NTCONTEXT32_F_FULL (NTCONTEXT_F_X86 | NTCONTEXT_F_CONTROL | NTCONTEXT_F_INTEGER | NTCONTEXT_F_SEGMENTS)
355/** Full amd64 context valid. */
356#define NTCONTEXT64_F_FULL (NTCONTEXT_F_AMD64 | NTCONTEXT_F_CONTROL | NTCONTEXT_F_INTEGER | NTCONTEXT_F_SEGMENTS)
357
358
359/**
360 * 32bit exception record.
361 */
362typedef struct KDPACKETEXCP32
363{
364 /** The exception code identifying the excpetion. */
365 uint32_t u32ExcpCode;
366 /** Flags associated with the exception. */
367 uint32_t u32ExcpFlags;
368 /** Pointer to a chained exception record. */
369 uint32_t u32PtrExcpRecNested;
370 /** Address where the exception occurred. */
371 uint32_t u32PtrExcpAddr;
372 /** Number of parameters in the exception information array. */
373 uint32_t cExcpParms;
374 /** Exception parameters array. */
375 uint32_t au32ExcpParms[KDPACKETEXCP_PARMS_MAX];
376} KDPACKETEXCP32;
377AssertCompileSize(KDPACKETEXCP32, 80);
378/** Pointer to an exception record. */
379typedef KDPACKETEXCP32 *PKDPACKETEXCP32;
380/** Pointer to a const exception record. */
381typedef const KDPACKETEXCP32 *PCKDPACKETEXCP32;
382
383
384/** @name Exception codes.
385 * @{ */
386/** A breakpoint was hit. */
387#define KD_PACKET_EXCP_CODE_BKPT UINT32_C(0x80000003)
388/** An instruction was single stepped. */
389#define KD_PACKET_EXCP_CODE_SINGLE_STEP UINT32_C(0x80000004)
390/** @} */
391
392
393/** Maximum number of bytes in the instruction stream. */
394#define KD_PACKET_CTRL_REPORT_INSN_STREAM_MAX 16
395
396/**
397 * 64bit control report record.
398 */
399typedef struct KDPACKETCTRLREPORT64
400{
401 /** Value of DR6. */
402 uint64_t u64RegDr6;
403 /** Value of DR7. */
404 uint64_t u64RegDr7;
405 /** EFLAGS. */
406 uint32_t u32RegEflags;
407 /** Number of instruction bytes in the instruction stream. */
408 uint16_t cbInsnStream;
409 /** Report flags. */
410 uint16_t fFlags;
411 /** The instruction stream. */
412 uint8_t abInsn[KD_PACKET_CTRL_REPORT_INSN_STREAM_MAX];
413 /** CS selector. */
414 uint16_t u16SegCs;
415 /** DS selector. */
416 uint16_t u16SegDs;
417 /** ES selector. */
418 uint16_t u16SegEs;
419 /** FS selector. */
420 uint16_t u16SegFs;
421} KDPACKETCTRLREPORT64;
422AssertCompileSize(KDPACKETCTRLREPORT64, 2 * 8 + 4 + 2 * 2 + 16 + 4 * 2);
423/** Pointer to a control report record. */
424typedef KDPACKETCTRLREPORT64 *PKDPACKETCTRLREPORT64;
425/** Pointer to a const control report record. */
426typedef const KDPACKETCTRLREPORT64 *PCKDPACKETCTRLREPORT64;
427
428
429/**
430 * 64bit state change packet body.
431 */
432typedef struct KDPACKETSTATECHANGE64
433{
434 /** The new state. */
435 uint32_t u32StateNew;
436 /** The processor level. */
437 uint16_t u16CpuLvl;
438 /** The processor ID generating the state change. */
439 uint16_t idCpu;
440 /** Number of processors in the system. */
441 uint32_t cCpus;
442 /** Alignment. */
443 uint32_t u32Alignment;
444 /** The thread ID currently executing when the state change occurred. */
445 uint64_t idThread;
446 /** Program counter of the thread. */
447 uint64_t u64RipThread;
448 /** Data based on the state. */
449 union
450 {
451 /** Exception occurred data. */
452 struct
453 {
454 /** The exception record. */
455 KDPACKETEXCP64 ExcpRec;
456 /** First chance(?). */
457 uint32_t u32FirstChance;
458 } Exception;
459 } u;
460 /** The control report */
461 union
462 {
463 /** AMD64 control report. */
464 KDPACKETCTRLREPORT64 Amd64;
465 } uCtrlReport;
466} KDPACKETSTATECHANGE64;
467//AssertCompileSize(KDPACKETSTATECHANGE64, 4 + 2 * 2 + 2 * 4 + 2 * 8 + sizeof(KDPACKETEXCP64) + 4 + sizeof(KDPACKETCTRLREPORT64));
468/** Pointer to a 64bit state change packet body. */
469typedef KDPACKETSTATECHANGE64 *PKDPACKETSTATECHANGE64;
470/** Pointer to a const 64bit state change packet body. */
471typedef const KDPACKETSTATECHANGE64 *PCKDPACKETSTATECHANGE64;
472
473
474/** @name State change state types.
475 * @{ */
476/** Minimum state change type. */
477#define KD_PACKET_STATE_CHANGE_MIN UINT32_C(0x00003030)
478/** An exception occured. */
479#define KD_PACKET_STATE_CHANGE_EXCEPTION KD_PACKET_STATE_CHANGE_MIN
480/** Symbols were loaded(?). */
481#define KD_PACKET_STATE_CHANGE_LOAD_SYMBOLS UINT32_C(0x00003031)
482/** Command string (custom command was executed?). */
483#define KD_PACKET_STATE_CHANGE_CMD_STRING UINT32_C(0x00003032)
484/** Maximum state change type (exclusive). */
485#define KD_PACKET_STATE_CHANGE_MAX UINT32_C(0x00003033)
486/** @} */
487
488
489/**
490 * 64bit get version manipulate payload.
491 */
492typedef struct KDPACKETMANIPULATE_GETVERSION64
493{
494 /** Major version. */
495 uint16_t u16VersMaj;
496 /** Minor version. */
497 uint16_t u16VersMin;
498 /** Protocol version. */
499 uint8_t u8VersProtocol;
500 /** KD secondary version. */
501 uint8_t u8VersKdSecondary;
502 /** Flags. */
503 uint16_t fFlags;
504 /** Machine type. */
505 uint16_t u16MachineType;
506 /** Maximum packet type. */
507 uint8_t u8MaxPktType;
508 /** Maximum state change */
509 uint8_t u8MaxStateChange;
510 /** Maximum manipulate request ID. */
511 uint8_t u8MaxManipulate;
512 /** Some simulation flag. */
513 uint8_t u8Simulation;
514 /** Padding. */
515 uint16_t u16Padding;
516 /** Kernel base. */
517 uint64_t u64PtrKernBase;
518 /** Pointer of the loaded module list head. */
519 uint64_t u64PtrPsLoadedModuleList;
520 /** Pointer of the debugger data list. */
521 uint64_t u64PtrDebuggerDataList;
522} KDPACKETMANIPULATE_GETVERSION64;
523AssertCompileSize(KDPACKETMANIPULATE_GETVERSION64, 40);
524/** Pointer to a 64bit get version manipulate payload. */
525typedef KDPACKETMANIPULATE_GETVERSION64 *PKDPACKETMANIPULATE_GETVERSION64;
526/** Pointer to a const 64bit get version manipulate payload. */
527typedef const KDPACKETMANIPULATE_GETVERSION64 *PCKDPACKETMANIPULATE_GETVERSION64;
528
529
530/** @name Get version flags.
531 * @{ */
532/** Flag whether this is a multi processor kernel. */
533#define KD_PACKET_MANIPULATE64_GET_VERSION_F_MP RT_BIT_32(0)
534/** Flag whether the pointer is 64bit. */
535#define KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64 RT_BIT_32(2)
536/** @} */
537
538
539/**
540 * 64bit memory transfer manipulate payload.
541 */
542typedef struct KDPACKETMANIPULATE_XFERMEM64
543{
544 /** Target base address. */
545 uint64_t u64PtrTarget;
546 /** Requested number of bytes to transfer*/
547 uint32_t cbXferReq;
548 /** Number of bytes actually transferred (response). */
549 uint32_t cbXfered;
550 /** Some padding?. */
551 uint64_t au64Pad[3];
552} KDPACKETMANIPULATE_XFERMEM64;
553AssertCompileSize(KDPACKETMANIPULATE_XFERMEM64, 40);
554/** Pointer to a 64bit memory transfer manipulate payload. */
555typedef KDPACKETMANIPULATE_XFERMEM64 *PKDPACKETMANIPULATE_XFERMEM64;
556/** Pointer to a const 64bit memory transfer manipulate payload. */
557typedef const KDPACKETMANIPULATE_XFERMEM64 *PCKDPACKETMANIPULATE_XFERMEM64;
558
559
560/**
561 * 64bit control space transfer manipulate payload.
562 *
563 * @note Same layout as the memory transfer but the pointer has a different meaning so
564 * we moved it into a separate request structure.
565 */
566typedef struct KDPACKETMANIPULATE_XFERCTRLSPACE64
567{
568 /** Identifier of the item to transfer in the control space. */
569 uint64_t u64IdXfer;
570 /** Requested number of bytes to transfer*/
571 uint32_t cbXferReq;
572 /** Number of bytes actually transferred (response). */
573 uint32_t cbXfered;
574 /** Some padding?. */
575 uint64_t au64Pad[3];
576} KDPACKETMANIPULATE_XFERCTRLSPACE64;
577AssertCompileSize(KDPACKETMANIPULATE_XFERCTRLSPACE64, 40);
578/** Pointer to a 64bit memory transfer manipulate payload. */
579typedef KDPACKETMANIPULATE_XFERCTRLSPACE64 *PKDPACKETMANIPULATE_XFERCTRLSPACE64;
580/** Pointer to a const 64bit memory transfer manipulate payload. */
581typedef const KDPACKETMANIPULATE_XFERCTRLSPACE64 *PCKDPACKETMANIPULATE_XFERCTRLSPACE64;
582
583
584/** @name Known control space identifiers.
585 * @{ */
586/** Read/Write KPCR address. */
587#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR UINT64_C(0)
588/** Read/Write KPCRB address. */
589#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB UINT64_C(1)
590/** Read/Write Kernel context. */
591#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX UINT64_C(2)
592/** Read/Write current kernel thread. */
593#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD UINT64_C(3)
594/** @} */
595
596
597/**
598 * 64bit restore breakpoint manipulate payload.
599 */
600typedef struct KDPACKETMANIPULATE_RESTOREBKPT64
601{
602 /** The breakpoint handle to restore. */
603 uint32_t u32HndBkpt;
604 /** Blows up the request to the required size. */
605 uint8_t abPad[36];
606} KDPACKETMANIPULATE_RESTOREBKPT64;
607AssertCompileSize(KDPACKETMANIPULATE_RESTOREBKPT64, 40);
608/** Pointer to a 64bit restore breakpoint manipulate payload. */
609typedef KDPACKETMANIPULATE_RESTOREBKPT64 *PKDPACKETMANIPULATE_RESTOREBKPT64;
610/** Pointer to a const 64bit restore breakpoint manipulate payload. */
611typedef const KDPACKETMANIPULATE_RESTOREBKPT64 *PCKDPACKETMANIPULATE_RESTOREBKPT64;
612
613
614/**
615 * 64bit write breakpoint manipulate payload.
616 */
617typedef struct KDPACKETMANIPULATE_WRITEBKPT64
618{
619 /** Where to write the breakpoint. */
620 uint64_t u64PtrBkpt;
621 /** The breakpoint handle returned in the response. */
622 uint32_t u32HndBkpt;
623 /** Blows up the request to the required size. */
624 uint8_t abPad[28];
625} KDPACKETMANIPULATE_WRITEBKPT64;
626AssertCompileSize(KDPACKETMANIPULATE_WRITEBKPT64, 40);
627/** Pointer to a 64bit write breakpoint manipulate payload. */
628typedef KDPACKETMANIPULATE_WRITEBKPT64 *PKDPACKETMANIPULATE_WRITEBKPT64;
629/** Pointer to a const 64bit write breakpoint manipulate payload. */
630typedef const KDPACKETMANIPULATE_WRITEBKPT64 *PCKDPACKETMANIPULATE_WRITEBKPT64;
631
632
633/**
634 * Context extended manipulate payload.
635 */
636typedef struct KDPACKETMANIPULATE_CONTEXTEX
637{
638 /** Where to start copying the context. */
639 uint32_t offStart;
640 /** Number of bytes to transfer. */
641 uint32_t cbXfer;
642 /** Number of bytes actually transfered. */
643 uint32_t cbXfered;
644 /** Blows up the request to the required size. */
645 uint8_t abPad[28];
646} KDPACKETMANIPULATE_CONTEXTEX;
647AssertCompileSize(KDPACKETMANIPULATE_CONTEXTEX, 40);
648/** Pointer to a context extended manipulate payload. */
649typedef KDPACKETMANIPULATE_CONTEXTEX *PKDPACKETMANIPULATE_CONTEXTEX;
650/** Pointer to a const context extended manipulate payload. */
651typedef const KDPACKETMANIPULATE_CONTEXTEX *PCKDPACKETMANIPULATE_CONTEXTEX;
652
653
654/**
655 * Continue manipulate payload.
656 */
657typedef struct KDPACKETMANIPULATE_CONTINUE
658{
659 /** Continue (status?). */
660 uint32_t u32NtContSts;
661 /** Blows up the request to the required size. */
662 uint8_t abPad[36];
663} KDPACKETMANIPULATE_CONTINUE;
664AssertCompileSize(KDPACKETMANIPULATE_CONTINUE, 40);
665/** Pointer to a continue manipulate payload. */
666typedef KDPACKETMANIPULATE_CONTINUE *PKDPACKETMANIPULATE_CONTINUE;
667/** Pointer to a const continue manipulate payload. */
668typedef const KDPACKETMANIPULATE_CONTINUE *PCKDPACKETMANIPULATE_CONTINUE;
669
670
671/**
672 * Continue 2 manipulate payload.
673 */
674typedef struct KDPACKETMANIPULATE_CONTINUE2
675{
676 /** Continue (status?). */
677 uint32_t u32NtContSts;
678 /** Trace flag. */
679 uint32_t fTrace;
680 /** Bitsize dependent data. */
681 union
682 {
683 /** 32bit. */
684 struct
685 {
686 /** DR7 value to continue with. */
687 uint32_t u32RegDr7;
688 /** @todo (?) */
689 uint32_t u32SymCurStart;
690 uint32_t u32SymCurEnd;
691 } x86;
692 /** 64bit. */
693 struct
694 {
695 /** DR7 value to continue with. */
696 uint64_t u64RegDr7;
697 /** @todo (?) */
698 uint64_t u64SymCurStart;
699 uint64_t u64SymCurEnd;
700 } amd64;
701 } u;
702 /** Blows up the request to the required size. */
703 uint8_t abPad[8];
704} KDPACKETMANIPULATE_CONTINUE2;
705AssertCompileSize(KDPACKETMANIPULATE_CONTINUE2, 40);
706/** Pointer to a continue 2 manipulate payload. */
707typedef KDPACKETMANIPULATE_CONTINUE2 *PKDPACKETMANIPULATE_CONTINUE2;
708/** Pointer to a const continue 2 manipulate payload. */
709typedef const KDPACKETMANIPULATE_CONTINUE2 *PCKDPACKETMANIPULATE_CONTINUE2;
710
711
712/**
713 * Set context manipulate payload.
714 */
715typedef struct KDPACKETMANIPULATE_SETCONTEXT
716{
717 /** Continue (status?). */
718 uint32_t u32CtxFlags;
719 /** Blows up the request to the required size. */
720 uint8_t abPad[36];
721} KDPACKETMANIPULATE_SETCONTEXT;
722AssertCompileSize(KDPACKETMANIPULATE_SETCONTEXT, 40);
723/** Pointer to a set context manipulate payload. */
724typedef KDPACKETMANIPULATE_SETCONTEXT *PKDPACKETMANIPULATE_SETCONTEXT;
725/** Pointer to a const set context manipulate payload. */
726typedef const KDPACKETMANIPULATE_SETCONTEXT *PCKDPACKETMANIPULATE_SETCONTEXT;
727
728
729/**
730 * Manipulate request packet header (Same for 32bit and 64bit).
731 */
732typedef struct KDPACKETMANIPULATEHDR
733{
734 /** The request to execute. */
735 uint32_t idReq;
736 /** The processor level to execute the request on. */
737 uint16_t u16CpuLvl;
738 /** The processor ID to execute the request on. */
739 uint16_t idCpu;
740 /** Return status code. */
741 uint32_t u32NtStatus;
742 /** Alignment. */
743 uint32_t u32Alignment;
744} KDPACKETMANIPULATEHDR;
745AssertCompileSize(KDPACKETMANIPULATEHDR, 3 * 4 + 2 * 2);
746/** Pointer to a manipulate request packet header. */
747typedef KDPACKETMANIPULATEHDR *PKDPACKETMANIPULATEHDR;
748/** Pointer to a const manipulate request packet header. */
749typedef const KDPACKETMANIPULATEHDR *PCPKDPACKETMANIPULATEHDR;
750
751
752/**
753 * 64bit manipulate state request packet.
754 */
755typedef struct KDPACKETMANIPULATE64
756{
757 /** Header. */
758 KDPACKETMANIPULATEHDR Hdr;
759 /** Request payloads. */
760 union
761 {
762 /** Get Version. */
763 KDPACKETMANIPULATE_GETVERSION64 GetVersion;
764 /** Read/Write memory. */
765 KDPACKETMANIPULATE_XFERMEM64 XferMem;
766 /** Continue. */
767 KDPACKETMANIPULATE_CONTINUE Continue;
768 /** Continue2. */
769 KDPACKETMANIPULATE_CONTINUE2 Continue2;
770 /** Set context. */
771 KDPACKETMANIPULATE_SETCONTEXT SetContext;
772 /** Read/Write control space. */
773 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace;
774 /** Restore breakpoint. */
775 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt;
776 /** Write breakpoint. */
777 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt;
778 /** Context extended. */
779 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
780 } u;
781} KDPACKETMANIPULATE64;
782AssertCompileSize(KDPACKETMANIPULATE64, 16 + 40);
783/** Pointer to a 64bit manipulate state request packet. */
784typedef KDPACKETMANIPULATE64 *PKDPACKETMANIPULATE64;
785/** Pointer to a const 64bit manipulate state request packet. */
786typedef const KDPACKETMANIPULATE64 *PCKDPACKETMANIPULATE64;
787
788/** @name Manipulate requests.
789 * @{ */
790/** Minimum available request. */
791#define KD_PACKET_MANIPULATE_REQ_MIN UINT32_C(0x00003130)
792/** Read virtual memory request. */
793#define KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM KD_PACKET_MANIPULATE_REQ_MIN
794/** Write virtual memory request. */
795#define KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM UINT32_C(0x00003131)
796/** Get context request. */
797#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT UINT32_C(0x00003132)
798/** Set context request. */
799#define KD_PACKET_MANIPULATE_REQ_SET_CONTEXT UINT32_C(0x00003133)
800/** Write breakpoint request. */
801#define KD_PACKET_MANIPULATE_REQ_WRITE_BKPT UINT32_C(0x00003134)
802/** Restore breakpoint request. */
803#define KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT UINT32_C(0x00003135)
804/** Continue request. */
805#define KD_PACKET_MANIPULATE_REQ_CONTINUE UINT32_C(0x00003136)
806/** Read control space request. */
807#define KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE UINT32_C(0x00003137)
808/** Write control space request. */
809#define KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE UINT32_C(0x00003138)
810/** Read I/O space request. */
811#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE UINT32_C(0x00003139)
812/** Write I/O space request. */
813#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE UINT32_C(0x0000313a)
814/** Reboot request. */
815#define KD_PACKET_MANIPULATE_REQ_REBOOT UINT32_C(0x0000313b)
816/** continue 2nd version request. */
817#define KD_PACKET_MANIPULATE_REQ_CONTINUE2 UINT32_C(0x0000313c)
818/** Read physical memory request. */
819#define KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM UINT32_C(0x0000313d)
820/** Write physical memory request. */
821#define KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM UINT32_C(0x0000313e)
822/** Query special calls request. */
823#define KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS UINT32_C(0x0000313f)
824/** Set special calls request. */
825#define KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS UINT32_C(0x00003140)
826/** Clear special calls request. */
827#define KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS UINT32_C(0x00003141)
828/** Set internal breakpoint request. */
829#define KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT UINT32_C(0x00003142)
830/** Get internal breakpoint request. */
831#define KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT UINT32_C(0x00003143)
832/** Read I/O space extended request. */
833#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX UINT32_C(0x00003144)
834/** Write I/O space extended request. */
835#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX UINT32_C(0x00003145)
836/** Get version request. */
837#define KD_PACKET_MANIPULATE_REQ_GET_VERSION UINT32_C(0x00003146)
838/** @todo */
839/** Clear all internal breakpoints request. */
840#define KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT UINT32_C(0x0000315a)
841/** @todo */
842/** Get context extended request. */
843#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX UINT32_C(0x0000315f)
844/** @todo */
845/** Maximum available request (exclusive). */
846#define KD_PACKET_MANIPULATE_REQ_MAX UINT32_C(0x00003161)
847/** @} */
848
849/**
850 * KD stub receive state.
851 */
852typedef enum KDRECVSTATE
853{
854 /** Invalid state. */
855 KDRECVSTATE_INVALID = 0,
856 /** Receiving the first byte of the packet header. */
857 KDRECVSTATE_PACKET_HDR_FIRST_BYTE,
858 /** Receiving the second byte of the packet header. */
859 KDRECVSTATE_PACKET_HDR_SECOND_BYTE,
860 /** Receiving the header. */
861 KDRECVSTATE_PACKET_HDR,
862 /** Receiving the packet body. */
863 KDRECVSTATE_PACKET_BODY,
864 /** Receiving the trailing byte. */
865 KDRECVSTATE_PACKET_TRAILER,
866 /** Blow up the enum to 32bits for easier alignment of members in structs. */
867 KDRECVSTATE_32BIT_HACK = 0x7fffffff
868} KDRECVSTATE;
869
870
871/**
872 * KD context data.
873 */
874typedef struct KDCTX
875{
876 /** Internal debugger console data. */
877 DBGC Dbgc;
878 /** Number of bytes received left for the current state. */
879 size_t cbRecvLeft;
880 /** Pointer where to write the next received data. */
881 uint8_t *pbRecv;
882 /** The current state when receiving a new packet. */
883 KDRECVSTATE enmState;
884 /** The timeout waiting for new data. */
885 RTMSINTERVAL msRecvTimeout;
886 /** Timestamp when we last received data from the remote end. */
887 uint64_t tsRecvLast;
888 /** Packet header being received. */
889 union
890 {
891 KDPACKETHDR Fields;
892 uint8_t ab[16];
893 } PktHdr;
894 /** The next packet ID to send. */
895 uint32_t idPktNext;
896 /** Offset into the body receive buffer. */
897 size_t offBodyRecv;
898 /** Body data. */
899 uint8_t abBody[_4K];
900 /** The trailer byte storage. */
901 uint8_t bTrailer;
902 /** Flag whether a breakin packet was received since the last time it was reset. */
903 bool fBreakinRecv;
904
905 /** Pointer to the OS digger WinNt interface if a matching guest was detected. */
906 PDBGFOSIWINNT pIfWinNt;
907} KDCTX;
908/** Pointer to the KD context data. */
909typedef KDCTX *PKDCTX;
910/** Pointer to const KD context data. */
911typedef const KDCTX *PCKDCTX;
912/** Pointer to a KD context data pointer. */
913typedef PKDCTX *PPKDCTX;
914
915
916/*********************************************************************************************************************************
917* Internal Functions *
918*********************************************************************************************************************************/
919
920
921#ifdef LOG_ENABLED
922/**
923 * Returns a human readable string of the given packet sub type.
924 *
925 * @returns Pointer to sub type string.
926 * @param u16SubType The sub type to convert to a string.
927 */
928static const char *dbgcKdPktDumpSubTypeToStr(uint16_t u16SubType)
929{
930 switch (u16SubType)
931 {
932 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32: return "StateChange32";
933 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE: return "Manipulate";
934 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO: return "DebugIo";
935 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE: return "Ack";
936 case KD_PACKET_HDR_SUB_TYPE_RESEND: return "Resend";
937 case KD_PACKET_HDR_SUB_TYPE_RESET: return "Reset";
938 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64: return "StateChange64";
939 case KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN: return "PollBreakin";
940 case KD_PACKET_HDR_SUB_TYPE_TRACE_IO: return "TraceIo";
941 case KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST: return "ControlRequest";
942 case KD_PACKET_HDR_SUB_TYPE_FILE_IO: return "FileIo";
943 default: break;
944 }
945
946 return "<UNKNOWN>";
947}
948
949
950/**
951 * Returns a human readable string of the given manipulate request ID.
952 *
953 * @returns nothing.
954 * @param idReq Request ID (API number in KD speak).
955 */
956static const char *dbgcKdPktDumpManipulateReqToStr(uint32_t idReq)
957{
958 switch (idReq)
959 {
960 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM: return "ReadVirtMem";
961 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM: return "WriteVirtMem";
962 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT: return "GetContext";
963 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT: return "SetContext";
964 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT: return "WriteBkpt";
965 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT: return "RestoreBkpt";
966 case KD_PACKET_MANIPULATE_REQ_CONTINUE: return "Continue";
967 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE: return "ReadCtrlSpace";
968 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE: return "WriteCtrlSpace";
969 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE: return "ReadIoSpace";
970 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE: return "WriteIoSpace";
971 case KD_PACKET_MANIPULATE_REQ_REBOOT: return "Reboot";
972 case KD_PACKET_MANIPULATE_REQ_CONTINUE2: return "Continue2";
973 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM: return "ReadPhysMem";
974 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM: return "WritePhysMem";
975 case KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS: return "QuerySpecCalls";
976 case KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS: return "SetSpecCalls";
977 case KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS: return "ClrSpecCalls";
978 case KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT: return "SetIntBkpt";
979 case KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT: return "GetIntBkpt";
980 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX: return "ReadIoSpaceEx";
981 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX: return "WriteIoSpaceEx";
982 case KD_PACKET_MANIPULATE_REQ_GET_VERSION: return "GetVersion";
983 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT: return "ClrAllIntBkpt";
984 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX: return "GetContextEx";
985 default: break;
986 }
987
988 return "<UNKNOWN>";
989}
990
991
992/**
993 * Dumps the content of a manipulate packet.
994 *
995 * @returns nothing.
996 * @param pSgBuf S/G buffer containing the manipulate packet payload.
997 */
998static void dbgcKdPktDumpManipulate(PRTSGBUF pSgBuf)
999{
1000 KDPACKETMANIPULATEHDR Hdr;
1001 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, &Hdr, sizeof(Hdr));
1002
1003 if (cbCopied == sizeof(Hdr))
1004 {
1005 const char *pszReq = dbgcKdPktDumpManipulateReqToStr(Hdr.idReq);
1006
1007 Log3((" MANIPULATE(%#x (%s), %#x, %u, %#x)\n",
1008 Hdr.idReq, pszReq, Hdr.u16CpuLvl, Hdr.idCpu, Hdr.u32NtStatus));
1009
1010 switch (Hdr.idReq)
1011 {
1012 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
1013 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
1014 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
1015 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
1016 {
1017 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1018 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferMem64, sizeof(XferMem64));
1019 if (cbCopied == sizeof(XferMem64))
1020 {
1021 Log3((" u64PtrTarget: %RX64\n"
1022 " cbXferReq: %RX32\n"
1023 " cbXfered: %RX32\n",
1024 XferMem64.u64PtrTarget, XferMem64.cbXferReq, XferMem64.cbXfered));
1025 }
1026 else
1027 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferMem64), cbCopied));
1028 break;
1029 }
1030 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
1031 {
1032 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
1033 cbCopied = RTSgBufCopyToBuf(pSgBuf, &RestoreBkpt64, sizeof(RestoreBkpt64));
1034 if (cbCopied == sizeof(RestoreBkpt64))
1035 Log3((" u32HndBkpt: %RX32\n", RestoreBkpt64.u32HndBkpt));
1036 else
1037 Log3((" Payload to small, expected %u, got %zu\n", sizeof(RestoreBkpt64), cbCopied));
1038 break;
1039 }
1040 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
1041 {
1042 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
1043 cbCopied = RTSgBufCopyToBuf(pSgBuf, &WriteBkpt64, sizeof(WriteBkpt64));
1044 if (cbCopied == sizeof(WriteBkpt64))
1045 Log3((" u64PtrBkpt: %RX64\n"
1046 " u32HndBkpt: %RX32\n",
1047 WriteBkpt64.u64PtrBkpt, WriteBkpt64.u32HndBkpt));
1048 else
1049 Log3((" Payload to small, expected %u, got %zu\n", sizeof(WriteBkpt64), cbCopied));
1050 break;
1051 }
1052 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
1053 {
1054 KDPACKETMANIPULATE_CONTINUE Continue;
1055 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1056 if (cbCopied == sizeof(Continue))
1057 Log3((" u32NtContSts: %RX32\n", Continue.u32NtContSts));
1058 else
1059 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1060 break;
1061 }
1062 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
1063 {
1064 KDPACKETMANIPULATE_CONTINUE2 Continue;
1065 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1066 if (cbCopied == sizeof(Continue))
1067 Log3((" u32NtContSts: %RX32\n"
1068 " fTrace: %RX32\n",
1069 Continue.u32NtContSts, Continue.fTrace));
1070 else
1071 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1072 break;
1073 }
1074 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
1075 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
1076 {
1077 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
1078 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferCtrlSpace64, sizeof(XferCtrlSpace64));
1079 if (cbCopied == sizeof(XferCtrlSpace64))
1080 {
1081 Log3((" u64IdXfer: %RX64\n"
1082 " cbXferReq: %RX32\n"
1083 " cbXfered: %RX32\n",
1084 XferCtrlSpace64.u64IdXfer, XferCtrlSpace64.cbXferReq, XferCtrlSpace64.cbXfered));
1085 }
1086 else
1087 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferCtrlSpace64), cbCopied));
1088 break;
1089 }
1090 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
1091 {
1092 KDPACKETMANIPULATE_CONTEXTEX GetContextEx;
1093 cbCopied = RTSgBufCopyToBuf(pSgBuf, &GetContextEx, sizeof(GetContextEx));
1094 if (cbCopied == sizeof(GetContextEx))
1095 {
1096 Log3((" offStart: %RX32\n"
1097 " cbXferReq: %RX32\n"
1098 " cbXfered: %RX32\n",
1099 GetContextEx.offStart, GetContextEx.cbXfer, GetContextEx.cbXfered));
1100 }
1101 else
1102 Log3((" Payload to small, expected %u, got %zu\n", sizeof(GetContextEx), cbCopied));
1103 break;
1104 }
1105 default:
1106 break;
1107 }
1108 }
1109 else
1110 Log3((" MANIPULATE(Header too small, expected %u, got %zu)\n", sizeof(Hdr), cbCopied));
1111}
1112
1113
1114/**
1115 * Dumps the received packet to the debug log.
1116 *
1117 * @returns VBox status code.
1118 * @param pPktHdr The packet header to dump.
1119 * @param fRx Flag whether the packet was received (false indicates an outgoing packet).
1120 */
1121static void dbgcKdPktDump(PCKDPACKETHDR pPktHdr, PCRTSGSEG paSegs, uint32_t cSegs, bool fRx)
1122{
1123 RTSGBUF SgBuf;
1124
1125 RTSgBufInit(&SgBuf, paSegs, cSegs);
1126
1127 Log3(("%s KDPKTHDR(%#x, %#x (%s), %u, %#x, %#x)\n",
1128 fRx ? "=>" : "<=",
1129 pPktHdr->u32Signature, pPktHdr->u16SubType, dbgcKdPktDumpSubTypeToStr(pPktHdr->u16SubType),
1130 pPktHdr->cbBody, pPktHdr->idPacket, pPktHdr->u32ChkSum));
1131 switch (pPktHdr->u16SubType)
1132 {
1133 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
1134 dbgcKdPktDumpManipulate(&SgBuf);
1135 break;
1136 default:
1137 break;
1138 }
1139}
1140#endif
1141
1142
1143/**
1144 * Wrapper for the I/O interface write callback.
1145 *
1146 * @returns Status code.
1147 * @param pThis The KD context.
1148 * @param pvPkt The packet data to send.
1149 * @param cbPkt Size of the packet in bytes.
1150 */
1151DECLINLINE(int) dbgcKdCtxWrite(PKDCTX pThis, const void *pvPkt, size_t cbPkt)
1152{
1153 return pThis->Dbgc.pBack->pfnWrite(pThis->Dbgc.pBack, pvPkt, cbPkt, NULL /*pcbWritten*/);
1154}
1155
1156
1157/**
1158 * Fills in the given 64bit NT context structure with the requested values.
1159 *
1160 * @returns VBox status code.
1161 * @param pThis The KD context.
1162 * @param idCpu The CPU to query the context for.
1163 * @param pNtCtx The NT context structure to fill in.
1164 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1165 */
1166static int dbgcKdCtxQueryNtCtx64(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1167{
1168 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1169
1170 pNtCtx->fContext = NTCONTEXT_F_AMD64;
1171 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pNtCtx->u32RegMxCsr);
1172
1173 if ( RT_SUCCESS(rc)
1174 && fCtxFlags & NTCONTEXT_F_CONTROL)
1175 {
1176 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u16SegCs);
1177 if (RT_SUCCESS(rc))
1178 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u16SegSs);
1179 if (RT_SUCCESS(rc))
1180 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RIP, &pNtCtx->u64RegRip);
1181 if (RT_SUCCESS(rc))
1182 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSP, &pNtCtx->u64RegRsp);
1183 if (RT_SUCCESS(rc))
1184 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBP, &pNtCtx->u64RegRbp);
1185 if (RT_SUCCESS(rc))
1186 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1187 if (RT_SUCCESS(rc))
1188 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1189 }
1190
1191 if ( RT_SUCCESS(rc)
1192 && fCtxFlags & NTCONTEXT_F_INTEGER)
1193 {
1194 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RAX, &pNtCtx->u64RegRax);
1195 if (RT_SUCCESS(rc))
1196 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RCX, &pNtCtx->u64RegRcx);
1197 if (RT_SUCCESS(rc))
1198 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDX, &pNtCtx->u64RegRdx);
1199 if (RT_SUCCESS(rc))
1200 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBX, &pNtCtx->u64RegRbx);
1201 if (RT_SUCCESS(rc))
1202 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSI, &pNtCtx->u64RegRsi);
1203 if (RT_SUCCESS(rc))
1204 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDI, &pNtCtx->u64RegRdi);
1205 if (RT_SUCCESS(rc))
1206 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R8, &pNtCtx->u64RegR8);
1207 if (RT_SUCCESS(rc))
1208 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R9, &pNtCtx->u64RegR9);
1209 if (RT_SUCCESS(rc))
1210 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R10, &pNtCtx->u64RegR10);
1211 if (RT_SUCCESS(rc))
1212 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R11, &pNtCtx->u64RegR11);
1213 if (RT_SUCCESS(rc))
1214 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R12, &pNtCtx->u64RegR12);
1215 if (RT_SUCCESS(rc))
1216 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R13, &pNtCtx->u64RegR13);
1217 if (RT_SUCCESS(rc))
1218 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R14, &pNtCtx->u64RegR14);
1219 if (RT_SUCCESS(rc))
1220 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R15, &pNtCtx->u64RegR15);
1221 if (RT_SUCCESS(rc))
1222 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1223 }
1224
1225 if ( RT_SUCCESS(rc)
1226 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1227 {
1228 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u16SegDs);
1229 if (RT_SUCCESS(rc))
1230 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u16SegEs);
1231 if (RT_SUCCESS(rc))
1232 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u16SegFs);
1233 if (RT_SUCCESS(rc))
1234 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u16SegGs);
1235 if (RT_SUCCESS(rc))
1236 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1237 }
1238
1239 if ( RT_SUCCESS(rc)
1240 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1241 {
1242 /** @todo. */
1243 }
1244
1245 if ( RT_SUCCESS(rc)
1246 && fCtxFlags & NTCONTEXT_F_DEBUG)
1247 {
1248 /** @todo. */
1249 }
1250
1251 return rc;
1252}
1253
1254
1255#define KD_REG_INIT(a_pszName, a_enmType, a_ValMember, a_Val) \
1256 do \
1257 { \
1258 aRegsSet[idxReg].pszName = a_pszName; \
1259 aRegsSet[idxReg].enmType = a_enmType; \
1260 aRegsSet[idxReg].Val.a_ValMember = a_Val; \
1261 idxReg++; \
1262 } while (0)
1263#define KD_REG_INIT_DTR(a_pszName, a_Base, a_Limit) \
1264 do \
1265 { \
1266 aRegsSet[idxReg].pszName = a_pszName; \
1267 aRegsSet[idxReg].enmType = DBGFREGVALTYPE_DTR; \
1268 aRegsSet[idxReg].Val.dtr.u64Base = a_Base; \
1269 aRegsSet[idxReg].Val.dtr.u32Limit = a_Limit; \
1270 idxReg++; \
1271 } while (0)
1272#define KD_REG_INIT_U16(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U16, u16, a_Val)
1273#define KD_REG_INIT_U32(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U32, u32, a_Val)
1274#define KD_REG_INIT_U64(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U64, u64, a_Val)
1275
1276
1277/**
1278 * Writes the indicated values from the given context structure to the guests register set.
1279 *
1280 * @returns VBox status code.
1281 * @param pThis The KD context.
1282 * @param idCpu The CPU to query the context for.
1283 * @param pNtCtx The NT context structure to set.
1284 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to set.
1285 */
1286static int dbgcKdCtxSetNtCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1287{
1288 uint32_t idxReg = 0;
1289 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1290
1291 KD_REG_INIT_U32("mxcsr", pNtCtx->u32RegMxCsr);
1292
1293 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1294 {
1295#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1296 KD_REG_INIT_U16("cs", pNtCtx->u16SegCs);
1297 KD_REG_INIT_U16("ss", pNtCtx->u16SegSs);
1298#endif
1299 KD_REG_INIT_U64("rip", pNtCtx->u64RegRip);
1300 KD_REG_INIT_U64("rsp", pNtCtx->u64RegRsp);
1301 KD_REG_INIT_U64("rbp", pNtCtx->u64RegRbp);
1302 KD_REG_INIT_U32("rflags", pNtCtx->u32RegEflags);
1303 }
1304
1305 if (fCtxFlags & NTCONTEXT_F_INTEGER)
1306 {
1307 KD_REG_INIT_U64("rax", pNtCtx->u64RegRax);
1308 KD_REG_INIT_U64("rcx", pNtCtx->u64RegRcx);
1309 KD_REG_INIT_U64("rdx", pNtCtx->u64RegRdx);
1310 KD_REG_INIT_U64("rbx", pNtCtx->u64RegRbx);
1311 KD_REG_INIT_U64("rsi", pNtCtx->u64RegRsi);
1312 KD_REG_INIT_U64("rdi", pNtCtx->u64RegRdi);
1313 KD_REG_INIT_U64("r8", pNtCtx->u64RegR8);
1314 KD_REG_INIT_U64("r9", pNtCtx->u64RegR9);
1315 KD_REG_INIT_U64("r10", pNtCtx->u64RegR10);
1316 KD_REG_INIT_U64("r11", pNtCtx->u64RegR11);
1317 KD_REG_INIT_U64("r12", pNtCtx->u64RegR12);
1318 KD_REG_INIT_U64("r13", pNtCtx->u64RegR13);
1319 KD_REG_INIT_U64("r14", pNtCtx->u64RegR14);
1320 KD_REG_INIT_U64("r15", pNtCtx->u64RegR15);
1321 }
1322
1323 if (fCtxFlags & NTCONTEXT_F_SEGMENTS)
1324 {
1325#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1326 KD_REG_INIT_U16("ds", pNtCtx->u16SegDs);
1327 KD_REG_INIT_U16("es", pNtCtx->u16SegEs);
1328 KD_REG_INIT_U16("fs", pNtCtx->u16SegFs);
1329 KD_REG_INIT_U16("gs", pNtCtx->u16SegGs);
1330#endif
1331 }
1332
1333 if (fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1334 {
1335 /** @todo. */
1336 }
1337
1338 if (fCtxFlags & NTCONTEXT_F_DEBUG)
1339 {
1340 /** @todo. */
1341 }
1342
1343 return DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
1344}
1345
1346
1347/**
1348 * Fills in the given 64bit NT kernel context structure with the requested values.
1349 *
1350 * @returns VBox status code.
1351 * @param pThis The KD context.
1352 * @param idCpu The CPU to query the context for.
1353 * @param pKNtCtx The NT context structure to fill in.
1354 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1355 */
1356static int dbgcKdCtxQueryNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT64 pKNtCtx, uint32_t fCtxFlags)
1357{
1358 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
1359
1360 int rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u64RegCr0);
1361 if (RT_SUCCESS(rc))
1362 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u64RegCr2);
1363 if (RT_SUCCESS(rc))
1364 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u64RegCr3);
1365 if (RT_SUCCESS(rc))
1366 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u64RegCr4);
1367 if (RT_SUCCESS(rc))
1368 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR8, &pKNtCtx->u64RegCr8);
1369 if (RT_SUCCESS(rc))
1370 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pKNtCtx->u64RegDr0);
1371 if (RT_SUCCESS(rc))
1372 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pKNtCtx->u64RegDr1);
1373 if (RT_SUCCESS(rc))
1374 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR2, &pKNtCtx->u64RegDr2);
1375 if (RT_SUCCESS(rc))
1376 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pKNtCtx->u64RegDr3);
1377 if (RT_SUCCESS(rc))
1378 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pKNtCtx->u64RegDr6);
1379 if (RT_SUCCESS(rc))
1380 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pKNtCtx->u64RegDr7);
1381 if (RT_SUCCESS(rc))
1382 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
1383 if (RT_SUCCESS(rc))
1384 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u64PtrBase);
1385 if (RT_SUCCESS(rc))
1386 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
1387 if (RT_SUCCESS(rc))
1388 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u64PtrBase);
1389 if (RT_SUCCESS(rc))
1390 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
1391 if (RT_SUCCESS(rc))
1392 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
1393 if (RT_SUCCESS(rc))
1394 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pKNtCtx->u32RegMxCsr);
1395 /** @todo Debug control and stuff. */
1396
1397 if (RT_SUCCESS(rc))
1398 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_GS_BASE, &pKNtCtx->u64MsrGsBase);
1399 if (RT_SUCCESS(rc))
1400 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_KERNEL_GS_BASE, &pKNtCtx->u64MsrKernelGsBase);
1401 if (RT_SUCCESS(rc))
1402 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K6_STAR, &pKNtCtx->u64MsrStar);
1403 if (RT_SUCCESS(rc))
1404 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_LSTAR, &pKNtCtx->u64MsrLstar);
1405 if (RT_SUCCESS(rc))
1406 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_CSTAR, &pKNtCtx->u64MsrCstar);
1407 if (RT_SUCCESS(rc))
1408 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_SF_MASK, &pKNtCtx->u64MsrSfMask);
1409 /** @todo XCR0 */
1410
1411 if (RT_SUCCESS(rc))
1412 rc = dbgcKdCtxQueryNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, fCtxFlags);
1413
1414 return rc;
1415}
1416
1417
1418/**
1419 * Fills in the given 64bit NT kernel context structure with the requested values.
1420 *
1421 * @returns VBox status code.
1422 * @param pThis The KD context.
1423 * @param idCpu The CPU to query the context for.
1424 * @param pKNtCtx The NT context structure to fill in.
1425 * @param cbSet How many bytes of the context are valid.
1426 */
1427static int dbgcKdCtxSetNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTKCONTEXT64 pKNtCtx, size_t cbSet)
1428{
1429 AssertReturn(cbSet >= RT_UOFFSETOF(NTKCONTEXT64, Ctx), VERR_INVALID_PARAMETER);
1430
1431 uint32_t idxReg = 0;
1432 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1433
1434 KD_REG_INIT_U64("cr0", pKNtCtx->u64RegCr0);
1435 KD_REG_INIT_U64("cr2", pKNtCtx->u64RegCr2);
1436 KD_REG_INIT_U64("cr3", pKNtCtx->u64RegCr3);
1437 KD_REG_INIT_U64("cr4", pKNtCtx->u64RegCr4);
1438 KD_REG_INIT_U64("cr8", pKNtCtx->u64RegCr8);
1439 KD_REG_INIT_U64("dr0", pKNtCtx->u64RegDr0);
1440 KD_REG_INIT_U64("dr1", pKNtCtx->u64RegDr1);
1441 KD_REG_INIT_U64("dr2", pKNtCtx->u64RegDr2);
1442 KD_REG_INIT_U64("dr3", pKNtCtx->u64RegDr3);
1443 KD_REG_INIT_U64("dr6", pKNtCtx->u64RegDr6);
1444 KD_REG_INIT_U64("dr7", pKNtCtx->u64RegDr7);
1445
1446 KD_REG_INIT_DTR("gdtr", pKNtCtx->Gdtr.u64PtrBase, pKNtCtx->Gdtr.u16Limit);
1447 KD_REG_INIT_DTR("idtr", pKNtCtx->Idtr.u64PtrBase, pKNtCtx->Idtr.u16Limit);
1448
1449#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1450 KD_REG_INIT_U16("tr", pKNtCtx->u16RegTr);
1451 KD_REG_INIT_U16("ldtr", pKNtCtx->u16RegLdtr);
1452#endif
1453 KD_REG_INIT_U32("mxcsr", pKNtCtx->u32RegMxCsr);
1454
1455 KD_REG_INIT_U64("msr_gs_base", pKNtCtx->u64MsrGsBase);
1456 KD_REG_INIT_U64("krnl_gs_base", pKNtCtx->u64MsrKernelGsBase);
1457 KD_REG_INIT_U64("star", pKNtCtx->u64MsrStar);
1458 KD_REG_INIT_U64("lstar", pKNtCtx->u64MsrLstar);
1459 KD_REG_INIT_U64("cstar", pKNtCtx->u64MsrCstar);
1460 KD_REG_INIT_U64("sf_mask", pKNtCtx->u64MsrSfMask);
1461
1462 int rc = DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
1463 if ( RT_SUCCESS(rc)
1464 && cbSet > RT_UOFFSETOF(NTKCONTEXT64, Ctx)) /** @todo Probably wrong. */
1465 rc = dbgcKdCtxSetNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, pKNtCtx->Ctx.fContext);
1466
1467 return rc;
1468}
1469
1470#undef KD_REG_INIT_64
1471#undef KD_REG_INIT_32
1472#undef KD_REG_INIT_16
1473#undef KD_REG_INIT_DTR
1474#undef KD_REG_INIT
1475
1476
1477/**
1478 * Validates the given KD packet header.
1479 *
1480 * @returns Flag whether the packet header is valid, false if invalid.
1481 * @param pPktHdr The packet header to validate.
1482 */
1483static bool dbgcKdPktHdrValidate(PCKDPACKETHDR pPktHdr)
1484{
1485 if ( pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_DATA
1486 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_CONTROL
1487 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_BREAKIN)
1488 return false;
1489
1490 if (pPktHdr->u16SubType >= KD_PACKET_HDR_SUB_TYPE_MAX)
1491 return false;
1492
1493 uint32_t idPacket = pPktHdr->idPacket & UINT32_C(0xfffffffe);
1494 if ( idPacket != KD_PACKET_HDR_ID_INITIAL
1495 && idPacket != KD_PACKET_HDR_ID_RESET
1496 && idPacket != 0 /* Happens on the very first packet */)
1497 return false;
1498
1499 return true;
1500}
1501
1502
1503/**
1504 * Generates a checksum from the given buffer.
1505 *
1506 * @returns Generated checksum.
1507 * @param pv The data to generate a checksum from.
1508 * @param cb Number of bytes to checksum.
1509 */
1510static uint32_t dbgcKdPktChkSumGen(const void *pv, size_t cb)
1511{
1512 const uint8_t *pb = (const uint8_t *)pv;
1513 uint32_t u32ChkSum = 0;
1514
1515 while (cb--)
1516 u32ChkSum += *pb++;
1517
1518 return u32ChkSum;
1519}
1520
1521
1522/**
1523 * Generates a checksum from the given segments.
1524 *
1525 * @returns Generated checksum.
1526 * @param paSegs Pointer to the array of segments containing the data.
1527 * @param cSegs Number of segments.
1528 * @param pcbChkSum Where to store the number of bytes checksummed, optional.
1529 */
1530static uint32_t dbgcKdPktChkSumGenSg(PCRTSGSEG paSegs, uint32_t cSegs, size_t *pcbChkSum)
1531{
1532 size_t cbChkSum = 0;
1533 uint32_t u32ChkSum = 0;
1534
1535 for (uint32_t i = 0; i < cSegs; i++)
1536 {
1537 u32ChkSum += dbgcKdPktChkSumGen(paSegs[i].pvSeg, paSegs[i].cbSeg);
1538 cbChkSum += paSegs[i].cbSeg;
1539 }
1540
1541 if (pcbChkSum)
1542 *pcbChkSum = cbChkSum;
1543
1544 return u32ChkSum;
1545}
1546
1547
1548/**
1549 * Waits for an acknowledgment.
1550 *
1551 * @returns VBox status code.
1552 * @param pThis The KD context.
1553 * @param msWait Maximum number of milliseconds to wait for an acknowledge.
1554 * @param pfResend Where to store the resend requested flag on success.
1555 */
1556static int dbgcKdCtxPktWaitForAck(PKDCTX pThis, RTMSINTERVAL msWait, bool *pfResend)
1557{
1558 KDPACKETHDR PktAck;
1559 uint8_t *pbCur = (uint8_t *)&PktAck;
1560 size_t cbLeft = sizeof(PktAck);
1561 uint64_t tsStartMs = RTTimeMilliTS();
1562 int rc = VINF_SUCCESS;
1563
1564 LogFlowFunc(("pThis=%p msWait=%u pfResend=%p\n", pThis, msWait, pfResend));
1565
1566 RT_ZERO(PktAck);
1567
1568 /* There might be breakin packets in the queue, read until we get something else. */
1569 while ( msWait
1570 && RT_SUCCESS(rc))
1571 {
1572 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
1573 {
1574 size_t cbRead = 0;
1575 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, 1, &cbRead);
1576 if ( RT_SUCCESS(rc)
1577 && cbRead == 1)
1578 {
1579 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
1580 msWait -= RT_MIN(msWait, tsSpanMs);
1581 tsStartMs = RTTimeMilliTS();
1582
1583 if (*pbCur == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
1584 pThis->fBreakinRecv = true;
1585 else
1586 {
1587 pbCur++;
1588 cbLeft--;
1589 break;
1590 }
1591 }
1592 }
1593 else
1594 rc = VERR_TIMEOUT;
1595 }
1596
1597 if ( RT_SUCCESS(rc)
1598 && !msWait)
1599 rc = VERR_TIMEOUT;
1600
1601 if (RT_SUCCESS(rc))
1602 {
1603 while ( msWait
1604 && RT_SUCCESS(rc)
1605 && cbLeft)
1606 {
1607 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, msWait))
1608 {
1609 size_t cbRead = 0;
1610 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pbCur, cbLeft, &cbRead);
1611 if (RT_SUCCESS(rc))
1612 {
1613 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
1614 msWait -= RT_MIN(msWait, tsSpanMs);
1615 tsStartMs = RTTimeMilliTS();
1616
1617 cbLeft -= cbRead;
1618 pbCur += cbRead;
1619 }
1620 }
1621 else
1622 rc = VERR_TIMEOUT;
1623 }
1624
1625 if (RT_SUCCESS(rc))
1626 {
1627 if (PktAck.u32Signature == KD_PACKET_HDR_SIGNATURE_CONTROL)
1628 {
1629 if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE)
1630 rc = VINF_SUCCESS;
1631 else if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_RESEND)
1632 {
1633 *pfResend = true;
1634 rc = VINF_SUCCESS;
1635 }
1636 else
1637 rc = VERR_NET_PROTOCOL_ERROR;
1638 }
1639 else
1640 rc = VERR_NET_PROTOCOL_ERROR;
1641 }
1642 }
1643
1644 LogFlowFunc(("returns rc=%Rrc *pfResend=%RTbool\n", rc, *pfResend));
1645 return rc;
1646}
1647
1648
1649/**
1650 * Sends the given packet header and optional segmented body (the trailing byte is sent automatically).
1651 *
1652 * @returns VBox status code.
1653 * @param pThis The KD context.
1654 * @param u32Signature The signature to send.
1655 * @param u16SubType The sub type to send.
1656 * @param paSegs Pointer to the array of segments to send in the body, optional.
1657 * @param cSegs Number of segments.
1658 * @param fAck Flag whether to wait for an acknowledge.
1659 */
1660static int dbgcKdCtxPktSendSg(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
1661 PCRTSGSEG paSegs, uint32_t cSegs, bool fAck)
1662{
1663 int rc = VINF_SUCCESS;
1664 uint32_t cRetriesLeft = 3;
1665 uint8_t bTrailer = KD_PACKET_TRAILING_BYTE;
1666 KDPACKETHDR Hdr;
1667
1668 size_t cbChkSum = 0;
1669 uint32_t u32ChkSum = dbgcKdPktChkSumGenSg(paSegs, cSegs, &cbChkSum);
1670
1671 Hdr.u32Signature = u32Signature;
1672 Hdr.u16SubType = u16SubType;
1673 Hdr.cbBody = (uint16_t)cbChkSum;
1674 Hdr.idPacket = pThis->idPktNext;
1675 Hdr.u32ChkSum = u32ChkSum;
1676
1677#ifdef LOG_ENABLED
1678 dbgcKdPktDump(&Hdr, paSegs, cSegs, false /*fRx*/);
1679#endif
1680
1681 while (cRetriesLeft--)
1682 {
1683 bool fResend = false;
1684
1685 rc = dbgcKdCtxWrite(pThis, &Hdr, sizeof(Hdr));
1686 if ( RT_SUCCESS(rc)
1687 && paSegs
1688 && cSegs)
1689 {
1690 for (uint32_t i = 0; i < cSegs && RT_SUCCESS(rc); i++)
1691 rc = dbgcKdCtxWrite(pThis, paSegs[i].pvSeg, paSegs[i].cbSeg);
1692
1693 if (RT_SUCCESS(rc))
1694 rc = dbgcKdCtxWrite(pThis, &bTrailer, sizeof(bTrailer));
1695 }
1696
1697 if (RT_SUCCESS(rc))
1698 {
1699 if (fAck)
1700 rc = dbgcKdCtxPktWaitForAck(pThis, 10 * 1000, &fResend);
1701
1702 if ( RT_SUCCESS(rc)
1703 && !fResend)
1704 break;
1705 }
1706 }
1707
1708 return rc;
1709}
1710
1711
1712/**
1713 * Sends the given packet header and optional body (the trailing byte is sent automatically).
1714 *
1715 * @returns VBox status code.
1716 * @param pThis The KD context.
1717 * @param u32Signature The signature to send.
1718 * @param u16SubType The sub type to send.
1719 * @param pvBody The body to send, optional.
1720 * @param cbBody Body size in bytes.
1721 * @param fAck Flag whether to wait for an acknowledge.
1722 */
1723DECLINLINE(int) dbgcKdCtxPktSend(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
1724 const void *pvBody, size_t cbBody,
1725 bool fAck)
1726{
1727 RTSGSEG Seg;
1728
1729 Seg.pvSeg = (void *)pvBody;
1730 Seg.cbSeg = cbBody;
1731 return dbgcKdCtxPktSendSg(pThis, u32Signature, u16SubType, cbBody ? &Seg : NULL, cbBody ? 1 : 0, fAck);
1732}
1733
1734
1735/**
1736 * Sends a resend packet answer.
1737 *
1738 * @returns VBox status code.
1739 * @param pThis The KD context.
1740 */
1741DECLINLINE(int) dbgcKdCtxPktSendResend(PKDCTX pThis)
1742{
1743 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESEND,
1744 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
1745}
1746
1747
1748/**
1749 * Sends a resend packet answer.
1750 *
1751 * @returns VBox status code.
1752 * @param pThis The KD context.
1753 */
1754DECLINLINE(int) dbgcKdCtxPktSendReset(PKDCTX pThis)
1755{
1756 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
1757 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESET,
1758 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
1759}
1760
1761
1762/**
1763 * Sends an acknowledge packet answer.
1764 *
1765 * @returns VBox status code.
1766 * @param pThis The KD context.
1767 */
1768DECLINLINE(int) dbgcKdCtxPktSendAck(PKDCTX pThis)
1769{
1770 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE,
1771 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
1772}
1773
1774
1775/**
1776 * Resets the packet receive state machine.
1777 *
1778 * @returns nothing.
1779 * @param pThis The KD context.
1780 */
1781static void dbgcKdCtxPktRecvReset(PKDCTX pThis)
1782{
1783 pThis->enmState = KDRECVSTATE_PACKET_HDR_FIRST_BYTE;
1784 pThis->pbRecv = &pThis->PktHdr.ab[0];
1785 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[0]);
1786 pThis->msRecvTimeout = RT_INDEFINITE_WAIT;
1787 pThis->tsRecvLast = RTTimeMilliTS();
1788}
1789
1790
1791/**
1792 * Sends a state change event packet.
1793 *
1794 * @returns VBox status code.
1795 * @param pThis The KD context data.
1796 * @param enmType The event type.
1797 */
1798static int dbgcKdCtxStateChangeSend(PKDCTX pThis, DBGFEVENTTYPE enmType)
1799{
1800 LogFlowFunc(("pThis=%p enmType=%u\n", pThis, enmType));
1801
1802 /* Select the record to send based on the CPU mode. */
1803 int rc = VINF_SUCCESS;
1804 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
1805 switch (enmMode)
1806 {
1807 case CPUMMODE_PROTECTED:
1808 {
1809 break;
1810 }
1811 case CPUMMODE_LONG:
1812 {
1813 KDPACKETSTATECHANGE64 StateChange64;
1814 RT_ZERO(StateChange64);
1815
1816 StateChange64.u32StateNew = KD_PACKET_STATE_CHANGE_EXCEPTION;
1817 StateChange64.u16CpuLvl = 0x6; /** @todo Figure this one out. */
1818 StateChange64.idCpu = pThis->Dbgc.idCpu;
1819 StateChange64.cCpus = (uint16_t)DBGFR3CpuGetCount(pThis->Dbgc.pUVM);
1820 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RIP, &StateChange64.u64RipThread);
1821 if (RT_SUCCESS(rc))
1822 {
1823 /** @todo Properly fill in the exception record. */
1824 switch (enmType)
1825 {
1826 case DBGFEVENT_HALT_DONE:
1827 case DBGFEVENT_BREAKPOINT:
1828 case DBGFEVENT_BREAKPOINT_IO:
1829 case DBGFEVENT_BREAKPOINT_MMIO:
1830 case DBGFEVENT_BREAKPOINT_HYPER:
1831 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_BKPT;
1832 break;
1833 case DBGFEVENT_STEPPED:
1834 case DBGFEVENT_STEPPED_HYPER:
1835 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_SINGLE_STEP;
1836 break;
1837 default:
1838 AssertMsgFailed(("Invalid DBGF event type for state change %d!\n", enmType));
1839 }
1840
1841 StateChange64.u.Exception.ExcpRec.cExcpParms = 3;
1842 StateChange64.u.Exception.u32FirstChance = 0x1;
1843
1844 /** @todo Properly fill in the control report. */
1845 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR6, &StateChange64.uCtrlReport.Amd64.u64RegDr6);
1846 if (RT_SUCCESS(rc))
1847 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR7, &StateChange64.uCtrlReport.Amd64.u64RegDr7);
1848 if (RT_SUCCESS(rc))
1849 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RFLAGS, &StateChange64.uCtrlReport.Amd64.u32RegEflags);
1850 if (RT_SUCCESS(rc))
1851 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_CS, &StateChange64.uCtrlReport.Amd64.u16SegCs);
1852 if (RT_SUCCESS(rc))
1853 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DS, &StateChange64.uCtrlReport.Amd64.u16SegDs);
1854 if (RT_SUCCESS(rc))
1855 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_ES, &StateChange64.uCtrlReport.Amd64.u16SegEs);
1856 if (RT_SUCCESS(rc))
1857 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_FS, &StateChange64.uCtrlReport.Amd64.u16SegFs);
1858
1859 /* Read instruction bytes. */
1860 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
1861 DBGFADDRESS AddrRip;
1862 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRip, StateChange64.u64RipThread);
1863 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
1864 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
1865 if (RT_SUCCESS(rc))
1866 {
1867 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
1868 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
1869 &StateChange64, sizeof(StateChange64), false /*fAck*/);
1870 }
1871 }
1872 break;
1873 }
1874 case CPUMMODE_REAL:
1875 default:
1876 return DBGCCmdHlpPrintf(&pThis->Dbgc.CmdHlp, "error: Invalid CPU mode %d.\n", enmMode);
1877 }
1878
1879 LogFlowFunc(("returns %Rrc\n", rc));
1880 return rc;
1881}
1882
1883
1884/**
1885 * Processes a get version 64 request.
1886 *
1887 * @returns VBox status code.
1888 * @param pThis The KD context.
1889 * @param pPktManip The manipulate packet request.
1890 */
1891static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
1892{
1893 KDPACKETMANIPULATE64 Resp;
1894 RT_ZERO(Resp);
1895
1896 /* Fill in the generic part. */
1897 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
1898 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
1899 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
1900 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
1901
1902 /* Build our own response in case there is no Windows interface available. */
1903 uint32_t NtBuildNumber = 0x0f2800; /* Used when there is no NT interface available, which probably breaks symbol loading. */
1904 bool f32Bit = false;
1905 if (pThis->pIfWinNt)
1906 {
1907 int rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM,
1908 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
1909 &NtBuildNumber, &f32Bit);
1910 if (RT_SUCCESS(rc))
1911 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, &Resp.u.GetVersion.u64PtrKernBase,
1912 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
1913 }
1914
1915 /* Fill in the request specific part. */
1916 Resp.u.GetVersion.u16VersMaj = NtBuildNumber >> 16;
1917 Resp.u.GetVersion.u16VersMin = NtBuildNumber & UINT32_C(0xffff);
1918 Resp.u.GetVersion.u8VersProtocol = 0x6; /* From a Windows 10 guest. */
1919 Resp.u.GetVersion.u8VersKdSecondary = 0x2; /* From a Windows 10 guest. */
1920 Resp.u.GetVersion.fFlags = KD_PACKET_MANIPULATE64_GET_VERSION_F_MP;
1921 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
1922 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
1923 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_MAX - KD_PACKET_MANIPULATE_REQ_MIN;
1924 Resp.u.GetVersion.u64PtrDebuggerDataList = 0;
1925
1926 if (f32Bit)
1927 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_I386;
1928 else
1929 {
1930 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
1931 Resp.u.GetVersion.fFlags |= KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64;
1932 }
1933
1934 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
1935 &Resp, sizeof(Resp), true /*fAck*/);
1936}
1937
1938
1939/**
1940 * Processes a read memory 64 request.
1941 *
1942 * @returns VBox status code.
1943 * @param pThis The KD context.
1944 * @param pPktManip The manipulate packet request.
1945 */
1946static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
1947{
1948 KDPACKETMANIPULATEHDR RespHdr;
1949 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1950 uint8_t abMem[_4K];
1951 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
1952
1953 DBGFADDRESS AddrRead;
1954 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
1955 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
1956 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, pPktManip->u.XferMem.u64PtrTarget);
1957 else
1958 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, pPktManip->u.XferMem.u64PtrTarget);
1959
1960 RTSGSEG aRespSegs[3];
1961 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
1962 RespHdr.idReq = pPktManip->Hdr.idReq;
1963 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
1964 RespHdr.idCpu = pPktManip->Hdr.idCpu;
1965 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
1966
1967 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
1968 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
1969 XferMem64.cbXfered = (uint32_t)cbRead;
1970
1971 aRespSegs[0].pvSeg = &RespHdr;
1972 aRespSegs[0].cbSeg = sizeof(RespHdr);
1973 aRespSegs[1].pvSeg = &XferMem64;
1974 aRespSegs[1].cbSeg = sizeof(XferMem64);
1975
1976 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
1977 if (RT_SUCCESS(rc))
1978 {
1979 cSegs++;
1980 aRespSegs[2].pvSeg = &abMem[0];
1981 aRespSegs[2].cbSeg = cbRead;
1982 }
1983 else
1984 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
1985
1986 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
1987 &aRespSegs[0], cSegs, true /*fAck*/);
1988}
1989
1990
1991/**
1992 * Processes a write memory 64 request.
1993 *
1994 * @returns VBox status code.
1995 * @param pThis The KD context.
1996 * @param pPktManip The manipulate packet request.
1997 */
1998static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
1999{
2000 KDPACKETMANIPULATEHDR RespHdr;
2001 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2002 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2003
2004 DBGFADDRESS AddrWrite;
2005 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2006 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
2007 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
2008 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, pPktManip->u.XferMem.u64PtrTarget);
2009 else
2010 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, pPktManip->u.XferMem.u64PtrTarget);
2011
2012 RTSGSEG aRespSegs[2];
2013 uint32_t cSegs = 2;
2014 RespHdr.idReq = pPktManip->Hdr.idReq;
2015 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2016 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2017 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2018
2019 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2020 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2021 XferMem64.cbXfered = (uint32_t)cbWrite;
2022
2023 aRespSegs[0].pvSeg = &RespHdr;
2024 aRespSegs[0].cbSeg = sizeof(RespHdr);
2025 aRespSegs[1].pvSeg = &XferMem64;
2026 aRespSegs[1].cbSeg = sizeof(XferMem64);
2027
2028 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
2029 if (RT_FAILURE(rc))
2030 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2031
2032 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2033 &aRespSegs[0], cSegs, true /*fAck*/);
2034}
2035
2036
2037/**
2038 * Processes a continue request.
2039 *
2040 * @returns VBox status code.
2041 * @param pThis The KD context.
2042 * @param pPktManip The manipulate packet request.
2043 */
2044static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2045{
2046 RT_NOREF(pPktManip);
2047 int rc = VINF_SUCCESS;
2048
2049 /* No response, just resume. */
2050 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2051 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2052
2053 return rc;
2054}
2055
2056
2057/**
2058 * Processes a continue request.
2059 *
2060 * @returns VBox status code.
2061 * @param pThis The KD context.
2062 * @param pPktManip The manipulate packet request.
2063 */
2064static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2065{
2066 int rc = VINF_SUCCESS;
2067
2068 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
2069 if (pPktManip->u.Continue2.fTrace)
2070 {
2071 PDBGFADDRESS pStackPop = NULL;
2072 RTGCPTR cbStackPop = 0;
2073 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
2074 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
2075 }
2076 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2077 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2078
2079 return rc;
2080}
2081
2082
2083/**
2084 * Processes a set context request.
2085 *
2086 * @returns VBox status code.
2087 * @param pThis The KD context.
2088 * @param pPktManip The manipulate packet request.
2089 */
2090static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2091{
2092 KDPACKETMANIPULATEHDR RespHdr;
2093 KDPACKETMANIPULATE_SETCONTEXT SetContext;
2094 RT_ZERO(RespHdr); RT_ZERO(SetContext);
2095
2096 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2097
2098 RTSGSEG aRespSegs[2];
2099 uint32_t cSegs = 2;
2100 RespHdr.idReq = pPktManip->Hdr.idReq;
2101 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2102 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2103 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2104
2105 /** @todo What do these flags mean? Can't be the context state to set because the valid one is
2106 * in NTCONTEXT64::fContext (observed with WinDbg). */
2107 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
2108
2109 aRespSegs[0].pvSeg = &RespHdr;
2110 aRespSegs[0].cbSeg = sizeof(RespHdr);
2111 aRespSegs[1].pvSeg = &SetContext;
2112 aRespSegs[1].cbSeg = sizeof(SetContext);
2113
2114 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, pNtCtx->fContext);
2115 if (RT_FAILURE(rc))
2116 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2117
2118 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2119 &aRespSegs[0], cSegs, true /*fAck*/);
2120}
2121
2122
2123/**
2124 * Processes a read control space 64 request.
2125 *
2126 * @returns VBox status code.
2127 * @param pThis The KD context.
2128 * @param pPktManip The manipulate packet request.
2129 */
2130static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2131{
2132 KDPACKETMANIPULATEHDR RespHdr;
2133 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2134 uint8_t abResp[sizeof(NTKCONTEXT64)];
2135 uint32_t cbData = 0;
2136 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2137 RT_ZERO(abResp);
2138
2139 RTSGSEG aRespSegs[3];
2140 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2141 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
2142 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2143 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2144 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2145
2146 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
2147 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
2148
2149 aRespSegs[0].pvSeg = &RespHdr;
2150 aRespSegs[0].cbSeg = sizeof(RespHdr);
2151 aRespSegs[1].pvSeg = &XferCtrlSpace64;
2152 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
2153
2154 int rc = VINF_SUCCESS;
2155 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
2156 {
2157 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
2158 {
2159 if (pThis->pIfWinNt)
2160 {
2161 RTGCUINTPTR GCPtrKpcr = 0;
2162
2163 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2164 &GCPtrKpcr, NULL /*pKpcrb*/);
2165 if (RT_SUCCESS(rc))
2166 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
2167 }
2168
2169 cbData = sizeof(RTGCUINTPTR);
2170 break;
2171 }
2172 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
2173 {
2174 if (pThis->pIfWinNt)
2175 {
2176 RTGCUINTPTR GCPtrKpcrb = 0;
2177
2178 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2179 NULL /*pKpcr*/, &GCPtrKpcrb);
2180 if (RT_SUCCESS(rc))
2181 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
2182 }
2183
2184 cbData = sizeof(RTGCUINTPTR);
2185 break;
2186 }
2187 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
2188 {
2189 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
2190 if (RT_SUCCESS(rc))
2191 cbData = sizeof(NTKCONTEXT64);
2192 break;
2193 }
2194 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
2195 {
2196 if (pThis->pIfWinNt)
2197 {
2198 RTGCUINTPTR GCPtrCurThrd = 0;
2199
2200 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
2201 &GCPtrCurThrd);
2202 if (RT_SUCCESS(rc))
2203 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
2204 }
2205
2206 cbData = sizeof(RTGCUINTPTR);
2207 break;
2208 }
2209 default:
2210 rc = VERR_NOT_SUPPORTED;
2211 break;
2212 }
2213
2214 if ( RT_SUCCESS(rc)
2215 && cbData)
2216 {
2217 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
2218
2219 cSegs++;
2220 aRespSegs[2].pvSeg = &abResp[0];
2221 aRespSegs[2].cbSeg = cbData;
2222 }
2223 else if (RT_FAILURE(rc))
2224 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2225
2226 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2227 &aRespSegs[0], cSegs, true /*fAck*/);
2228}
2229
2230
2231/**
2232 * Processes a write control space 64 request.
2233 *
2234 * @returns VBox status code.
2235 * @param pThis The KD context.
2236 * @param pPktManip The manipulate packet request.
2237 */
2238static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2239{
2240 KDPACKETMANIPULATEHDR RespHdr;
2241 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2242 uint32_t cbData = 0;
2243 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2244
2245 RTSGSEG aRespSegs[2];
2246 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
2247 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2248 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2249 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2250
2251 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
2252 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
2253
2254 aRespSegs[0].pvSeg = &RespHdr;
2255 aRespSegs[0].cbSeg = sizeof(RespHdr);
2256 aRespSegs[1].pvSeg = &XferCtrlSpace64;
2257 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
2258
2259 int rc = VINF_SUCCESS;
2260 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
2261 {
2262 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
2263 {
2264 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2265 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
2266 if (RT_SUCCESS(rc))
2267 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
2268 break;
2269 }
2270 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
2271 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
2272 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
2273 default:
2274 rc = VERR_NOT_SUPPORTED;
2275 break;
2276 }
2277
2278 if (RT_FAILURE(rc))
2279 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2280 else
2281 XferCtrlSpace64.cbXfered = cbData;
2282
2283 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2284 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2285}
2286
2287
2288/**
2289 * Processes a restore breakpoint 64 request.
2290 *
2291 * @returns VBox status code.
2292 * @param pThis The KD context.
2293 * @param pPktManip The manipulate packet request.
2294 */
2295static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2296{
2297 KDPACKETMANIPULATEHDR RespHdr;
2298 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
2299 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
2300
2301 RTSGSEG aRespSegs[2];
2302 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
2303 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2304 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2305 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2306
2307 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
2308
2309 aRespSegs[0].pvSeg = &RespHdr;
2310 aRespSegs[0].cbSeg = sizeof(RespHdr);
2311 aRespSegs[1].pvSeg = &RestoreBkpt64;
2312 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
2313
2314 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
2315 if ( RT_FAILURE(rc)
2316 && rc != VERR_DBGF_BP_NOT_FOUND)
2317 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2318
2319 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2320 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2321}
2322
2323
2324/**
2325 * Processes a write breakpoint 64 request.
2326 *
2327 * @returns VBox status code.
2328 * @param pThis The KD context.
2329 * @param pPktManip The manipulate packet request.
2330 */
2331static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2332{
2333 KDPACKETMANIPULATEHDR RespHdr;
2334 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
2335 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
2336
2337 RTSGSEG aRespSegs[2];
2338 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
2339 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2340 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2341 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2342
2343 aRespSegs[0].pvSeg = &RespHdr;
2344 aRespSegs[0].cbSeg = sizeof(RespHdr);
2345 aRespSegs[1].pvSeg = &WriteBkpt64;
2346 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
2347
2348 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
2349
2350 DBGFADDRESS BpAddr;
2351 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, pPktManip->u.WriteBkpt.u64PtrBkpt);
2352 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
2353 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
2354 if (RT_FAILURE(rc))
2355 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2356
2357 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2358 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2359}
2360
2361
2362/**
2363 * Processes a get context extended 64 request.
2364 *
2365 * @returns VBox status code.
2366 * @param pThis The KD context.
2367 * @param pPktManip The manipulate packet request.
2368 */
2369static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2370{
2371 KDPACKETMANIPULATEHDR RespHdr;
2372 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
2373 NTCONTEXT64 NtCtx;
2374 RT_ZERO(RespHdr); RT_ZERO(ContextEx);
2375
2376 RTSGSEG aRespSegs[3];
2377 uint32_t cSegs = 2;
2378 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
2379 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2380 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2381 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
2382
2383 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
2384 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
2385 ContextEx.cbXfered = 0;
2386
2387 aRespSegs[0].pvSeg = &RespHdr;
2388 aRespSegs[0].cbSeg = sizeof(RespHdr);
2389 aRespSegs[1].pvSeg = &ContextEx;
2390 aRespSegs[1].cbSeg = sizeof(ContextEx);
2391
2392 int rc = dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx, NTCONTEXT64_F_FULL);
2393 if ( RT_SUCCESS(rc)
2394 && pPktManip->u.ContextEx.offStart < sizeof(NtCtx))
2395 {
2396 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2397 ContextEx.cbXfered = RT_MIN(sizeof(NtCtx) - ContextEx.offStart, ContextEx.cbXfer);
2398
2399 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
2400 aRespSegs[2].cbSeg = ContextEx.cbXfered;
2401 cSegs++;
2402 }
2403
2404 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2405 &aRespSegs[0], cSegs, true /*fAck*/);
2406}
2407
2408
2409/**
2410 * Processes a manipulate packet.
2411 *
2412 * @returns VBox status code.
2413 * @param pThis The KD context.
2414 */
2415static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
2416{
2417 int rc = VINF_SUCCESS;
2418 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
2419
2420 switch (pPktManip->Hdr.idReq)
2421 {
2422 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
2423 {
2424 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
2425 break;
2426 }
2427 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
2428 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
2429 {
2430 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
2431 break;
2432 }
2433 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
2434 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
2435 {
2436 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
2437 break;
2438 }
2439 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
2440 {
2441 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
2442 break;
2443 }
2444 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
2445 {
2446 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
2447 break;
2448 }
2449 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
2450 {
2451 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
2452 break;
2453 }
2454 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
2455 {
2456 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
2457 break;
2458 }
2459 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
2460 {
2461 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
2462 break;
2463 }
2464 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
2465 {
2466 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
2467 break;
2468 }
2469 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
2470 {
2471 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
2472 break;
2473 }
2474 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
2475 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
2476 break;
2477 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
2478 {
2479 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
2480 break;
2481 }
2482 default:
2483 KDPACKETMANIPULATEHDR RespHdr;
2484 RT_ZERO(RespHdr);
2485
2486 RespHdr.idReq = pPktManip->Hdr.idReq;
2487 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2488 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2489 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
2490 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2491 &RespHdr, sizeof(RespHdr), true /*fAck*/);
2492 break;
2493 }
2494
2495 return rc;
2496}
2497
2498
2499/**
2500 * Processes a fully received packet.
2501 *
2502 * @returns VBox status code.
2503 * @param pThis The KD context.
2504 */
2505static int dbgcKdCtxPktProcess(PKDCTX pThis)
2506{
2507 int rc = VINF_SUCCESS;
2508
2509 pThis->fBreakinRecv = false;
2510
2511 /* Verify checksum. */
2512 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
2513 {
2514 /** @todo Check packet id. */
2515 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
2516 {
2517 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
2518 rc = dbgcKdCtxPktSendAck(pThis);
2519 }
2520 if (RT_SUCCESS(rc))
2521 {
2522#ifdef LOG_ENABLED
2523 RTSGSEG Seg;
2524 Seg.pvSeg = &pThis->abBody[0];
2525 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
2526 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
2527#endif
2528
2529 switch (pThis->PktHdr.Fields.u16SubType)
2530 {
2531 case KD_PACKET_HDR_SUB_TYPE_RESET:
2532 {
2533 pThis->idPktNext = 0;
2534 rc = dbgcKdCtxPktSendReset(pThis);
2535 if (RT_SUCCESS(rc))
2536 {
2537 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2538 if (rc == VWRN_DBGF_ALREADY_HALTED)
2539 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2540 }
2541 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
2542 break;
2543 }
2544 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
2545 {
2546 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
2547 switch (enmMode)
2548 {
2549 case CPUMMODE_PROTECTED:
2550 {
2551 rc = VERR_NOT_IMPLEMENTED;
2552 break;
2553 }
2554 case CPUMMODE_LONG:
2555 {
2556 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
2557 rc = dbgcKdCtxPktManipulate64Process(pThis);
2558 break;
2559 }
2560 case CPUMMODE_REAL:
2561 default:
2562 rc = VERR_NOT_SUPPORTED;
2563 break;
2564 }
2565 break;
2566 }
2567 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
2568 case KD_PACKET_HDR_SUB_TYPE_RESEND:
2569 {
2570 /* Don't do anything. */
2571 rc = VINF_SUCCESS;
2572 break;
2573 }
2574 default:
2575 rc = VERR_NOT_IMPLEMENTED;
2576 }
2577 }
2578 }
2579 else
2580 {
2581 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
2582 rc = dbgcKdCtxPktSendResend(pThis);
2583 }
2584
2585 if (pThis->fBreakinRecv)
2586 {
2587 pThis->fBreakinRecv = false;
2588 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2589 if (rc == VWRN_DBGF_ALREADY_HALTED)
2590 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2591 }
2592
2593 /* Next packet. */
2594 dbgcKdCtxPktRecvReset(pThis);
2595 return rc;
2596}
2597
2598
2599/**
2600 * Processes the received data based on the current state.
2601 *
2602 * @returns VBox status code.
2603 * @param pThis The KD context.
2604 */
2605static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
2606{
2607 int rc = VINF_SUCCESS;
2608
2609 switch (pThis->enmState)
2610 {
2611 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
2612 {
2613 /* Does it look like a valid packet start?. */
2614 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
2615 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
2616 {
2617 pThis->pbRecv = &pThis->PktHdr.ab[1];
2618 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
2619 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
2620 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
2621 }
2622 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2623 {
2624 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2625 if (rc == VWRN_DBGF_ALREADY_HALTED)
2626 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
2627 dbgcKdCtxPktRecvReset(pThis);
2628 }
2629 /* else: Ignore and continue. */
2630 break;
2631 }
2632 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
2633 {
2634 /*
2635 * If the first and second byte differ there might be a single breakin
2636 * packet byte received and this is actually the start of a new packet.
2637 */
2638 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
2639 {
2640 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2641 {
2642 /* Halt the VM and rearrange the packet receiving state machine. */
2643 LogFlow(("DbgKd: Halting VM!\n"));
2644
2645 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2646 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
2647 pThis->pbRecv = &pThis->PktHdr.ab[1];
2648 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
2649 }
2650 else
2651 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
2652 }
2653 else
2654 {
2655 /* Normal packet receive continues with the rest of the header. */
2656 pThis->pbRecv = &pThis->PktHdr.ab[2];
2657 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
2658 pThis->enmState = KDRECVSTATE_PACKET_HDR;
2659 }
2660 break;
2661 }
2662 case KDRECVSTATE_PACKET_HDR:
2663 {
2664 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
2665 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
2666 {
2667 /* Start receiving the body. */
2668 if (pThis->PktHdr.Fields.cbBody)
2669 {
2670 pThis->pbRecv = &pThis->abBody[0];
2671 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
2672 pThis->enmState = KDRECVSTATE_PACKET_BODY;
2673 }
2674 else /* No body means no trailer byte it looks like. */
2675 rc = dbgcKdCtxPktProcess(pThis);
2676 }
2677 else
2678 rc = VERR_NET_PROTOCOL_ERROR;
2679 break;
2680 }
2681 case KDRECVSTATE_PACKET_BODY:
2682 {
2683 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
2684 pThis->bTrailer = 0;
2685 pThis->pbRecv = &pThis->bTrailer;
2686 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
2687 break;
2688 }
2689 case KDRECVSTATE_PACKET_TRAILER:
2690 {
2691 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
2692 rc = dbgcKdCtxPktProcess(pThis);
2693 else
2694 rc = VERR_NET_PROTOCOL_ERROR;
2695 break;
2696 }
2697 default:
2698 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
2699 }
2700
2701 return rc;
2702}
2703
2704
2705/**
2706 * Receive data and processes complete packets.
2707 *
2708 * @returns Status code.
2709 * @param pThis The KD context.
2710 */
2711static int dbgcKdCtxRecv(PKDCTX pThis)
2712{
2713 int rc = VINF_SUCCESS;
2714
2715 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
2716
2717 if (pThis->cbRecvLeft)
2718 {
2719 size_t cbRead = 0;
2720 rc = pThis->Dbgc.pBack->pfnRead(pThis->Dbgc.pBack, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
2721 if (RT_SUCCESS(rc))
2722 {
2723 pThis->tsRecvLast = RTTimeMilliTS();
2724 pThis->cbRecvLeft -= cbRead;
2725 pThis->pbRecv += cbRead;
2726 if (!pThis->cbRecvLeft)
2727 rc = dbgcKdCtxRecvDataProcess(pThis);
2728 }
2729 }
2730
2731 LogFlowFunc(("returns rc=%Rrc\n", rc));
2732 return rc;
2733}
2734
2735
2736/**
2737 * Processes debugger events.
2738 *
2739 * @returns VBox status code.
2740 * @param pThis The KD context data.
2741 * @param pEvent Pointer to event data.
2742 */
2743static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
2744{
2745 /*
2746 * Process the event.
2747 */
2748 //PDBGC pDbgc = &pThis->Dbgc;
2749 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
2750 pThis->Dbgc.iArg = 0;
2751 int rc = VINF_SUCCESS;
2752 switch (pEvent->enmType)
2753 {
2754 /*
2755 * The first part is events we have initiated with commands.
2756 */
2757 case DBGFEVENT_HALT_DONE:
2758 {
2759 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
2760 break;
2761 }
2762
2763 /*
2764 * The second part is events which can occur at any time.
2765 */
2766#if 0
2767 case DBGFEVENT_FATAL_ERROR:
2768 {
2769 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
2770 dbgcGetEventCtx(pEvent->enmCtx));
2771 if (RT_SUCCESS(rc))
2772 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
2773 break;
2774 }
2775#endif
2776
2777 case DBGFEVENT_BREAKPOINT:
2778 case DBGFEVENT_BREAKPOINT_IO:
2779 case DBGFEVENT_BREAKPOINT_MMIO:
2780 case DBGFEVENT_BREAKPOINT_HYPER:
2781 case DBGFEVENT_STEPPED:
2782 case DBGFEVENT_STEPPED_HYPER:
2783 {
2784 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
2785 break;
2786 }
2787
2788#if 0
2789 case DBGFEVENT_ASSERTION_HYPER:
2790 {
2791 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
2792 "\ndbgf event: Hypervisor Assertion! (%s)\n"
2793 "%s"
2794 "%s"
2795 "\n",
2796 dbgcGetEventCtx(pEvent->enmCtx),
2797 pEvent->u.Assert.pszMsg1,
2798 pEvent->u.Assert.pszMsg2);
2799 if (RT_SUCCESS(rc))
2800 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
2801 break;
2802 }
2803
2804 case DBGFEVENT_DEV_STOP:
2805 {
2806 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
2807 "\n"
2808 "dbgf event: DBGFSTOP (%s)\n"
2809 "File: %s\n"
2810 "Line: %d\n"
2811 "Function: %s\n",
2812 dbgcGetEventCtx(pEvent->enmCtx),
2813 pEvent->u.Src.pszFile,
2814 pEvent->u.Src.uLine,
2815 pEvent->u.Src.pszFunction);
2816 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
2817 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
2818 "Message: %s\n",
2819 pEvent->u.Src.pszMessage);
2820 if (RT_SUCCESS(rc))
2821 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
2822 break;
2823 }
2824
2825
2826 case DBGFEVENT_INVALID_COMMAND:
2827 {
2828 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
2829 break;
2830 }
2831#endif
2832
2833 case DBGFEVENT_POWERING_OFF:
2834 {
2835 pThis->Dbgc.fReady = false;
2836 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, false);
2837 rc = VERR_GENERAL_FAILURE;
2838 break;
2839 }
2840
2841#if 0
2842 default:
2843 {
2844 /*
2845 * Probably a generic event. Look it up to find its name.
2846 */
2847 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
2848 if (pEvtDesc)
2849 {
2850 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
2851 {
2852 Assert(pEvtDesc->pszDesc);
2853 Assert(pEvent->u.Generic.cArgs == 1);
2854 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
2855 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
2856 }
2857 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
2858 {
2859 Assert(pEvent->u.Generic.cArgs >= 5);
2860 char szDetails[512];
2861 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
2862 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
2863 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
2864 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
2865 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
2866 szDetails);
2867 }
2868 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
2869 || pEvent->u.Generic.cArgs > 1
2870 || ( pEvent->u.Generic.cArgs == 1
2871 && pEvent->u.Generic.auArgs[0] != 0))
2872 {
2873 if (pEvtDesc->pszDesc)
2874 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
2875 pEvtDesc->pszName, pEvtDesc->pszDesc);
2876 else
2877 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
2878 if (pEvent->u.Generic.cArgs <= 1)
2879 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
2880 else
2881 {
2882 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
2883 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
2884 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
2885 }
2886 }
2887 else
2888 {
2889 if (pEvtDesc->pszDesc)
2890 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
2891 pEvtDesc->pszName, pEvtDesc->pszDesc);
2892 else
2893 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
2894 }
2895 }
2896 else
2897 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
2898 break;
2899 }
2900#else
2901 default:
2902 rc = VERR_NOT_IMPLEMENTED;
2903 break;
2904#endif
2905 }
2906
2907 return rc;
2908}
2909
2910
2911/**
2912 * Handle a receive timeout.
2913 *
2914 * @returns VBox status code.
2915 * @param pThis Pointer to the KD context.
2916 */
2917static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
2918{
2919 int rc = VINF_SUCCESS;
2920
2921 LogFlowFunc(("pThis=%p\n", pThis));
2922
2923 /*
2924 * If a single breakin packet byte was received but the header is otherwise incomplete
2925 * the VM is halted and a state change will be sent in the event processing loop.
2926 */
2927 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
2928 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2929 {
2930 LogFlow(("DbgKd: Halting VM!\n"));
2931 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
2932 }
2933 else /* Send a reset packet (@todo Figure out the semantics in this case exactly). */
2934 rc = dbgcKdCtxPktSendReset(pThis);
2935
2936 dbgcKdCtxPktRecvReset(pThis);
2937
2938 LogFlowFunc(("rc=%Rrc\n", rc));
2939 return rc;
2940}
2941
2942
2943/**
2944 * Run the debugger console.
2945 *
2946 * @returns VBox status code.
2947 * @param pThis Pointer to the KD context.
2948 */
2949int dbgcKdRun(PKDCTX pThis)
2950{
2951 /*
2952 * We're ready for commands now.
2953 */
2954 pThis->Dbgc.fReady = true;
2955 pThis->Dbgc.pBack->pfnSetReady(pThis->Dbgc.pBack, true);
2956
2957 /*
2958 * Main Debugger Loop.
2959 *
2960 * This loop will either block on waiting for input or on waiting on
2961 * debug events. If we're forwarding the log we cannot wait for long
2962 * before we must flush the log.
2963 */
2964 int rc;
2965 for (;;)
2966 {
2967 rc = VERR_SEM_OUT_OF_TURN;
2968 if (pThis->Dbgc.pUVM)
2969 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
2970
2971 if (RT_SUCCESS(rc))
2972 {
2973 /*
2974 * Wait for a debug event.
2975 */
2976 DBGFEVENT Evt;
2977 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
2978 if (RT_SUCCESS(rc))
2979 {
2980 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
2981 if (RT_FAILURE(rc))
2982 break;
2983 }
2984 else if (rc != VERR_TIMEOUT)
2985 break;
2986
2987 /*
2988 * Check for input.
2989 */
2990 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 0))
2991 {
2992 rc = dbgcKdCtxRecv(pThis);
2993 if (RT_FAILURE(rc))
2994 break;
2995 }
2996 }
2997 else if (rc == VERR_SEM_OUT_OF_TURN)
2998 {
2999 /*
3000 * Wait for input.
3001 */
3002 if (pThis->Dbgc.pBack->pfnInput(pThis->Dbgc.pBack, 1000))
3003 {
3004 rc = dbgcKdCtxRecv(pThis);
3005 if (RT_FAILURE(rc))
3006 break;
3007 }
3008 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
3009 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
3010 rc = dbgcKdCtxRecvTimeout(pThis);
3011 }
3012 else
3013 break;
3014 }
3015
3016 return rc;
3017}
3018
3019
3020/**
3021 * Creates a KD context instance with the given backend.
3022 *
3023 * @returns VBox status code.
3024 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
3025 * @param pBack The backend to use for I/O.
3026 * @param fFlags Flags controlling the behavior.
3027 */
3028static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PDBGCBACK pBack, unsigned fFlags)
3029{
3030 /*
3031 * Validate input.
3032 */
3033 AssertPtrReturn(pBack, VERR_INVALID_POINTER);
3034 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
3035
3036 /*
3037 * Allocate and initialize.
3038 */
3039 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
3040 if (!pThis)
3041 return VERR_NO_MEMORY;
3042
3043 dbgcInitCmdHlp(&pThis->Dbgc);
3044 /*
3045 * This is compied from the native debug console (will be used for monitor commands)
3046 * in DBGCConsole.cpp. Try to keep both functions in sync.
3047 */
3048 pThis->Dbgc.pBack = pBack;
3049 /*pThis->Dbgc.pfnOutput = dbgcOutputGdb;*/
3050 pThis->Dbgc.pvOutputUser = pThis;
3051 pThis->Dbgc.pVM = NULL;
3052 pThis->Dbgc.pUVM = NULL;
3053 pThis->Dbgc.idCpu = 0;
3054 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
3055 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
3056 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
3057 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
3058 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
3059 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
3060 //pThis->Dbgc.fLog = false;
3061 pThis->Dbgc.fRegTerse = true;
3062 pThis->Dbgc.fStepTraceRegs = true;
3063 //pThis->Dbgc.cPagingHierarchyDumps = 0;
3064 //pThis->Dbgc.DisasmPos = {0};
3065 //pThis->Dbgc.SourcePos = {0};
3066 //pThis->Dbgc.DumpPos = {0};
3067 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
3068 //pThis->Dbgc.cbDumpElement = 0;
3069 //pThis->Dbgc.cVars = 0;
3070 //pThis->Dbgc.paVars = NULL;
3071 //pThis->Dbgc.pPlugInHead = NULL;
3072 //pThis->Dbgc.pFirstBp = NULL;
3073 //pThis->Dbgc.abSearch = {0};
3074 //pThis->Dbgc.cbSearch = 0;
3075 pThis->Dbgc.cbSearchUnit = 1;
3076 pThis->Dbgc.cMaxSearchHits = 1;
3077 //pThis->Dbgc.SearchAddr = {0};
3078 //pThis->Dbgc.cbSearchRange = 0;
3079
3080 //pThis->Dbgc.uInputZero = 0;
3081 //pThis->Dbgc.iRead = 0;
3082 //pThis->Dbgc.iWrite = 0;
3083 //pThis->Dbgc.cInputLines = 0;
3084 //pThis->Dbgc.fInputOverflow = false;
3085 pThis->Dbgc.fReady = true;
3086 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
3087 //pThis->Dbgc.iArg = 0;
3088 //pThis->Dbgc.rcOutput = 0;
3089 //pThis->Dbgc.rcCmd = 0;
3090
3091 //pThis->Dbgc.pszHistoryFile = NULL;
3092 //pThis->Dbgc.pszGlobalInitScript = NULL;
3093 //pThis->Dbgc.pszLocalInitScript = NULL;
3094
3095 dbgcEvalInit();
3096
3097 pThis->fBreakinRecv = false;
3098 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
3099 pThis->pIfWinNt = NULL;
3100 dbgcKdCtxPktRecvReset(pThis);
3101
3102 *ppKdCtx = pThis;
3103 return VINF_SUCCESS;
3104}
3105
3106
3107/**
3108 * Destroys the given KD context.
3109 *
3110 * @returns nothing.
3111 * @param pThis The KD context to destroy.
3112 */
3113static void dbgcKdCtxDestroy(PKDCTX pThis)
3114{
3115 AssertPtr(pThis);
3116
3117 pThis->pIfWinNt = NULL;
3118
3119 /* Detach from the VM. */
3120 if (pThis->Dbgc.pUVM)
3121 DBGFR3Detach(pThis->Dbgc.pUVM);
3122
3123 /* Free config strings. */
3124 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
3125 pThis->Dbgc.pszGlobalInitScript = NULL;
3126 RTStrFree(pThis->Dbgc.pszLocalInitScript);
3127 pThis->Dbgc.pszLocalInitScript = NULL;
3128 RTStrFree(pThis->Dbgc.pszHistoryFile);
3129 pThis->Dbgc.pszHistoryFile = NULL;
3130
3131 /* Finally, free the instance memory. */
3132 RTMemFree(pThis);
3133}
3134
3135
3136DECLHIDDEN(int) dbgcKdStubCreate(PUVM pUVM, PDBGCBACK pBack, unsigned fFlags)
3137{
3138 /*
3139 * Validate input.
3140 */
3141 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
3142 PVM pVM = NULL;
3143 if (pUVM)
3144 {
3145 pVM = VMR3GetVM(pUVM);
3146 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
3147 }
3148
3149 /*
3150 * Allocate and initialize instance data
3151 */
3152 PKDCTX pThis;
3153 int rc = dbgcKdCtxCreate(&pThis, pBack, fFlags);
3154 if (RT_FAILURE(rc))
3155 return rc;
3156 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
3157 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
3158
3159 /*
3160 * Attach to the specified VM.
3161 */
3162 if (RT_SUCCESS(rc) && pUVM)
3163 {
3164 rc = DBGFR3Attach(pUVM);
3165 if (RT_SUCCESS(rc))
3166 {
3167 pThis->Dbgc.pVM = pVM;
3168 pThis->Dbgc.pUVM = pUVM;
3169 pThis->Dbgc.idCpu = 0;
3170
3171 /* Try detecting a Windows NT guest. */
3172 char szName[64];
3173 rc = DBGFR3OSDetect(pUVM, szName, sizeof(szName));
3174 if (RT_SUCCESS(rc))
3175 {
3176 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pUVM, DBGFOSINTERFACE_WINNT);
3177 if (pThis->pIfWinNt)
3178 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3179 else
3180 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3181 }
3182 else
3183 {
3184 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3185 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3186 }
3187 }
3188 else
3189 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
3190 }
3191
3192 /*
3193 * Load plugins.
3194 */
3195 if (RT_SUCCESS(rc))
3196 {
3197 if (pVM)
3198 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
3199 dbgcEventInit(&pThis->Dbgc);
3200
3201 /*
3202 * Run the debugger main loop.
3203 */
3204 rc = dbgcKdRun(pThis);
3205 dbgcEventTerm(&pThis->Dbgc);
3206 }
3207
3208 /*
3209 * Cleanup console debugger session.
3210 */
3211 dbgcKdCtxDestroy(pThis);
3212 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
3213}
3214
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