VirtualBox

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

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

Debugger/DBGCRemoteKd: Implement basic breakpoint handling

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