VirtualBox

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

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