VirtualBox

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

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

Debugger/RemoteKd: Add beginnings of debug stub talking the KD remote protocol (WinDbg and friends), heavy work in progress [scm fix]

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