VirtualBox

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

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

Debugger/DBGCRemoteKd: Some fixes and implement basic continue/continue2 requests, allows basic control over the VM. WinDbg can now successfully query the state and continue/single step the VM

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