VirtualBox

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

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

Debugger: doxygen fix attempt

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 160.6 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 87580 2021-02-03 15:48:29Z 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 - buffer overflow. */
54#define NTSTATUS_BUFFER_OVERFLOW UINT32_C(0x80000005)
55/** NT status code - operation unsuccesful. */
56#define NTSTATUS_UNSUCCESSFUL UINT32_C(0xc0000001)
57/** NT status code - operation not implemented. */
58#define NTSTATUS_NOT_IMPLEMENTED UINT32_C(0xc0000002)
59/** NT status code - Object not found. */
60#define NTSTATUS_NOT_FOUND UINT32_C(0xc0000225)
61
62/** Offset where the KD version block pointer is stored in the KPCR.
63 * From: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kprcb/amd64.htm */
64#define KD_KPCR_VERSION_BLOCK_ADDR_OFF 0x34
65
66
67/*********************************************************************************************************************************
68* Structures and Typedefs *
69*********************************************************************************************************************************/
70
71/**
72 * KD packet header as sent over the wire.
73 */
74typedef struct KDPACKETHDR
75{
76 /** Packet signature (leader) - defines the type of packet. */
77 uint32_t u32Signature;
78 /** Packet (sub) type. */
79 uint16_t u16SubType;
80 /** Size of the packet body in bytes.*/
81 uint16_t cbBody;
82 /** Packet ID. */
83 uint32_t idPacket;
84 /** Checksum of the packet body. */
85 uint32_t u32ChkSum;
86} KDPACKETHDR;
87AssertCompileSize(KDPACKETHDR, 16);
88/** Pointer to a packet header. */
89typedef KDPACKETHDR *PKDPACKETHDR;
90/** Pointer to a const packet header. */
91typedef const KDPACKETHDR *PCKDPACKETHDR;
92
93/** Signature for a data packet. */
94#define KD_PACKET_HDR_SIGNATURE_DATA UINT32_C(0x30303030)
95/** First byte for a data packet header. */
96#define KD_PACKET_HDR_SIGNATURE_DATA_BYTE 0x30
97/** Signature for a control packet. */
98#define KD_PACKET_HDR_SIGNATURE_CONTROL UINT32_C(0x69696969)
99/** First byte for a control packet header. */
100#define KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE 0x69
101/** Signature for a breakin packet. */
102#define KD_PACKET_HDR_SIGNATURE_BREAKIN UINT32_C(0x62626262)
103/** First byte for a breakin packet header. */
104#define KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE 0x62
105
106/** @name Packet sub types.
107 * @{ */
108#define KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32 UINT16_C(1)
109#define KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE UINT16_C(2)
110#define KD_PACKET_HDR_SUB_TYPE_DEBUG_IO UINT16_C(3)
111#define KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE UINT16_C(4)
112#define KD_PACKET_HDR_SUB_TYPE_RESEND UINT16_C(5)
113#define KD_PACKET_HDR_SUB_TYPE_RESET UINT16_C(6)
114#define KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64 UINT16_C(7)
115#define KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN UINT16_C(8)
116#define KD_PACKET_HDR_SUB_TYPE_TRACE_IO UINT16_C(9)
117#define KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST UINT16_C(10)
118#define KD_PACKET_HDR_SUB_TYPE_FILE_IO UINT16_C(11)
119#define KD_PACKET_HDR_SUB_TYPE_MAX UINT16_C(12)
120/** @} */
121
122/** Initial packet ID value. */
123#define KD_PACKET_HDR_ID_INITIAL UINT32_C(0x80800800)
124/** Packet ID value after a resync. */
125#define KD_PACKET_HDR_ID_RESET UINT32_C(0x80800000)
126
127/** Trailing byte of a packet. */
128#define KD_PACKET_TRAILING_BYTE 0xaa
129
130
131/** Maximum number of parameters in the exception record. */
132#define KDPACKETEXCP_PARMS_MAX 15
133
134/**
135 * 64bit exception record.
136 */
137typedef struct KDPACKETEXCP64
138{
139 /** The exception code identifying the excpetion. */
140 uint32_t u32ExcpCode;
141 /** Flags associated with the exception. */
142 uint32_t u32ExcpFlags;
143 /** Pointer to a chained exception record. */
144 uint64_t u64PtrExcpRecNested;
145 /** Address where the exception occurred. */
146 uint64_t u64PtrExcpAddr;
147 /** Number of parameters in the exception information array. */
148 uint32_t cExcpParms;
149 /** Alignment. */
150 uint32_t u32Alignment;
151 /** Exception parameters array. */
152 uint64_t au64ExcpParms[KDPACKETEXCP_PARMS_MAX];
153} KDPACKETEXCP64;
154AssertCompileSize(KDPACKETEXCP64, 152);
155/** Pointer to an exception record. */
156typedef KDPACKETEXCP64 *PKDPACKETEXCP64;
157/** Pointer to a const exception record. */
158typedef const KDPACKETEXCP64 *PCKDPACKETEXCP64;
159
160
161/**
162 * amd64 NT context structure.
163 */
164typedef struct NTCONTEXT64
165{
166 /** The P[1-6]Home members. */
167 uint64_t au64PHome[6];
168 /** Context flags indicating the valid bits, see NTCONTEXT_F_XXX. */
169 uint32_t fContext;
170 /** MXCSR register. */
171 uint32_t u32RegMxCsr;
172 /** CS selector. */
173 uint16_t u16SegCs;
174 /** DS selector. */
175 uint16_t u16SegDs;
176 /** ES selector. */
177 uint16_t u16SegEs;
178 /** FS selector. */
179 uint16_t u16SegFs;
180 /** GS selector. */
181 uint16_t u16SegGs;
182 /** SS selector. */
183 uint16_t u16SegSs;
184 /** EFlags register. */
185 uint32_t u32RegEflags;
186 /** DR0 register. */
187 uint64_t u64RegDr0;
188 /** DR1 register. */
189 uint64_t u64RegDr1;
190 /** DR2 register. */
191 uint64_t u64RegDr2;
192 /** DR3 register. */
193 uint64_t u64RegDr3;
194 /** DR6 register. */
195 uint64_t u64RegDr6;
196 /** DR7 register. */
197 uint64_t u64RegDr7;
198 /** RAX register. */
199 uint64_t u64RegRax;
200 /** RCX register. */
201 uint64_t u64RegRcx;
202 /** RDX register. */
203 uint64_t u64RegRdx;
204 /** RBX register. */
205 uint64_t u64RegRbx;
206 /** RSP register. */
207 uint64_t u64RegRsp;
208 /** RBP register. */
209 uint64_t u64RegRbp;
210 /** RSI register. */
211 uint64_t u64RegRsi;
212 /** RDI register. */
213 uint64_t u64RegRdi;
214 /** R8 register. */
215 uint64_t u64RegR8;
216 /** R9 register. */
217 uint64_t u64RegR9;
218 /** R10 register. */
219 uint64_t u64RegR10;
220 /** R11 register. */
221 uint64_t u64RegR11;
222 /** R12 register. */
223 uint64_t u64RegR12;
224 /** R13 register. */
225 uint64_t u64RegR13;
226 /** R14 register. */
227 uint64_t u64RegR14;
228 /** R15 register. */
229 uint64_t u64RegR15;
230 /** RIP register. */
231 uint64_t u64RegRip;
232 /** Extended floating point save area. */
233 X86FXSTATE FxSave;
234 /** AVX(?) vector registers. */
235 RTUINT128U aRegsVec[26];
236 /** Vector control register. */
237 uint64_t u64RegVecCtrl;
238 /** Debug control. */
239 uint64_t u64DbgCtrl;
240 /** @todo lbr */
241 uint64_t u64LastBrToRip;
242 uint64_t u64LastBrFromRip;
243 uint64_t u64LastExcpToRip;
244 uint64_t u64LastExcpFromRip;
245} NTCONTEXT64;
246AssertCompileSize(NTCONTEXT64, 1232);
247AssertCompileMemberOffset(NTCONTEXT64, FxSave, 0x100);
248AssertCompileMemberOffset(NTCONTEXT64, aRegsVec, 0x300);
249/** Pointer to an amd64 NT context. */
250typedef NTCONTEXT64 *PNTCONTEXT64;
251/** Pointer to a const amd64 NT context. */
252typedef const NTCONTEXT64 *PCNTCONTEXT64;
253
254
255/**
256 * 64bit [GI]DT descriptor.
257 */
258typedef struct NTKCONTEXTDESC64
259{
260 /** Alignment. */
261 uint16_t au16Alignment[3];
262 /** Limit. */
263 uint16_t u16Limit;
264 /** Base address. */
265 uint64_t u64PtrBase;
266} NTKCONTEXTDESC64;
267AssertCompileSize(NTKCONTEXTDESC64, 2 * 8);
268/** Pointer to a 64bit [GI]DT descriptor. */
269typedef NTKCONTEXTDESC64 *PNTKCONTEXTDESC64;
270/** Pointer to a const 64bit [GI]DT descriptor. */
271typedef const NTKCONTEXTDESC64 *PCNTKCONTEXTDESC64;
272
273
274/**
275 * Kernel context as queried by KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE
276 */
277typedef struct NTKCONTEXT64
278{
279 /** CR0 register. */
280 uint64_t u64RegCr0;
281 /** CR2 register. */
282 uint64_t u64RegCr2;
283 /** CR3 register. */
284 uint64_t u64RegCr3;
285 /** CR4 register. */
286 uint64_t u64RegCr4;
287 /** DR0 register. */
288 uint64_t u64RegDr0;
289 /** DR1 register. */
290 uint64_t u64RegDr1;
291 /** DR2 register. */
292 uint64_t u64RegDr2;
293 /** DR3 register. */
294 uint64_t u64RegDr3;
295 /** DR6 register. */
296 uint64_t u64RegDr6;
297 /** DR7 register. */
298 uint64_t u64RegDr7;
299 /** GDTR. */
300 NTKCONTEXTDESC64 Gdtr;
301 /** IDTR. */
302 NTKCONTEXTDESC64 Idtr;
303 /** TR register. */
304 uint16_t u16RegTr;
305 /** LDTR register. */
306 uint16_t u16RegLdtr;
307 /** MXCSR register. */
308 uint32_t u32RegMxCsr;
309 /** Debug control. */
310 uint64_t u64DbgCtrl;
311 /** @todo lbr */
312 uint64_t u64LastBrToRip;
313 uint64_t u64LastBrFromRip;
314 uint64_t u64LastExcpToRip;
315 uint64_t u64LastExcpFromRip;
316 /** CR8 register. */
317 uint64_t u64RegCr8;
318 /** GS base MSR register. */
319 uint64_t u64MsrGsBase;
320 /** Kernel GS base MSR register. */
321 uint64_t u64MsrKernelGsBase;
322 /** STAR MSR register. */
323 uint64_t u64MsrStar;
324 /** LSTAR MSR register. */
325 uint64_t u64MsrLstar;
326 /** CSTAR MSR register. */
327 uint64_t u64MsrCstar;
328 /** SFMASK MSR register. */
329 uint64_t u64MsrSfMask;
330 /** XCR0 register. */
331 uint64_t u64RegXcr0;
332 /** Standard context. */
333 NTCONTEXT64 Ctx;
334} NTKCONTEXT64;
335AssertCompileMemberOffset(NTKCONTEXT64, Ctx, 224);
336/** Pointer to an amd64 NT context. */
337typedef NTKCONTEXT64 *PNTKCONTEXT64;
338/** Pointer to a const amd64 NT context. */
339typedef const NTKCONTEXT64 *PCNTKCONTEXT64;
340
341
342/**
343 * 32bit context FPU save area.
344 */
345typedef struct NTCONTEXT32_FPU_SAVE_AREA
346{
347 uint32_t u32CtrlWord;
348 uint32_t u32StatusWord;
349 uint32_t u32TagWord;
350 uint32_t u32ErrorOff;
351 uint32_t u32ErrorSel;
352 uint32_t u32DataOff;
353 uint32_t u32DataSel;
354 uint8_t abRegArea[80];
355 uint32_t u32Cr0Npx;
356} NTCONTEXT32_FPU_SAVE_AREA;
357/** Pointer to an 32bit context FPU save area. */
358typedef NTCONTEXT32_FPU_SAVE_AREA *PNTCONTEXT32_FPU_SAVE_AREA;
359/** Pointer to a const 32bit context FPU save area. */
360typedef const NTCONTEXT32_FPU_SAVE_AREA *PCNTCONTEXT32_FPU_SAVE_AREA;
361
362
363/**
364 * i386 NT context structure.
365 */
366typedef struct NTCONTEXT32
367{
368 /** Context flags indicating the valid bits, see NTCONTEXT_F_XXX. */
369 uint32_t fContext;
370 /** DR0 register. */
371 uint32_t u32RegDr0;
372 /** DR1 register. */
373 uint32_t u32RegDr1;
374 /** DR2 register. */
375 uint32_t u32RegDr2;
376 /** DR3 register. */
377 uint32_t u32RegDr3;
378 /** DR6 register. */
379 uint32_t u32RegDr6;
380 /** DR7 register. */
381 uint32_t u32RegDr7;
382 /** Floating point save area. */
383 NTCONTEXT32_FPU_SAVE_AREA FloatSave;
384 /** GS segment. */
385 uint32_t u32SegGs;
386 /** FS segment. */
387 uint32_t u32SegFs;
388 /** ES segment. */
389 uint32_t u32SegEs;
390 /** DS segment. */
391 uint32_t u32SegDs;
392 /** EDI register. */
393 uint32_t u32RegEdi;
394 /** ESI register. */
395 uint32_t u32RegEsi;
396 /** EBX register. */
397 uint32_t u32RegEbx;
398 /** EDX register. */
399 uint32_t u32RegEdx;
400 /** ECX register. */
401 uint32_t u32RegEcx;
402 /** EAX register. */
403 uint32_t u32RegEax;
404 /** EBP register. */
405 uint32_t u32RegEbp;
406 /** EIP register. */
407 uint32_t u32RegEip;
408 /** CS segment. */
409 uint32_t u32SegCs;
410 /** EFLAGS register. */
411 uint32_t u32RegEflags;
412 /** ESP register. */
413 uint32_t u32RegEsp;
414 /** SS segment. */
415 uint32_t u32SegSs;
416 /** @todo Extended registers */
417 uint8_t abRegsExtended[512];
418} NTCONTEXT32;
419AssertCompileSize(NTCONTEXT32, 716);
420/** Pointer to an i386 NT context. */
421typedef NTCONTEXT32 *PNTCONTEXT32;
422/** Pointer to a const i386 NT context. */
423typedef const NTCONTEXT32 *PCNTCONTEXT32;
424
425
426/**
427 * 32bit [GI]DT descriptor.
428 */
429typedef struct NTKCONTEXTDESC32
430{
431 /** Alignment. */
432 uint16_t u16Alignment;
433 /** Limit. */
434 uint16_t u16Limit;
435 /** Base address. */
436 uint32_t u32PtrBase;
437} NTKCONTEXTDESC32;
438AssertCompileSize(NTKCONTEXTDESC32, 2 * 4);
439/** Pointer to an 32bit [GI]DT descriptor. */
440typedef NTKCONTEXTDESC32 *PNTKCONTEXTDESC32;
441/** Pointer to a const 32bit [GI]DT descriptor. */
442typedef const NTKCONTEXTDESC32 *PCNTKCONTEXTDESC32;
443
444
445/**
446 * 32bit Kernel context as queried by KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE
447 */
448typedef struct NTKCONTEXT32
449{
450 /** CR0 register. */
451 uint32_t u32RegCr0;
452 /** CR2 register. */
453 uint32_t u32RegCr2;
454 /** CR3 register. */
455 uint32_t u32RegCr3;
456 /** CR4 register. */
457 uint32_t u32RegCr4;
458 /** DR0 register. */
459 uint32_t u32RegDr0;
460 /** DR1 register. */
461 uint32_t u32RegDr1;
462 /** DR2 register. */
463 uint32_t u32RegDr2;
464 /** DR3 register. */
465 uint32_t u32RegDr3;
466 /** DR6 register. */
467 uint32_t u32RegDr6;
468 /** DR7 register. */
469 uint32_t u32RegDr7;
470 /** GDTR. */
471 NTKCONTEXTDESC32 Gdtr;
472 /** IDTR. */
473 NTKCONTEXTDESC32 Idtr;
474 /** TR register. */
475 uint16_t u16RegTr;
476 /** LDTR register. */
477 uint16_t u16RegLdtr;
478 /** Padding. */
479 uint8_t abPad[24];
480} NTKCONTEXT32;
481AssertCompileSize(NTKCONTEXT32, 84);
482/** Pointer to an i386 NT context. */
483typedef NTKCONTEXT32 *PNTKCONTEXT32;
484/** Pointer to a const i386 NT context. */
485typedef const NTKCONTEXT32 *PCNTKCONTEXT32;
486
487
488/** x86 context. */
489#define NTCONTEXT_F_X86 UINT32_C(0x00010000)
490/** AMD64 context. */
491#define NTCONTEXT_F_AMD64 UINT32_C(0x00100000)
492/** Control registers valid (CS, (R)SP, (R)IP, FLAGS and BP). */
493#define NTCONTEXT_F_CONTROL RT_BIT_32(0)
494/** Integer registers valid. */
495#define NTCONTEXT_F_INTEGER RT_BIT_32(1)
496/** Segment registers valid. */
497#define NTCONTEXT_F_SEGMENTS RT_BIT_32(2)
498/** Floating point registers valid. */
499#define NTCONTEXT_F_FLOATING_POINT RT_BIT_32(3)
500/** Debug registers valid. */
501#define NTCONTEXT_F_DEBUG RT_BIT_32(4)
502/** Extended registers valid (x86 only). */
503#define NTCONTEXT_F_EXTENDED RT_BIT_32(5)
504/** Full x86 context valid. */
505#define NTCONTEXT32_F_FULL (NTCONTEXT_F_X86 | NTCONTEXT_F_CONTROL | NTCONTEXT_F_INTEGER | NTCONTEXT_F_SEGMENTS)
506/** Full amd64 context valid. */
507#define NTCONTEXT64_F_FULL (NTCONTEXT_F_AMD64 | NTCONTEXT_F_CONTROL | NTCONTEXT_F_INTEGER | NTCONTEXT_F_SEGMENTS)
508
509
510/**
511 * 32bit exception record.
512 */
513typedef struct KDPACKETEXCP32
514{
515 /** The exception code identifying the excpetion. */
516 uint32_t u32ExcpCode;
517 /** Flags associated with the exception. */
518 uint32_t u32ExcpFlags;
519 /** Pointer to a chained exception record. */
520 uint32_t u32PtrExcpRecNested;
521 /** Address where the exception occurred. */
522 uint32_t u32PtrExcpAddr;
523 /** Number of parameters in the exception information array. */
524 uint32_t cExcpParms;
525 /** Exception parameters array. */
526 uint32_t au32ExcpParms[KDPACKETEXCP_PARMS_MAX];
527} KDPACKETEXCP32;
528AssertCompileSize(KDPACKETEXCP32, 80);
529/** Pointer to an exception record. */
530typedef KDPACKETEXCP32 *PKDPACKETEXCP32;
531/** Pointer to a const exception record. */
532typedef const KDPACKETEXCP32 *PCKDPACKETEXCP32;
533
534
535/** @name Exception codes.
536 * @{ */
537/** A breakpoint was hit. */
538#define KD_PACKET_EXCP_CODE_BKPT UINT32_C(0x80000003)
539/** An instruction was single stepped. */
540#define KD_PACKET_EXCP_CODE_SINGLE_STEP UINT32_C(0x80000004)
541/** @} */
542
543
544/** Maximum number of bytes in the instruction stream. */
545#define KD_PACKET_CTRL_REPORT_INSN_STREAM_MAX 16
546
547/**
548 * 64bit control report record.
549 */
550typedef struct KDPACKETCTRLREPORT64
551{
552 /** Value of DR6. */
553 uint64_t u64RegDr6;
554 /** Value of DR7. */
555 uint64_t u64RegDr7;
556 /** EFLAGS. */
557 uint32_t u32RegEflags;
558 /** Number of instruction bytes in the instruction stream. */
559 uint16_t cbInsnStream;
560 /** Report flags. */
561 uint16_t fFlags;
562 /** The instruction stream. */
563 uint8_t abInsn[KD_PACKET_CTRL_REPORT_INSN_STREAM_MAX];
564 /** CS selector. */
565 uint16_t u16SegCs;
566 /** DS selector. */
567 uint16_t u16SegDs;
568 /** ES selector. */
569 uint16_t u16SegEs;
570 /** FS selector. */
571 uint16_t u16SegFs;
572} KDPACKETCTRLREPORT64;
573AssertCompileSize(KDPACKETCTRLREPORT64, 2 * 8 + 4 + 2 * 2 + 16 + 4 * 2);
574/** Pointer to a control report record. */
575typedef KDPACKETCTRLREPORT64 *PKDPACKETCTRLREPORT64;
576/** Pointer to a const control report record. */
577typedef const KDPACKETCTRLREPORT64 *PCKDPACKETCTRLREPORT64;
578
579
580/**
581 * 64bit state change packet body.
582 */
583typedef struct KDPACKETSTATECHANGE64
584{
585 /** The new state. */
586 uint32_t u32StateNew;
587 /** The processor level. */
588 uint16_t u16CpuLvl;
589 /** The processor ID generating the state change. */
590 uint16_t idCpu;
591 /** Number of processors in the system. */
592 uint32_t cCpus;
593 /** Alignment. */
594 uint32_t u32Alignment;
595 /** The thread ID currently executing when the state change occurred. */
596 uint64_t idThread;
597 /** Program counter of the thread. */
598 uint64_t u64RipThread;
599 /** Data based on the state. */
600 union
601 {
602 /** Exception occurred data. */
603 struct
604 {
605 /** The exception record. */
606 KDPACKETEXCP64 ExcpRec;
607 /** First chance(?). */
608 uint32_t u32FirstChance;
609 } Exception;
610 } u;
611 /** The control report */
612 union
613 {
614 /** AMD64 control report. */
615 KDPACKETCTRLREPORT64 Amd64;
616 } uCtrlReport;
617} KDPACKETSTATECHANGE64;
618//AssertCompileSize(KDPACKETSTATECHANGE64, 4 + 2 * 2 + 2 * 4 + 2 * 8 + sizeof(KDPACKETEXCP64) + 4 + sizeof(KDPACKETCTRLREPORT64));
619/** Pointer to a 64bit state change packet body. */
620typedef KDPACKETSTATECHANGE64 *PKDPACKETSTATECHANGE64;
621/** Pointer to a const 64bit state change packet body. */
622typedef const KDPACKETSTATECHANGE64 *PCKDPACKETSTATECHANGE64;
623
624
625/** @name State change state types.
626 * @{ */
627/** Minimum state change type. */
628#define KD_PACKET_STATE_CHANGE_MIN UINT32_C(0x00003030)
629/** An exception occured. */
630#define KD_PACKET_STATE_CHANGE_EXCEPTION KD_PACKET_STATE_CHANGE_MIN
631/** Symbols were loaded(?). */
632#define KD_PACKET_STATE_CHANGE_LOAD_SYMBOLS UINT32_C(0x00003031)
633/** Command string (custom command was executed?). */
634#define KD_PACKET_STATE_CHANGE_CMD_STRING UINT32_C(0x00003032)
635/** Maximum state change type (exclusive). */
636#define KD_PACKET_STATE_CHANGE_MAX UINT32_C(0x00003033)
637/** @} */
638
639
640/**
641 * Debug I/O payload.
642 */
643typedef struct KDPACKETDEBUGIO
644{
645 /** Debug I/O payload type (KD_PACKET_DEBUG_IO_STRING). */
646 uint32_t u32Type;
647 /** The processor level. */
648 uint16_t u16CpuLvl;
649 /** The processor ID generating this packet. */
650 uint16_t idCpu;
651 /** Type dependent data. */
652 union
653 {
654 /** Debug string sent. */
655 struct
656 {
657 /** Length of the string following in bytes. */
658 uint32_t cbStr;
659 /** Some padding it looks like. */
660 uint32_t u32Pad;
661 } Str;
662 /** Debug prompt. */
663 struct
664 {
665 /** Length of prompt. */
666 uint32_t cbPrompt;
667 /** Size of the string returned on success. */
668 uint32_t cbReturn;
669 } Prompt;
670 } u;
671} KDPACKETDEBUGIO;
672AssertCompileSize(KDPACKETDEBUGIO, 16);
673/** Pointer to a Debug I/O payload. */
674typedef KDPACKETDEBUGIO *PKDPACKETDEBUGIO;
675/** Pointer to a const Debug I/O payload. */
676typedef const KDPACKETDEBUGIO *PCKDPACKETDEBUGIO;
677
678
679/** @name Debug I/O types.
680 * @{ */
681/** Debug string output (usually DbgPrint() and friends). */
682#define KD_PACKET_DEBUG_IO_STRING UINT32_C(0x00003230)
683/** Get debug string (DbgPrompt()). */
684#define KD_PACKET_DEBUG_IO_GET_STRING UINT32_C(0x00003231)
685/** @} */
686
687
688/**
689 * 64bit get version manipulate payload.
690 */
691typedef struct KDPACKETMANIPULATE_GETVERSION64
692{
693 /** Major version. */
694 uint16_t u16VersMaj;
695 /** Minor version. */
696 uint16_t u16VersMin;
697 /** Protocol version. */
698 uint8_t u8VersProtocol;
699 /** KD secondary version. */
700 uint8_t u8VersKdSecondary;
701 /** Flags. */
702 uint16_t fFlags;
703 /** Machine type. */
704 uint16_t u16MachineType;
705 /** Maximum packet type. */
706 uint8_t u8MaxPktType;
707 /** Maximum state change */
708 uint8_t u8MaxStateChange;
709 /** Maximum manipulate request ID. */
710 uint8_t u8MaxManipulate;
711 /** Some simulation flag. */
712 uint8_t u8Simulation;
713 /** Padding. */
714 uint16_t u16Padding;
715 /** Kernel base. */
716 uint64_t u64PtrKernBase;
717 /** Pointer of the loaded module list head. */
718 uint64_t u64PtrPsLoadedModuleList;
719 /** Pointer of the debugger data list. */
720 uint64_t u64PtrDebuggerDataList;
721} KDPACKETMANIPULATE_GETVERSION64;
722AssertCompileSize(KDPACKETMANIPULATE_GETVERSION64, 40);
723/** Pointer to a 64bit get version manipulate payload. */
724typedef KDPACKETMANIPULATE_GETVERSION64 *PKDPACKETMANIPULATE_GETVERSION64;
725/** Pointer to a const 64bit get version manipulate payload. */
726typedef const KDPACKETMANIPULATE_GETVERSION64 *PCKDPACKETMANIPULATE_GETVERSION64;
727
728
729/** @name Get version flags.
730 * @{ */
731/** Flag whether this is a multi processor kernel. */
732#define KD_PACKET_MANIPULATE64_GET_VERSION_F_MP RT_BIT_32(0)
733/** Flag whether the pointer is 64bit. */
734#define KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64 RT_BIT_32(2)
735/** @} */
736
737
738/**
739 * 64bit memory transfer manipulate payload.
740 */
741typedef struct KDPACKETMANIPULATE_XFERMEM64
742{
743 /** Target base address. */
744 uint64_t u64PtrTarget;
745 /** Requested number of bytes to transfer*/
746 uint32_t cbXferReq;
747 /** Number of bytes actually transferred (response). */
748 uint32_t cbXfered;
749 /** Some padding?. */
750 uint64_t au64Pad[3];
751} KDPACKETMANIPULATE_XFERMEM64;
752AssertCompileSize(KDPACKETMANIPULATE_XFERMEM64, 40);
753/** Pointer to a 64bit memory transfer manipulate payload. */
754typedef KDPACKETMANIPULATE_XFERMEM64 *PKDPACKETMANIPULATE_XFERMEM64;
755/** Pointer to a const 64bit memory transfer manipulate payload. */
756typedef const KDPACKETMANIPULATE_XFERMEM64 *PCKDPACKETMANIPULATE_XFERMEM64;
757
758
759/**
760 * 64bit control space transfer manipulate payload.
761 *
762 * @note Same layout as the memory transfer but the pointer has a different meaning so
763 * we moved it into a separate request structure.
764 */
765typedef struct KDPACKETMANIPULATE_XFERCTRLSPACE64
766{
767 /** Identifier of the item to transfer in the control space. */
768 uint64_t u64IdXfer;
769 /** Requested number of bytes to transfer*/
770 uint32_t cbXferReq;
771 /** Number of bytes actually transferred (response). */
772 uint32_t cbXfered;
773 /** Some padding?. */
774 uint64_t au64Pad[3];
775} KDPACKETMANIPULATE_XFERCTRLSPACE64;
776AssertCompileSize(KDPACKETMANIPULATE_XFERCTRLSPACE64, 40);
777/** Pointer to a 64bit memory transfer manipulate payload. */
778typedef KDPACKETMANIPULATE_XFERCTRLSPACE64 *PKDPACKETMANIPULATE_XFERCTRLSPACE64;
779/** Pointer to a const 64bit memory transfer manipulate payload. */
780typedef const KDPACKETMANIPULATE_XFERCTRLSPACE64 *PCKDPACKETMANIPULATE_XFERCTRLSPACE64;
781
782
783/** @name Known control space identifiers.
784 * @{ */
785/** Read/Write KPCR address. */
786#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR UINT64_C(0)
787/** Read/Write KPCRB address. */
788#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB UINT64_C(1)
789/** Read/Write Kernel context. */
790#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX UINT64_C(2)
791/** Read/Write current kernel thread. */
792#define KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD UINT64_C(3)
793/** @} */
794
795
796/**
797 * 64bit restore breakpoint manipulate payload.
798 */
799typedef struct KDPACKETMANIPULATE_RESTOREBKPT64
800{
801 /** The breakpoint handle to restore. */
802 uint32_t u32HndBkpt;
803 /** Blows up the request to the required size. */
804 uint8_t abPad[36];
805} KDPACKETMANIPULATE_RESTOREBKPT64;
806AssertCompileSize(KDPACKETMANIPULATE_RESTOREBKPT64, 40);
807/** Pointer to a 64bit restore breakpoint manipulate payload. */
808typedef KDPACKETMANIPULATE_RESTOREBKPT64 *PKDPACKETMANIPULATE_RESTOREBKPT64;
809/** Pointer to a const 64bit restore breakpoint manipulate payload. */
810typedef const KDPACKETMANIPULATE_RESTOREBKPT64 *PCKDPACKETMANIPULATE_RESTOREBKPT64;
811
812
813/**
814 * 64bit write breakpoint manipulate payload.
815 */
816typedef struct KDPACKETMANIPULATE_WRITEBKPT64
817{
818 /** Where to write the breakpoint. */
819 uint64_t u64PtrBkpt;
820 /** The breakpoint handle returned in the response. */
821 uint32_t u32HndBkpt;
822 /** Blows up the request to the required size. */
823 uint8_t abPad[28];
824} KDPACKETMANIPULATE_WRITEBKPT64;
825AssertCompileSize(KDPACKETMANIPULATE_WRITEBKPT64, 40);
826/** Pointer to a 64bit write breakpoint manipulate payload. */
827typedef KDPACKETMANIPULATE_WRITEBKPT64 *PKDPACKETMANIPULATE_WRITEBKPT64;
828/** Pointer to a const 64bit write breakpoint manipulate payload. */
829typedef const KDPACKETMANIPULATE_WRITEBKPT64 *PCKDPACKETMANIPULATE_WRITEBKPT64;
830
831
832/**
833 * Context extended manipulate payload.
834 */
835typedef struct KDPACKETMANIPULATE_CONTEXTEX
836{
837 /** Where to start copying the context. */
838 uint32_t offStart;
839 /** Number of bytes to transfer. */
840 uint32_t cbXfer;
841 /** Number of bytes actually transfered. */
842 uint32_t cbXfered;
843 /** Blows up the request to the required size. */
844 uint8_t abPad[28];
845} KDPACKETMANIPULATE_CONTEXTEX;
846AssertCompileSize(KDPACKETMANIPULATE_CONTEXTEX, 40);
847/** Pointer to a context extended manipulate payload. */
848typedef KDPACKETMANIPULATE_CONTEXTEX *PKDPACKETMANIPULATE_CONTEXTEX;
849/** Pointer to a const context extended manipulate payload. */
850typedef const KDPACKETMANIPULATE_CONTEXTEX *PCKDPACKETMANIPULATE_CONTEXTEX;
851
852
853/**
854 * Continue manipulate payload.
855 */
856typedef struct KDPACKETMANIPULATE_CONTINUE
857{
858 /** Continue (status?). */
859 uint32_t u32NtContSts;
860 /** Blows up the request to the required size. */
861 uint8_t abPad[36];
862} KDPACKETMANIPULATE_CONTINUE;
863AssertCompileSize(KDPACKETMANIPULATE_CONTINUE, 40);
864/** Pointer to a continue manipulate payload. */
865typedef KDPACKETMANIPULATE_CONTINUE *PKDPACKETMANIPULATE_CONTINUE;
866/** Pointer to a const continue manipulate payload. */
867typedef const KDPACKETMANIPULATE_CONTINUE *PCKDPACKETMANIPULATE_CONTINUE;
868
869
870/**
871 * Continue 2 manipulate payload.
872 */
873typedef struct KDPACKETMANIPULATE_CONTINUE2
874{
875 /** Continue (status?). */
876 uint32_t u32NtContSts;
877 /** Trace flag. */
878 uint32_t fTrace;
879 /** Bitsize dependent data. */
880 union
881 {
882 /** 32bit. */
883 struct
884 {
885 /** DR7 value to continue with. */
886 uint32_t u32RegDr7;
887 /** @todo (?) */
888 uint32_t u32SymCurStart;
889 uint32_t u32SymCurEnd;
890 } x86;
891 /** 64bit. */
892 struct
893 {
894 /** DR7 value to continue with. */
895 uint64_t u64RegDr7;
896 /** @todo (?) */
897 uint64_t u64SymCurStart;
898 uint64_t u64SymCurEnd;
899 } amd64;
900 } u;
901 /** Blows up the request to the required size. */
902 uint8_t abPad[8];
903} KDPACKETMANIPULATE_CONTINUE2;
904AssertCompileSize(KDPACKETMANIPULATE_CONTINUE2, 40);
905/** Pointer to a continue 2 manipulate payload. */
906typedef KDPACKETMANIPULATE_CONTINUE2 *PKDPACKETMANIPULATE_CONTINUE2;
907/** Pointer to a const continue 2 manipulate payload. */
908typedef const KDPACKETMANIPULATE_CONTINUE2 *PCKDPACKETMANIPULATE_CONTINUE2;
909
910
911/**
912 * Set context manipulate payload.
913 */
914typedef struct KDPACKETMANIPULATE_SETCONTEXT
915{
916 /** Continue (status?). */
917 uint32_t u32CtxFlags;
918 /** Blows up the request to the required size. */
919 uint8_t abPad[36];
920} KDPACKETMANIPULATE_SETCONTEXT;
921AssertCompileSize(KDPACKETMANIPULATE_SETCONTEXT, 40);
922/** Pointer to a set context manipulate payload. */
923typedef KDPACKETMANIPULATE_SETCONTEXT *PKDPACKETMANIPULATE_SETCONTEXT;
924/** Pointer to a const set context manipulate payload. */
925typedef const KDPACKETMANIPULATE_SETCONTEXT *PCKDPACKETMANIPULATE_SETCONTEXT;
926
927
928/**
929 * Query memory properties payload.
930 */
931typedef struct KDPACKETMANIPULATE_QUERYMEMORY
932{
933 /** The address to query the properties for. */
934 uint64_t u64GCPtr;
935 /** Reserved. */
936 uint64_t u64Rsvd;
937 /** Address space type on return. */
938 uint32_t u32AddrSpace;
939 /** Protection flags. */
940 uint32_t u32Flags;
941 /** Blows up the request to the required size. */
942 uint8_t abPad[16];
943} KDPACKETMANIPULATE_QUERYMEMORY;
944AssertCompileSize(KDPACKETMANIPULATE_QUERYMEMORY, 40);
945/** Pointer to a query memory properties payload. */
946typedef KDPACKETMANIPULATE_QUERYMEMORY *PKDPACKETMANIPULATE_QUERYMEMORY;
947/** Pointer to a const query memory properties payload. */
948typedef const KDPACKETMANIPULATE_QUERYMEMORY *PCKDPACKETMANIPULATE_QUERYMEMORY;
949
950
951/** @name Query memory address space identifiers.
952 * @{ */
953/** Process memory space. */
954#define KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_PROCESS UINT32_C(0)
955/** Session memory space. */
956#define KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_SESSION UINT32_C(1)
957/** Kernel memory space. */
958#define KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_KERNEL UINT32_C(2)
959/** @} */
960
961
962/** @name Query memory address protection flags.
963 * @{ */
964/** Readable. */
965#define KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_READ RT_BIT_32(0)
966/** Writable. */
967#define KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_WRITE RT_BIT_32(1)
968/** Executable. */
969#define KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_EXEC RT_BIT_32(2)
970/** Fixed address. */
971#define KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_FIXED RT_BIT_32(3)
972/** @} */
973
974
975/**
976 * Search memory payload.
977 */
978typedef struct KDPACKETMANIPULATE_SEARCHMEMORY
979{
980 /** The address to start searching at on input, found address on output. */
981 uint64_t u64GCPtr;
982 /** Number of bytes to search. */
983 uint64_t cbSearch;
984 /** Length of the pattern to search for following the payload. */
985 uint32_t cbPattern;
986 /** Padding to the required size. */
987 uint32_t au32Pad[5];
988} KDPACKETMANIPULATE_SEARCHMEMORY;
989AssertCompileSize(KDPACKETMANIPULATE_SEARCHMEMORY, 40);
990/** Pointer to a search memory properties payload. */
991typedef KDPACKETMANIPULATE_SEARCHMEMORY *PKDPACKETMANIPULATE_SEARCHMEMORY;
992/** Pointer to a const search memory properties payload. */
993typedef const KDPACKETMANIPULATE_SEARCHMEMORY *PCKDPACKETMANIPULATE_SEARCHMEMORY;
994
995
996/**
997 * Manipulate request packet header (Same for 32bit and 64bit).
998 */
999typedef struct KDPACKETMANIPULATEHDR
1000{
1001 /** The request to execute. */
1002 uint32_t idReq;
1003 /** The processor level to execute the request on. */
1004 uint16_t u16CpuLvl;
1005 /** The processor ID to execute the request on. */
1006 uint16_t idCpu;
1007 /** Return status code. */
1008 uint32_t u32NtStatus;
1009 /** Alignment. */
1010 uint32_t u32Alignment;
1011} KDPACKETMANIPULATEHDR;
1012AssertCompileSize(KDPACKETMANIPULATEHDR, 3 * 4 + 2 * 2);
1013/** Pointer to a manipulate request packet header. */
1014typedef KDPACKETMANIPULATEHDR *PKDPACKETMANIPULATEHDR;
1015/** Pointer to a const manipulate request packet header. */
1016typedef const KDPACKETMANIPULATEHDR *PCPKDPACKETMANIPULATEHDR;
1017
1018
1019/**
1020 * 64bit manipulate state request packet.
1021 */
1022typedef struct KDPACKETMANIPULATE64
1023{
1024 /** Header. */
1025 KDPACKETMANIPULATEHDR Hdr;
1026 /** Request payloads. */
1027 union
1028 {
1029 /** Get Version. */
1030 KDPACKETMANIPULATE_GETVERSION64 GetVersion;
1031 /** Read/Write memory. */
1032 KDPACKETMANIPULATE_XFERMEM64 XferMem;
1033 /** Continue. */
1034 KDPACKETMANIPULATE_CONTINUE Continue;
1035 /** Continue2. */
1036 KDPACKETMANIPULATE_CONTINUE2 Continue2;
1037 /** Set context. */
1038 KDPACKETMANIPULATE_SETCONTEXT SetContext;
1039 /** Read/Write control space. */
1040 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace;
1041 /** Restore breakpoint. */
1042 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt;
1043 /** Write breakpoint. */
1044 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt;
1045 /** Context extended. */
1046 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
1047 /** Query memory. */
1048 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
1049 /** Search memory. */
1050 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
1051 } u;
1052} KDPACKETMANIPULATE64;
1053AssertCompileSize(KDPACKETMANIPULATE64, 16 + 40);
1054/** Pointer to a 64bit manipulate state request packet. */
1055typedef KDPACKETMANIPULATE64 *PKDPACKETMANIPULATE64;
1056/** Pointer to a const 64bit manipulate state request packet. */
1057typedef const KDPACKETMANIPULATE64 *PCKDPACKETMANIPULATE64;
1058
1059/** @name Manipulate requests.
1060 * @{ */
1061/** Minimum available request. */
1062#define KD_PACKET_MANIPULATE_REQ_MIN UINT32_C(0x00003130)
1063/** Read virtual memory request. */
1064#define KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM KD_PACKET_MANIPULATE_REQ_MIN
1065/** Write virtual memory request. */
1066#define KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM UINT32_C(0x00003131)
1067/** Get context request. */
1068#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT UINT32_C(0x00003132)
1069/** Set context request. */
1070#define KD_PACKET_MANIPULATE_REQ_SET_CONTEXT UINT32_C(0x00003133)
1071/** Write breakpoint request. */
1072#define KD_PACKET_MANIPULATE_REQ_WRITE_BKPT UINT32_C(0x00003134)
1073/** Restore breakpoint request. */
1074#define KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT UINT32_C(0x00003135)
1075/** Continue request. */
1076#define KD_PACKET_MANIPULATE_REQ_CONTINUE UINT32_C(0x00003136)
1077/** Read control space request. */
1078#define KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE UINT32_C(0x00003137)
1079/** Write control space request. */
1080#define KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE UINT32_C(0x00003138)
1081/** Read I/O space request. */
1082#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE UINT32_C(0x00003139)
1083/** Write I/O space request. */
1084#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE UINT32_C(0x0000313a)
1085/** Reboot request. */
1086#define KD_PACKET_MANIPULATE_REQ_REBOOT UINT32_C(0x0000313b)
1087/** continue 2nd version request. */
1088#define KD_PACKET_MANIPULATE_REQ_CONTINUE2 UINT32_C(0x0000313c)
1089/** Read physical memory request. */
1090#define KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM UINT32_C(0x0000313d)
1091/** Write physical memory request. */
1092#define KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM UINT32_C(0x0000313e)
1093/** Query special calls request. */
1094#define KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS UINT32_C(0x0000313f)
1095/** Set special calls request. */
1096#define KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS UINT32_C(0x00003140)
1097/** Clear special calls request. */
1098#define KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS UINT32_C(0x00003141)
1099/** Set internal breakpoint request. */
1100#define KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT UINT32_C(0x00003142)
1101/** Get internal breakpoint request. */
1102#define KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT UINT32_C(0x00003143)
1103/** Read I/O space extended request. */
1104#define KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX UINT32_C(0x00003144)
1105/** Write I/O space extended request. */
1106#define KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX UINT32_C(0x00003145)
1107/** Get version request. */
1108#define KD_PACKET_MANIPULATE_REQ_GET_VERSION UINT32_C(0x00003146)
1109/** Write breakpoint extended request. */
1110#define KD_PACKET_MANIPULATE_REQ_WRITE_BKPT_EX UINT32_C(0x00003147)
1111/** Restore breakpoint extended request. */
1112#define KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT_EX UINT32_C(0x00003148)
1113/** Cause a bugcheck request. */
1114#define KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK UINT32_C(0x00003149)
1115/** Cause a bugcheck request. */
1116#define KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR UINT32_C(0x00003150)
1117/** @todo 0x3151-0x3155 */
1118/** Search memory for a pattern request. */
1119#define KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY UINT32_C(0x00003156)
1120/** @todo 0x3157-0x3159 */
1121/** Clear all internal breakpoints request. */
1122#define KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT UINT32_C(0x0000315a)
1123/** Fill memory. */
1124#define KD_PACKET_MANIPULATE_REQ_FILL_MEMORY UINT32_C(0x0000315b)
1125/** Query memory properties. */
1126#define KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY UINT32_C(0x0000315c)
1127/** @todo 0x315d, 0x315e */
1128/** Get context extended request. */
1129#define KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX UINT32_C(0x0000315f)
1130/** @todo 0x3160 */
1131/** Maximum available request (exclusive). */
1132#define KD_PACKET_MANIPULATE_REQ_MAX UINT32_C(0x00003161)
1133/** @} */
1134
1135/**
1136 * KD stub receive state.
1137 */
1138typedef enum KDRECVSTATE
1139{
1140 /** Invalid state. */
1141 KDRECVSTATE_INVALID = 0,
1142 /** Receiving the first byte of the packet header. */
1143 KDRECVSTATE_PACKET_HDR_FIRST_BYTE,
1144 /** Receiving the second byte of the packet header. */
1145 KDRECVSTATE_PACKET_HDR_SECOND_BYTE,
1146 /** Receiving the header. */
1147 KDRECVSTATE_PACKET_HDR,
1148 /** Receiving the packet body. */
1149 KDRECVSTATE_PACKET_BODY,
1150 /** Receiving the trailing byte. */
1151 KDRECVSTATE_PACKET_TRAILER,
1152 /** Blow up the enum to 32bits for easier alignment of members in structs. */
1153 KDRECVSTATE_32BIT_HACK = 0x7fffffff
1154} KDRECVSTATE;
1155
1156
1157/**
1158 * KD emulated hardware breakpoint.
1159 */
1160typedef struct KDCTXHWBP
1161{
1162#ifndef VBOX_WITH_LOTS_OF_DBGF_BPS
1163 /** The DBGF breakpoint handle if active, UINT32_MAX if not active. */
1164 uint32_t hDbgfBp;
1165#else
1166 /** The DBGF breakpoint handle if active, NIL_DBGFBP if not active. */
1167 DBGFBP hDbgfBp;
1168#endif
1169 /** The linear address of the breakpoint if active. */
1170 RTGCPTR GCPtrBp;
1171 /** Access type of the breakpoint, see X86_DR7_RW_*. */
1172 uint8_t fAcc;
1173 /** Length flags of the breakpoint. */
1174 uint8_t fLen;
1175 /** Flag whether it is a local breakpoint. */
1176 bool fLocal;
1177 /** Flag whether it is a global breakpoint. */
1178 bool fGlobal;
1179 /** Flag whether the breakpoint has triggered since the last time of the reset. */
1180 bool fTriggered;
1181} KDCTXHWBP;
1182/** Pointer to an emulated hardware breakpoint. */
1183typedef KDCTXHWBP *PKDCTXHWBP;
1184/** Pointer to a const emulated hardware breakpoint. */
1185typedef const KDCTXHWBP *PCKDCTXHWBP;
1186
1187
1188/**
1189 * KD context data.
1190 */
1191typedef struct KDCTX
1192{
1193 /** Internal debugger console data. */
1194 DBGC Dbgc;
1195 /** Number of bytes received left for the current state. */
1196 size_t cbRecvLeft;
1197 /** Pointer where to write the next received data. */
1198 uint8_t *pbRecv;
1199 /** The current state when receiving a new packet. */
1200 KDRECVSTATE enmState;
1201 /** The timeout waiting for new data. */
1202 RTMSINTERVAL msRecvTimeout;
1203 /** Timestamp when we last received data from the remote end. */
1204 uint64_t tsRecvLast;
1205 /** Packet header being received. */
1206 union
1207 {
1208 KDPACKETHDR Fields;
1209 uint8_t ab[16];
1210 } PktHdr;
1211 /** The next packet ID to send. */
1212 uint32_t idPktNext;
1213 /** Offset into the body receive buffer. */
1214 size_t offBodyRecv;
1215 /** Body data. */
1216 uint8_t abBody[_4K];
1217 /** The trailer byte storage. */
1218 uint8_t bTrailer;
1219 /** Flag whether a breakin packet was received since the last time it was reset. */
1220 bool fBreakinRecv;
1221 /** Flag whether we entered the native VBox hypervisor through a bugcheck request. */
1222 bool fInVBoxDbg;
1223
1224 /** Emulated hardware breakpoint handling. */
1225 KDCTXHWBP aHwBp[4];
1226 /** Flag whether a single step completed since last time this was cleared. */
1227 bool fSingleStepped;
1228
1229 /** Pointer to the OS digger WinNt interface if a matching guest was detected. */
1230 PDBGFOSIWINNT pIfWinNt;
1231 /** Flag whether the detected guest is 32bit (false if 64bit). */
1232 bool f32Bit;
1233} KDCTX;
1234/** Pointer to the KD context data. */
1235typedef KDCTX *PKDCTX;
1236/** Pointer to const KD context data. */
1237typedef const KDCTX *PCKDCTX;
1238/** Pointer to a KD context data pointer. */
1239typedef PKDCTX *PPKDCTX;
1240
1241
1242/** Creates a possibly sign extended guest context pointer which is required for 32bit targets. */
1243#define KD_PTR_CREATE(a_pThis, a_GCPtr) ((a_pThis)->f32Bit && ((a_GCPtr) & RT_BIT_32(31)) ? (a_GCPtr) | UINT64_C(0xffffffff00000000) : (a_GCPtr))
1244/** Returns the value of a possibly sign extended guest context pointer received for 32bit targets. */
1245#define KD_PTR_GET(a_pThis, a_GCPtr) ((a_pThis)->f32Bit ? (a_GCPtr) & ~UINT64_C(0xffffffff00000000) : (a_GCPtr))
1246
1247#ifndef VBOX_WITH_LOTS_OF_DBGF_BPS
1248# define NIL_DBGFBP ((uint32_t)UINT32_MAX)
1249#endif
1250
1251
1252/*********************************************************************************************************************************
1253* Internal Functions *
1254*********************************************************************************************************************************/
1255
1256static void dbgcKdCtxMsgSend(PKDCTX pThis, bool fWarning, const char *pszMsg);
1257
1258
1259#ifdef LOG_ENABLED
1260/**
1261 * Returns a human readable string of the given packet sub type.
1262 *
1263 * @returns Pointer to sub type string.
1264 * @param u16SubType The sub type to convert to a string.
1265 */
1266static const char *dbgcKdPktDumpSubTypeToStr(uint16_t u16SubType)
1267{
1268 switch (u16SubType)
1269 {
1270 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32: return "StateChange32";
1271 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE: return "Manipulate";
1272 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO: return "DebugIo";
1273 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE: return "Ack";
1274 case KD_PACKET_HDR_SUB_TYPE_RESEND: return "Resend";
1275 case KD_PACKET_HDR_SUB_TYPE_RESET: return "Reset";
1276 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64: return "StateChange64";
1277 case KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN: return "PollBreakin";
1278 case KD_PACKET_HDR_SUB_TYPE_TRACE_IO: return "TraceIo";
1279 case KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST: return "ControlRequest";
1280 case KD_PACKET_HDR_SUB_TYPE_FILE_IO: return "FileIo";
1281 default: break;
1282 }
1283
1284 return "<UNKNOWN>";
1285}
1286
1287
1288/**
1289 * Returns a human readable string of the given manipulate request ID.
1290 *
1291 * @returns nothing.
1292 * @param idReq Request ID (API number in KD speak).
1293 */
1294static const char *dbgcKdPktDumpManipulateReqToStr(uint32_t idReq)
1295{
1296 switch (idReq)
1297 {
1298 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM: return "ReadVirtMem";
1299 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM: return "WriteVirtMem";
1300 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT: return "GetContext";
1301 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT: return "SetContext";
1302 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT: return "WriteBkpt";
1303 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT: return "RestoreBkpt";
1304 case KD_PACKET_MANIPULATE_REQ_CONTINUE: return "Continue";
1305 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE: return "ReadCtrlSpace";
1306 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE: return "WriteCtrlSpace";
1307 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE: return "ReadIoSpace";
1308 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE: return "WriteIoSpace";
1309 case KD_PACKET_MANIPULATE_REQ_REBOOT: return "Reboot";
1310 case KD_PACKET_MANIPULATE_REQ_CONTINUE2: return "Continue2";
1311 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM: return "ReadPhysMem";
1312 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM: return "WritePhysMem";
1313 case KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS: return "QuerySpecCalls";
1314 case KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS: return "SetSpecCalls";
1315 case KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS: return "ClrSpecCalls";
1316 case KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT: return "SetIntBkpt";
1317 case KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT: return "GetIntBkpt";
1318 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX: return "ReadIoSpaceEx";
1319 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX: return "WriteIoSpaceEx";
1320 case KD_PACKET_MANIPULATE_REQ_GET_VERSION: return "GetVersion";
1321 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT: return "ClrAllIntBkpt";
1322 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX: return "GetContextEx";
1323 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY: return "QueryMemory";
1324 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK: return "CauseBugCheck";
1325 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR: return "SwitchProcessor";
1326 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY: return "SearchMemory";
1327 default: break;
1328 }
1329
1330 return "<UNKNOWN>";
1331}
1332
1333
1334/**
1335 * Dumps the content of a manipulate packet.
1336 *
1337 * @returns nothing.
1338 * @param pSgBuf S/G buffer containing the manipulate packet payload.
1339 */
1340static void dbgcKdPktDumpManipulate(PRTSGBUF pSgBuf)
1341{
1342 KDPACKETMANIPULATEHDR Hdr;
1343 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, &Hdr, sizeof(Hdr));
1344
1345 if (cbCopied == sizeof(Hdr))
1346 {
1347 const char *pszReq = dbgcKdPktDumpManipulateReqToStr(Hdr.idReq);
1348
1349 Log3((" MANIPULATE(%#x (%s), %#x, %u, %#x)\n",
1350 Hdr.idReq, pszReq, Hdr.u16CpuLvl, Hdr.idCpu, Hdr.u32NtStatus));
1351
1352 switch (Hdr.idReq)
1353 {
1354 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
1355 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
1356 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
1357 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
1358 {
1359 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1360 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferMem64, sizeof(XferMem64));
1361 if (cbCopied == sizeof(XferMem64))
1362 {
1363 Log3((" u64PtrTarget: %RX64\n"
1364 " cbXferReq: %RX32\n"
1365 " cbXfered: %RX32\n",
1366 XferMem64.u64PtrTarget, XferMem64.cbXferReq, XferMem64.cbXfered));
1367 }
1368 else
1369 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferMem64), cbCopied));
1370 break;
1371 }
1372 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
1373 {
1374 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
1375 cbCopied = RTSgBufCopyToBuf(pSgBuf, &RestoreBkpt64, sizeof(RestoreBkpt64));
1376 if (cbCopied == sizeof(RestoreBkpt64))
1377 Log3((" u32HndBkpt: %RX32\n", RestoreBkpt64.u32HndBkpt));
1378 else
1379 Log3((" Payload to small, expected %u, got %zu\n", sizeof(RestoreBkpt64), cbCopied));
1380 break;
1381 }
1382 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
1383 {
1384 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
1385 cbCopied = RTSgBufCopyToBuf(pSgBuf, &WriteBkpt64, sizeof(WriteBkpt64));
1386 if (cbCopied == sizeof(WriteBkpt64))
1387 Log3((" u64PtrBkpt: %RX64\n"
1388 " u32HndBkpt: %RX32\n",
1389 WriteBkpt64.u64PtrBkpt, WriteBkpt64.u32HndBkpt));
1390 else
1391 Log3((" Payload to small, expected %u, got %zu\n", sizeof(WriteBkpt64), cbCopied));
1392 break;
1393 }
1394 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
1395 {
1396 KDPACKETMANIPULATE_CONTINUE Continue;
1397 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1398 if (cbCopied == sizeof(Continue))
1399 Log3((" u32NtContSts: %RX32\n", Continue.u32NtContSts));
1400 else
1401 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1402 break;
1403 }
1404 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
1405 {
1406 KDPACKETMANIPULATE_CONTINUE2 Continue;
1407 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1408 if (cbCopied == sizeof(Continue))
1409 Log3((" u32NtContSts: %RX32\n"
1410 " fTrace: %RX32\n",
1411 Continue.u32NtContSts, Continue.fTrace));
1412 else
1413 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1414 break;
1415 }
1416 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
1417 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
1418 {
1419 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
1420 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferCtrlSpace64, sizeof(XferCtrlSpace64));
1421 if (cbCopied == sizeof(XferCtrlSpace64))
1422 {
1423 Log3((" u64IdXfer: %RX64\n"
1424 " cbXferReq: %RX32\n"
1425 " cbXfered: %RX32\n",
1426 XferCtrlSpace64.u64IdXfer, XferCtrlSpace64.cbXferReq, XferCtrlSpace64.cbXfered));
1427 }
1428 else
1429 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferCtrlSpace64), cbCopied));
1430 break;
1431 }
1432 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
1433 {
1434 KDPACKETMANIPULATE_CONTEXTEX GetContextEx;
1435 cbCopied = RTSgBufCopyToBuf(pSgBuf, &GetContextEx, sizeof(GetContextEx));
1436 if (cbCopied == sizeof(GetContextEx))
1437 {
1438 Log3((" offStart: %RX32\n"
1439 " cbXferReq: %RX32\n"
1440 " cbXfered: %RX32\n",
1441 GetContextEx.offStart, GetContextEx.cbXfer, GetContextEx.cbXfered));
1442 }
1443 else
1444 Log3((" Payload to small, expected %u, got %zu\n", sizeof(GetContextEx), cbCopied));
1445 break;
1446 }
1447 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
1448 {
1449 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
1450 cbCopied = RTSgBufCopyToBuf(pSgBuf, &QueryMemory, sizeof(QueryMemory));
1451 if (cbCopied == sizeof(QueryMemory))
1452 {
1453 Log3((" u64GCPtr: %RX64\n"
1454 " u32AddrSpace: %RX32\n"
1455 " u32Flags: %RX32\n",
1456 QueryMemory.u64GCPtr, QueryMemory.u32AddrSpace, QueryMemory.u32Flags));
1457 }
1458 else
1459 Log3((" Payload to small, expected %u, got %zu\n", sizeof(QueryMemory), cbCopied));
1460 break;
1461 }
1462 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
1463 {
1464 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
1465 cbCopied = RTSgBufCopyToBuf(pSgBuf, &SearchMemory, sizeof(SearchMemory));
1466 if (cbCopied == sizeof(SearchMemory))
1467 {
1468 Log3((" u64GCPtr: %RX64\n"
1469 " cbSearch: %RX64\n"
1470 " cbPattern: %RX32\n",
1471 SearchMemory.u64GCPtr, SearchMemory.cbSearch, SearchMemory.cbPattern));
1472 }
1473 else
1474 Log3((" Payload to small, expected %u, got %zu\n", sizeof(SearchMemory), cbCopied));
1475 break;
1476 }
1477 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR:
1478 default:
1479 break;
1480 }
1481 }
1482 else
1483 Log3((" MANIPULATE(Header too small, expected %u, got %zu)\n", sizeof(Hdr), cbCopied));
1484}
1485
1486
1487/**
1488 * Dumps the received packet to the debug log.
1489 *
1490 * @returns VBox status code.
1491 * @param pPktHdr The packet header to dump.
1492 * @param fRx Flag whether the packet was received (false indicates an outgoing packet).
1493 */
1494static void dbgcKdPktDump(PCKDPACKETHDR pPktHdr, PCRTSGSEG paSegs, uint32_t cSegs, bool fRx)
1495{
1496 RTSGBUF SgBuf;
1497
1498 RTSgBufInit(&SgBuf, paSegs, cSegs);
1499
1500 Log3(("%s KDPKTHDR(%#x, %#x (%s), %u, %#x, %#x)\n",
1501 fRx ? "=>" : "<=",
1502 pPktHdr->u32Signature, pPktHdr->u16SubType, dbgcKdPktDumpSubTypeToStr(pPktHdr->u16SubType),
1503 pPktHdr->cbBody, pPktHdr->idPacket, pPktHdr->u32ChkSum));
1504 switch (pPktHdr->u16SubType)
1505 {
1506 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
1507 dbgcKdPktDumpManipulate(&SgBuf);
1508 break;
1509 default:
1510 break;
1511 }
1512}
1513#endif
1514
1515
1516/**
1517 * Resets the emulated hardware breakpoint state to a state similar after a reboot.
1518 *
1519 * @returns nothing.
1520 * @param pThis The KD context.
1521 */
1522static void dbgcKdCtxHwBpReset(PKDCTX pThis)
1523{
1524 pThis->fSingleStepped = false;
1525
1526 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1527 {
1528 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1529
1530 if (pBp->hDbgfBp != NIL_DBGFBP)
1531 {
1532 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->hDbgfBp);
1533 AssertRC(rc);
1534 }
1535
1536 pBp->hDbgfBp = NIL_DBGFBP;
1537 pBp->GCPtrBp = 0;
1538 pBp->fAcc = 0;
1539 pBp->fLen = 0;
1540 pBp->fLocal = false;
1541 pBp->fGlobal = false;
1542 pBp->fTriggered = false;
1543 }
1544}
1545
1546
1547/**
1548 * Updates the given breakpoint with the given properties.
1549 *
1550 * @returns VBox status code.
1551 * @param pThis The KD context.
1552 * @param pBp The breakpoint to update.
1553 * @param fAcc Access mode.
1554 * @param fLen Access length.
1555 * @param fGlobal Global breakpoint.
1556 * @param fLocal Local breakpoint.
1557 * @param GCPtrBp Linear address of the breakpoint.
1558 */
1559static int dbgcKdCtxHwBpUpdate(PKDCTX pThis, PKDCTXHWBP pBp, uint8_t fAcc, uint8_t fLen,
1560 bool fGlobal, bool fLocal, RTGCPTR GCPtrBp)
1561{
1562 int rc = VINF_SUCCESS;
1563
1564 /* Did anything actually change?. */
1565 if ( pBp->fAcc != fAcc
1566 || pBp->fLen != fLen
1567 || pBp->fGlobal != fGlobal
1568 || pBp->fLocal != fLocal
1569 || pBp->GCPtrBp != GCPtrBp)
1570 {
1571 /* Clear the old breakpoint. */
1572 if (pBp->hDbgfBp != NIL_DBGFBP)
1573 {
1574 rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->hDbgfBp);
1575 AssertRC(rc);
1576 pBp->hDbgfBp = NIL_DBGFBP;
1577 }
1578
1579 pBp->fAcc = fAcc;
1580 pBp->fLen = fLen;
1581 pBp->fGlobal = fGlobal;
1582 pBp->fLocal = fLocal;
1583 pBp->GCPtrBp = GCPtrBp;
1584 if (pBp->fGlobal || pBp->fLocal)
1585 {
1586 DBGFADDRESS AddrBp;
1587 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrBp, GCPtrBp);
1588
1589 uint8_t cb = 0;
1590 switch (pBp->fLen)
1591 {
1592 case X86_DR7_LEN_BYTE:
1593 cb = 1;
1594 break;
1595 case X86_DR7_LEN_WORD:
1596 cb = 2;
1597 break;
1598 case X86_DR7_LEN_DWORD:
1599 cb = 4;
1600 break;
1601 case X86_DR7_LEN_QWORD:
1602 cb = 8;
1603 break;
1604 default:
1605 AssertFailed();
1606 return VERR_NET_PROTOCOL_ERROR;
1607 }
1608
1609 rc = DBGFR3BpSetReg(pThis->Dbgc.pUVM, &AddrBp, 0 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/,
1610 pBp->fAcc, cb, &pBp->hDbgfBp);
1611 }
1612 }
1613
1614 return rc;
1615}
1616
1617
1618/**
1619 * Updates emulated hardware breakpoints based on the written DR7 value.
1620 *
1621 * @returns VBox status code.
1622 * @param pThis The KD context.
1623 * @param uDr7 The DR7 value which is written.
1624 */
1625static int dbgcKdCtxHwBpDr7Update(PKDCTX pThis, uint32_t uDr7)
1626{
1627 int rc = VINF_SUCCESS;
1628
1629 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1630 {
1631 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1632 uint8_t fAcc = X86_DR7_GET_RW(uDr7, i);
1633 uint8_t fLen = X86_DR7_GET_LEN(uDr7, i);
1634 bool fGlobal = (uDr7 & RT_BIT_32(1 + i * 2)) ? true : false;
1635 bool fLocal = (uDr7 & RT_BIT_32(i * 2)) ? true : false;
1636
1637 int rc2 = dbgcKdCtxHwBpUpdate(pThis, pBp, fAcc, fLen, fGlobal, fLocal, pThis->aHwBp[i].GCPtrBp);
1638 if ( RT_FAILURE(rc2)
1639 && RT_SUCCESS(rc))
1640 rc = rc2;
1641 }
1642
1643 return rc;
1644}
1645
1646
1647/**
1648 * Updates the linear guest pointer for the given hardware breakpoint.
1649 *
1650 * @returns VBox status code.
1651 * @param pThis The KD context.
1652 * @param pBp The breakpoint to update.
1653 * @param GCPtrBp The linear breakpoint address.
1654 */
1655DECLINLINE(int) dbgcKdCtxHwBpGCPtrUpdate(PKDCTX pThis, PKDCTXHWBP pBp, RTGCPTR GCPtrBp)
1656{
1657 return dbgcKdCtxHwBpUpdate(pThis, pBp, pBp->fAcc, pBp->fLen, pBp->fGlobal, pBp->fLocal, GCPtrBp);
1658}
1659
1660
1661/**
1662 * Calculates the DR7 value based on the emulated hardware breakpoint state and returns it.
1663 *
1664 * @returns The emulated DR7 value.
1665 * @param pThis The KD context.
1666 */
1667static uint32_t dbgcKdCtxHwBpDr7Get(PKDCTX pThis)
1668{
1669 uint32_t uDr7 = 0;
1670
1671 uDr7 |= X86_DR7_RW(0, pThis->aHwBp[0].fAcc);
1672 uDr7 |= X86_DR7_RW(1, pThis->aHwBp[1].fAcc);
1673 uDr7 |= X86_DR7_RW(2, pThis->aHwBp[2].fAcc);
1674 uDr7 |= X86_DR7_RW(3, pThis->aHwBp[3].fAcc);
1675
1676 uDr7 |= X86_DR7_LEN(0, pThis->aHwBp[0].fLen);
1677 uDr7 |= X86_DR7_LEN(1, pThis->aHwBp[1].fLen);
1678 uDr7 |= X86_DR7_LEN(2, pThis->aHwBp[2].fLen);
1679 uDr7 |= X86_DR7_LEN(3, pThis->aHwBp[3].fLen);
1680
1681 uDr7 |= pThis->aHwBp[0].fGlobal ? X86_DR7_G(0) : 0;
1682 uDr7 |= pThis->aHwBp[1].fGlobal ? X86_DR7_G(1) : 0;
1683 uDr7 |= pThis->aHwBp[2].fGlobal ? X86_DR7_G(2) : 0;
1684 uDr7 |= pThis->aHwBp[3].fGlobal ? X86_DR7_G(3) : 0;
1685
1686 uDr7 |= pThis->aHwBp[0].fLocal ? X86_DR7_L(0) : 0;
1687 uDr7 |= pThis->aHwBp[1].fLocal ? X86_DR7_L(1) : 0;
1688 uDr7 |= pThis->aHwBp[2].fLocal ? X86_DR7_L(2) : 0;
1689 uDr7 |= pThis->aHwBp[3].fLocal ? X86_DR7_L(3) : 0;
1690
1691 return uDr7;
1692}
1693
1694
1695/**
1696 * Updates emulated hardware breakpoints based on the written DR6 value.
1697 *
1698 * @returns nothing.
1699 * @param pThis The KD context.
1700 * @param uDr6 The DR7 value which is written.
1701 */
1702static void dbgcKdCtxHwBpDr6Update(PKDCTX pThis, uint32_t uDr6)
1703{
1704 pThis->aHwBp[0].fTriggered = (uDr6 & X86_DR6_B0) ? true : false;
1705 pThis->aHwBp[1].fTriggered = (uDr6 & X86_DR6_B1) ? true : false;
1706 pThis->aHwBp[2].fTriggered = (uDr6 & X86_DR6_B2) ? true : false;
1707 pThis->aHwBp[3].fTriggered = (uDr6 & X86_DR6_B3) ? true : false;
1708 pThis->fSingleStepped = (uDr6 & X86_DR6_BS) ? true : false;
1709}
1710
1711
1712/**
1713 * Calculates the DR6 value based on the emulated hardware breakpoint state and returns it.
1714 *
1715 * @returns The emulated DR6 value.
1716 * @param pThis The KD context.
1717 */
1718static uint32_t dbgcKdCtxHwBpDr6Get(PKDCTX pThis)
1719{
1720 uint32_t uDr6 = 0;
1721
1722 if (pThis->aHwBp[0].fTriggered)
1723 uDr6 |= X86_DR6_B0;
1724 if (pThis->aHwBp[1].fTriggered)
1725 uDr6 |= X86_DR6_B1;
1726 if (pThis->aHwBp[2].fTriggered)
1727 uDr6 |= X86_DR6_B2;
1728 if (pThis->aHwBp[3].fTriggered)
1729 uDr6 |= X86_DR6_B3;
1730 if (pThis->fSingleStepped)
1731 uDr6 |= X86_DR6_BS;
1732
1733 return uDr6;
1734}
1735
1736
1737/**
1738 * Wrapper for the I/O interface write callback.
1739 *
1740 * @returns Status code.
1741 * @param pThis The KD context.
1742 * @param pvPkt The packet data to send.
1743 * @param cbPkt Size of the packet in bytes.
1744 */
1745DECLINLINE(int) dbgcKdCtxWrite(PKDCTX pThis, const void *pvPkt, size_t cbPkt)
1746{
1747 return pThis->Dbgc.pIo->pfnWrite(pThis->Dbgc.pIo, pvPkt, cbPkt, NULL /*pcbWritten*/);
1748}
1749
1750
1751/**
1752 * Fills in the given 64bit NT context structure with the requested values.
1753 *
1754 * @returns VBox status code.
1755 * @param pThis The KD context.
1756 * @param idCpu The CPU to query the context for.
1757 * @param pNtCtx The NT context structure to fill in.
1758 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1759 */
1760static int dbgcKdCtxQueryNtCtx64(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1761{
1762 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1763
1764 pNtCtx->fContext = NTCONTEXT_F_AMD64;
1765 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pNtCtx->u32RegMxCsr);
1766
1767 if ( RT_SUCCESS(rc)
1768 && fCtxFlags & NTCONTEXT_F_CONTROL)
1769 {
1770 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u16SegCs);
1771 if (RT_SUCCESS(rc))
1772 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u16SegSs);
1773 if (RT_SUCCESS(rc))
1774 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RIP, &pNtCtx->u64RegRip);
1775 if (RT_SUCCESS(rc))
1776 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSP, &pNtCtx->u64RegRsp);
1777 if (RT_SUCCESS(rc))
1778 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBP, &pNtCtx->u64RegRbp);
1779 if (RT_SUCCESS(rc))
1780 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1781 if (RT_SUCCESS(rc))
1782 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1783 }
1784
1785 if ( RT_SUCCESS(rc)
1786 && fCtxFlags & NTCONTEXT_F_INTEGER)
1787 {
1788 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RAX, &pNtCtx->u64RegRax);
1789 if (RT_SUCCESS(rc))
1790 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RCX, &pNtCtx->u64RegRcx);
1791 if (RT_SUCCESS(rc))
1792 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDX, &pNtCtx->u64RegRdx);
1793 if (RT_SUCCESS(rc))
1794 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBX, &pNtCtx->u64RegRbx);
1795 if (RT_SUCCESS(rc))
1796 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSI, &pNtCtx->u64RegRsi);
1797 if (RT_SUCCESS(rc))
1798 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDI, &pNtCtx->u64RegRdi);
1799 if (RT_SUCCESS(rc))
1800 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R8, &pNtCtx->u64RegR8);
1801 if (RT_SUCCESS(rc))
1802 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R9, &pNtCtx->u64RegR9);
1803 if (RT_SUCCESS(rc))
1804 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R10, &pNtCtx->u64RegR10);
1805 if (RT_SUCCESS(rc))
1806 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R11, &pNtCtx->u64RegR11);
1807 if (RT_SUCCESS(rc))
1808 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R12, &pNtCtx->u64RegR12);
1809 if (RT_SUCCESS(rc))
1810 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R13, &pNtCtx->u64RegR13);
1811 if (RT_SUCCESS(rc))
1812 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R14, &pNtCtx->u64RegR14);
1813 if (RT_SUCCESS(rc))
1814 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R15, &pNtCtx->u64RegR15);
1815 if (RT_SUCCESS(rc))
1816 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1817 }
1818
1819 if ( RT_SUCCESS(rc)
1820 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1821 {
1822 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u16SegDs);
1823 if (RT_SUCCESS(rc))
1824 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u16SegEs);
1825 if (RT_SUCCESS(rc))
1826 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u16SegFs);
1827 if (RT_SUCCESS(rc))
1828 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u16SegGs);
1829 if (RT_SUCCESS(rc))
1830 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1831 }
1832
1833 if ( RT_SUCCESS(rc)
1834 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1835 {
1836 /** @todo NTCONTEXT_F_FLOATING_POINT. */
1837 }
1838
1839 if ( RT_SUCCESS(rc)
1840 && fCtxFlags & NTCONTEXT_F_DEBUG)
1841 {
1842 /** @todo NTCONTEXT_F_DEBUG */
1843 }
1844
1845 return rc;
1846}
1847
1848
1849/**
1850 * Fills in the given 32bit NT context structure with the requested values.
1851 *
1852 * @returns VBox status code.
1853 * @param pThis The KD context.
1854 * @param idCpu The CPU to query the context for.
1855 * @param pNtCtx The NT context structure to fill in.
1856 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1857 */
1858static int dbgcKdCtxQueryNtCtx32(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT32 pNtCtx, uint32_t fCtxFlags)
1859{
1860 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1861
1862 pNtCtx->fContext = NTCONTEXT_F_X86;
1863
1864 int rc = VINF_SUCCESS;
1865 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1866 {
1867 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u32SegCs);
1868 if (RT_SUCCESS(rc))
1869 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u32SegSs);
1870 if (RT_SUCCESS(rc))
1871 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EIP, &pNtCtx->u32RegEip);
1872 if (RT_SUCCESS(rc))
1873 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESP, &pNtCtx->u32RegEsp);
1874 if (RT_SUCCESS(rc))
1875 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBP, &pNtCtx->u32RegEbp);
1876 if (RT_SUCCESS(rc))
1877 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1878 if (RT_SUCCESS(rc))
1879 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1880 }
1881
1882 if ( RT_SUCCESS(rc)
1883 && fCtxFlags & NTCONTEXT_F_INTEGER)
1884 {
1885 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EAX, &pNtCtx->u32RegEax);
1886 if (RT_SUCCESS(rc))
1887 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ECX, &pNtCtx->u32RegEcx);
1888 if (RT_SUCCESS(rc))
1889 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDX, &pNtCtx->u32RegEdx);
1890 if (RT_SUCCESS(rc))
1891 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBX, &pNtCtx->u32RegEbx);
1892 if (RT_SUCCESS(rc))
1893 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESI, &pNtCtx->u32RegEsi);
1894 if (RT_SUCCESS(rc))
1895 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDI, &pNtCtx->u32RegEdi);
1896 if (RT_SUCCESS(rc))
1897 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1898 }
1899
1900 if ( RT_SUCCESS(rc)
1901 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1902 {
1903 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u32SegDs);
1904 if (RT_SUCCESS(rc))
1905 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u32SegEs);
1906 if (RT_SUCCESS(rc))
1907 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u32SegFs);
1908 if (RT_SUCCESS(rc))
1909 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u32SegGs);
1910 if (RT_SUCCESS(rc))
1911 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1912 }
1913
1914 if ( RT_SUCCESS(rc)
1915 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1916 {
1917 /** @todo NTCONTEXT_F_FLOATING_POINT. */
1918 }
1919
1920 if ( RT_SUCCESS(rc)
1921 && fCtxFlags & NTCONTEXT_F_DEBUG)
1922 {
1923 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pNtCtx->u32RegDr0);
1924 if (RT_SUCCESS(rc))
1925 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pNtCtx->u32RegDr1);
1926 if (RT_SUCCESS(rc))
1927 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pNtCtx->u32RegDr3);
1928 if (RT_SUCCESS(rc))
1929 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pNtCtx->u32RegDr6);
1930 if (RT_SUCCESS(rc))
1931 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pNtCtx->u32RegDr7);
1932 if (RT_SUCCESS(rc))
1933 pNtCtx->fContext |= NTCONTEXT_F_DEBUG;
1934 }
1935
1936 return rc;
1937}
1938
1939
1940#define KD_REG_INIT(a_pszName, a_enmType, a_ValMember, a_Val) \
1941 do \
1942 { \
1943 aRegsSet[idxReg].pszName = a_pszName; \
1944 aRegsSet[idxReg].enmType = a_enmType; \
1945 aRegsSet[idxReg].Val.a_ValMember = a_Val; \
1946 idxReg++; \
1947 } while (0)
1948#define KD_REG_INIT_DTR(a_pszName, a_Base, a_Limit) \
1949 do \
1950 { \
1951 aRegsSet[idxReg].pszName = a_pszName; \
1952 aRegsSet[idxReg].enmType = DBGFREGVALTYPE_DTR; \
1953 aRegsSet[idxReg].Val.dtr.u64Base = a_Base; \
1954 aRegsSet[idxReg].Val.dtr.u32Limit = a_Limit; \
1955 idxReg++; \
1956 } while (0)
1957#define KD_REG_INIT_U16(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U16, u16, a_Val)
1958#define KD_REG_INIT_U32(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U32, u32, a_Val)
1959#define KD_REG_INIT_U64(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U64, u64, a_Val)
1960
1961
1962/**
1963 * Writes the indicated values from the given context structure to the guests register set.
1964 *
1965 * @returns VBox status code.
1966 * @param pThis The KD context.
1967 * @param idCpu The CPU to query the context for.
1968 * @param pNtCtx The NT context structure to set.
1969 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to set.
1970 */
1971static int dbgcKdCtxSetNtCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1972{
1973 uint32_t idxReg = 0;
1974 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1975
1976 KD_REG_INIT_U32("mxcsr", pNtCtx->u32RegMxCsr);
1977
1978 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1979 {
1980#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1981 KD_REG_INIT_U16("cs", pNtCtx->u16SegCs);
1982 KD_REG_INIT_U16("ss", pNtCtx->u16SegSs);
1983#endif
1984 KD_REG_INIT_U64("rip", pNtCtx->u64RegRip);
1985 KD_REG_INIT_U64("rsp", pNtCtx->u64RegRsp);
1986 KD_REG_INIT_U64("rbp", pNtCtx->u64RegRbp);
1987 KD_REG_INIT_U32("rflags", pNtCtx->u32RegEflags);
1988 }
1989
1990 if (fCtxFlags & NTCONTEXT_F_INTEGER)
1991 {
1992 KD_REG_INIT_U64("rax", pNtCtx->u64RegRax);
1993 KD_REG_INIT_U64("rcx", pNtCtx->u64RegRcx);
1994 KD_REG_INIT_U64("rdx", pNtCtx->u64RegRdx);
1995 KD_REG_INIT_U64("rbx", pNtCtx->u64RegRbx);
1996 KD_REG_INIT_U64("rsi", pNtCtx->u64RegRsi);
1997 KD_REG_INIT_U64("rdi", pNtCtx->u64RegRdi);
1998 KD_REG_INIT_U64("r8", pNtCtx->u64RegR8);
1999 KD_REG_INIT_U64("r9", pNtCtx->u64RegR9);
2000 KD_REG_INIT_U64("r10", pNtCtx->u64RegR10);
2001 KD_REG_INIT_U64("r11", pNtCtx->u64RegR11);
2002 KD_REG_INIT_U64("r12", pNtCtx->u64RegR12);
2003 KD_REG_INIT_U64("r13", pNtCtx->u64RegR13);
2004 KD_REG_INIT_U64("r14", pNtCtx->u64RegR14);
2005 KD_REG_INIT_U64("r15", pNtCtx->u64RegR15);
2006 }
2007
2008 if (fCtxFlags & NTCONTEXT_F_SEGMENTS)
2009 {
2010#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2011 KD_REG_INIT_U16("ds", pNtCtx->u16SegDs);
2012 KD_REG_INIT_U16("es", pNtCtx->u16SegEs);
2013 KD_REG_INIT_U16("fs", pNtCtx->u16SegFs);
2014 KD_REG_INIT_U16("gs", pNtCtx->u16SegGs);
2015#endif
2016 }
2017
2018 if (fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
2019 {
2020 /** @todo NTCONTEXT_F_FLOATING_POINT. */
2021 }
2022
2023 if (fCtxFlags & NTCONTEXT_F_DEBUG)
2024 dbgcKdCtxMsgSend(pThis, true /*fWarning*/, "Setting local DR registers does not work!");
2025
2026 return DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2027}
2028
2029
2030/**
2031 * Fills in the given 64bit NT kernel context structure with the requested values.
2032 *
2033 * @returns VBox status code.
2034 * @param pThis The KD context.
2035 * @param idCpu The CPU to query the context for.
2036 * @param pKNtCtx The NT context structure to fill in.
2037 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
2038 */
2039static int dbgcKdCtxQueryNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT64 pKNtCtx, uint32_t fCtxFlags)
2040{
2041 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2042
2043 int rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u64RegCr0);
2044 if (RT_SUCCESS(rc))
2045 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u64RegCr2);
2046 if (RT_SUCCESS(rc))
2047 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u64RegCr3);
2048 if (RT_SUCCESS(rc))
2049 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u64RegCr4);
2050 if (RT_SUCCESS(rc))
2051 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR8, &pKNtCtx->u64RegCr8);
2052 if (RT_SUCCESS(rc))
2053 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2054 if (RT_SUCCESS(rc))
2055 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u64PtrBase);
2056 if (RT_SUCCESS(rc))
2057 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2058 if (RT_SUCCESS(rc))
2059 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u64PtrBase);
2060 if (RT_SUCCESS(rc))
2061 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2062 if (RT_SUCCESS(rc))
2063 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2064 if (RT_SUCCESS(rc))
2065 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pKNtCtx->u32RegMxCsr);
2066
2067 if (RT_SUCCESS(rc))
2068 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_GS_BASE, &pKNtCtx->u64MsrGsBase);
2069 if (RT_SUCCESS(rc))
2070 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_KERNEL_GS_BASE, &pKNtCtx->u64MsrKernelGsBase);
2071 if (RT_SUCCESS(rc))
2072 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K6_STAR, &pKNtCtx->u64MsrStar);
2073 if (RT_SUCCESS(rc))
2074 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_LSTAR, &pKNtCtx->u64MsrLstar);
2075 if (RT_SUCCESS(rc))
2076 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_CSTAR, &pKNtCtx->u64MsrCstar);
2077 if (RT_SUCCESS(rc))
2078 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_SF_MASK, &pKNtCtx->u64MsrSfMask);
2079 /** @todo XCR0 */
2080
2081 /* Get the emulated DR register state. */
2082 pKNtCtx->u64RegDr0 = pThis->aHwBp[0].GCPtrBp;
2083 pKNtCtx->u64RegDr1 = pThis->aHwBp[1].GCPtrBp;
2084 pKNtCtx->u64RegDr2 = pThis->aHwBp[2].GCPtrBp;
2085 pKNtCtx->u64RegDr3 = pThis->aHwBp[3].GCPtrBp;
2086 pKNtCtx->u64RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2087 pKNtCtx->u64RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2088
2089 if (RT_SUCCESS(rc))
2090 rc = dbgcKdCtxQueryNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, fCtxFlags);
2091
2092 return rc;
2093}
2094
2095
2096/**
2097 * Fills in the given 32bit NT kernel context structure with the requested values.
2098 *
2099 * @returns VBox status code.
2100 * @param pThis The KD context.
2101 * @param idCpu The CPU to query the context for.
2102 * @param pKNtCtx The NT context structure to fill in.
2103 */
2104static int dbgcKdCtxQueryNtKCtx32(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT32 pKNtCtx)
2105{
2106 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2107
2108 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u32RegCr0);
2109 if (RT_SUCCESS(rc))
2110 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u32RegCr2);
2111 if (RT_SUCCESS(rc))
2112 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u32RegCr3);
2113 if (RT_SUCCESS(rc))
2114 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u32RegCr4);
2115
2116 if (RT_SUCCESS(rc))
2117 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2118 if (RT_SUCCESS(rc))
2119 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u32PtrBase);
2120 if (RT_SUCCESS(rc))
2121 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2122 if (RT_SUCCESS(rc))
2123 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u32PtrBase);
2124 if (RT_SUCCESS(rc))
2125 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2126 if (RT_SUCCESS(rc))
2127 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2128
2129 /* Get the emulated DR register state. */
2130 pKNtCtx->u32RegDr0 = (uint32_t)pThis->aHwBp[0].GCPtrBp;
2131 pKNtCtx->u32RegDr1 = (uint32_t)pThis->aHwBp[1].GCPtrBp;
2132 pKNtCtx->u32RegDr2 = (uint32_t)pThis->aHwBp[2].GCPtrBp;
2133 pKNtCtx->u32RegDr3 = (uint32_t)pThis->aHwBp[3].GCPtrBp;
2134 pKNtCtx->u32RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2135 pKNtCtx->u32RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2136
2137 return rc;
2138}
2139
2140
2141/**
2142 * Fills in the given 64bit NT kernel context structure with the requested values.
2143 *
2144 * @returns VBox status code.
2145 * @param pThis The KD context.
2146 * @param idCpu The CPU to query the context for.
2147 * @param pKNtCtx The NT context structure to fill in.
2148 * @param cbSet How many bytes of the context are valid.
2149 */
2150static int dbgcKdCtxSetNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTKCONTEXT64 pKNtCtx, size_t cbSet)
2151{
2152 AssertReturn(cbSet >= RT_UOFFSETOF(NTKCONTEXT64, Ctx), VERR_INVALID_PARAMETER);
2153
2154 uint32_t idxReg = 0;
2155 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
2156
2157 KD_REG_INIT_U64("cr0", pKNtCtx->u64RegCr0);
2158 KD_REG_INIT_U64("cr2", pKNtCtx->u64RegCr2);
2159 KD_REG_INIT_U64("cr3", pKNtCtx->u64RegCr3);
2160 KD_REG_INIT_U64("cr4", pKNtCtx->u64RegCr4);
2161 KD_REG_INIT_U64("cr8", pKNtCtx->u64RegCr8);
2162
2163 KD_REG_INIT_DTR("gdtr", pKNtCtx->Gdtr.u64PtrBase, pKNtCtx->Gdtr.u16Limit);
2164 KD_REG_INIT_DTR("idtr", pKNtCtx->Idtr.u64PtrBase, pKNtCtx->Idtr.u16Limit);
2165
2166#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2167 KD_REG_INIT_U16("tr", pKNtCtx->u16RegTr);
2168 KD_REG_INIT_U16("ldtr", pKNtCtx->u16RegLdtr);
2169#endif
2170 KD_REG_INIT_U32("mxcsr", pKNtCtx->u32RegMxCsr);
2171
2172 KD_REG_INIT_U64("msr_gs_base", pKNtCtx->u64MsrGsBase);
2173 KD_REG_INIT_U64("krnl_gs_base", pKNtCtx->u64MsrKernelGsBase);
2174 KD_REG_INIT_U64("star", pKNtCtx->u64MsrStar);
2175 KD_REG_INIT_U64("lstar", pKNtCtx->u64MsrLstar);
2176 KD_REG_INIT_U64("cstar", pKNtCtx->u64MsrCstar);
2177 KD_REG_INIT_U64("sf_mask", pKNtCtx->u64MsrSfMask);
2178
2179 int rc = DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2180 if ( RT_SUCCESS(rc)
2181 && cbSet > RT_UOFFSETOF(NTKCONTEXT64, Ctx)) /** @todo Probably wrong. */
2182 rc = dbgcKdCtxSetNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, pKNtCtx->Ctx.fContext);
2183
2184 if (RT_SUCCESS(rc))
2185 {
2186 /* Update emulated hardware breakpoint state. */
2187 dbgcKdCtxHwBpDr6Update(pThis, (uint32_t)pKNtCtx->u64RegDr6);
2188 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pKNtCtx->u64RegDr7);
2189 if (RT_SUCCESS(rc))
2190 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[0], pKNtCtx->u64RegDr0);
2191 if (RT_SUCCESS(rc))
2192 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[1], pKNtCtx->u64RegDr1);
2193 if (RT_SUCCESS(rc))
2194 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[2], pKNtCtx->u64RegDr2);
2195 if (RT_SUCCESS(rc))
2196 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[3], pKNtCtx->u64RegDr3);
2197 }
2198
2199 return rc;
2200}
2201
2202#undef KD_REG_INIT_64
2203#undef KD_REG_INIT_32
2204#undef KD_REG_INIT_16
2205#undef KD_REG_INIT_DTR
2206#undef KD_REG_INIT
2207
2208
2209/**
2210 * Validates the given KD packet header.
2211 *
2212 * @returns Flag whether the packet header is valid, false if invalid.
2213 * @param pPktHdr The packet header to validate.
2214 */
2215static bool dbgcKdPktHdrValidate(PCKDPACKETHDR pPktHdr)
2216{
2217 if ( pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_DATA
2218 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_CONTROL
2219 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_BREAKIN)
2220 return false;
2221
2222 if (pPktHdr->u16SubType >= KD_PACKET_HDR_SUB_TYPE_MAX)
2223 return false;
2224
2225 uint32_t idPacket = pPktHdr->idPacket & UINT32_C(0xfffffffe);
2226 if ( idPacket != KD_PACKET_HDR_ID_INITIAL
2227 && idPacket != KD_PACKET_HDR_ID_RESET
2228 && idPacket != 0 /* Happens on the very first packet */)
2229 return false;
2230
2231 return true;
2232}
2233
2234
2235/**
2236 * Generates a checksum from the given buffer.
2237 *
2238 * @returns Generated checksum.
2239 * @param pv The data to generate a checksum from.
2240 * @param cb Number of bytes to checksum.
2241 */
2242static uint32_t dbgcKdPktChkSumGen(const void *pv, size_t cb)
2243{
2244 const uint8_t *pb = (const uint8_t *)pv;
2245 uint32_t u32ChkSum = 0;
2246
2247 while (cb--)
2248 u32ChkSum += *pb++;
2249
2250 return u32ChkSum;
2251}
2252
2253
2254/**
2255 * Generates a checksum from the given segments.
2256 *
2257 * @returns Generated checksum.
2258 * @param paSegs Pointer to the array of segments containing the data.
2259 * @param cSegs Number of segments.
2260 * @param pcbChkSum Where to store the number of bytes checksummed, optional.
2261 */
2262static uint32_t dbgcKdPktChkSumGenSg(PCRTSGSEG paSegs, uint32_t cSegs, size_t *pcbChkSum)
2263{
2264 size_t cbChkSum = 0;
2265 uint32_t u32ChkSum = 0;
2266
2267 for (uint32_t i = 0; i < cSegs; i++)
2268 {
2269 u32ChkSum += dbgcKdPktChkSumGen(paSegs[i].pvSeg, paSegs[i].cbSeg);
2270 cbChkSum += paSegs[i].cbSeg;
2271 }
2272
2273 if (pcbChkSum)
2274 *pcbChkSum = cbChkSum;
2275
2276 return u32ChkSum;
2277}
2278
2279
2280/**
2281 * Waits for an acknowledgment.
2282 *
2283 * @returns VBox status code.
2284 * @param pThis The KD context.
2285 * @param msWait Maximum number of milliseconds to wait for an acknowledge.
2286 * @param pfResend Where to store the resend requested flag on success.
2287 */
2288static int dbgcKdCtxPktWaitForAck(PKDCTX pThis, RTMSINTERVAL msWait, bool *pfResend)
2289{
2290 KDPACKETHDR PktAck;
2291 uint8_t *pbCur = (uint8_t *)&PktAck;
2292 size_t cbLeft = sizeof(PktAck);
2293 uint64_t tsStartMs = RTTimeMilliTS();
2294 int rc = VINF_SUCCESS;
2295
2296 LogFlowFunc(("pThis=%p msWait=%u pfResend=%p\n", pThis, msWait, pfResend));
2297
2298 RT_ZERO(PktAck);
2299
2300 /* There might be breakin packets in the queue, read until we get something else. */
2301 while ( msWait
2302 && RT_SUCCESS(rc))
2303 {
2304 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, msWait))
2305 {
2306 size_t cbRead = 0;
2307 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pbCur, 1, &cbRead);
2308 if ( RT_SUCCESS(rc)
2309 && cbRead == 1)
2310 {
2311 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2312 msWait -= RT_MIN(msWait, tsSpanMs);
2313 tsStartMs = RTTimeMilliTS();
2314
2315 if (*pbCur == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2316 pThis->fBreakinRecv = true;
2317 else
2318 {
2319 pbCur++;
2320 cbLeft--;
2321 break;
2322 }
2323 }
2324 }
2325 else
2326 rc = VERR_TIMEOUT;
2327 }
2328
2329 if ( RT_SUCCESS(rc)
2330 && !msWait)
2331 rc = VERR_TIMEOUT;
2332
2333 if (RT_SUCCESS(rc))
2334 {
2335 while ( msWait
2336 && RT_SUCCESS(rc)
2337 && cbLeft)
2338 {
2339 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, msWait))
2340 {
2341 size_t cbRead = 0;
2342 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pbCur, cbLeft, &cbRead);
2343 if (RT_SUCCESS(rc))
2344 {
2345 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2346 msWait -= RT_MIN(msWait, tsSpanMs);
2347 tsStartMs = RTTimeMilliTS();
2348
2349 cbLeft -= cbRead;
2350 pbCur += cbRead;
2351 }
2352 }
2353 else
2354 rc = VERR_TIMEOUT;
2355 }
2356
2357 if (RT_SUCCESS(rc))
2358 {
2359 if (PktAck.u32Signature == KD_PACKET_HDR_SIGNATURE_CONTROL)
2360 {
2361 if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE)
2362 rc = VINF_SUCCESS;
2363 else if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_RESEND)
2364 {
2365 *pfResend = true;
2366 rc = VINF_SUCCESS;
2367 }
2368 else
2369 rc = VERR_NET_PROTOCOL_ERROR;
2370 }
2371 else
2372 rc = VERR_NET_PROTOCOL_ERROR;
2373 }
2374 }
2375
2376 LogFlowFunc(("returns rc=%Rrc *pfResend=%RTbool\n", rc, *pfResend));
2377 return rc;
2378}
2379
2380
2381/**
2382 * Sends the given packet header and optional segmented body (the trailing byte is sent automatically).
2383 *
2384 * @returns VBox status code.
2385 * @param pThis The KD context.
2386 * @param u32Signature The signature to send.
2387 * @param u16SubType The sub type to send.
2388 * @param paSegs Pointer to the array of segments to send in the body, optional.
2389 * @param cSegs Number of segments.
2390 * @param fAck Flag whether to wait for an acknowledge.
2391 */
2392static int dbgcKdCtxPktSendSg(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2393 PCRTSGSEG paSegs, uint32_t cSegs, bool fAck)
2394{
2395 int rc = VINF_SUCCESS;
2396 uint32_t cRetriesLeft = 3;
2397 uint8_t bTrailer = KD_PACKET_TRAILING_BYTE;
2398 KDPACKETHDR Hdr;
2399
2400 size_t cbChkSum = 0;
2401 uint32_t u32ChkSum = dbgcKdPktChkSumGenSg(paSegs, cSegs, &cbChkSum);
2402
2403 Hdr.u32Signature = u32Signature;
2404 Hdr.u16SubType = u16SubType;
2405 Hdr.cbBody = (uint16_t)cbChkSum;
2406 Hdr.idPacket = pThis->idPktNext;
2407 Hdr.u32ChkSum = u32ChkSum;
2408
2409#ifdef LOG_ENABLED
2410 dbgcKdPktDump(&Hdr, paSegs, cSegs, false /*fRx*/);
2411#endif
2412
2413 while (cRetriesLeft--)
2414 {
2415 bool fResend = false;
2416
2417 rc = dbgcKdCtxWrite(pThis, &Hdr, sizeof(Hdr));
2418 if ( RT_SUCCESS(rc)
2419 && paSegs
2420 && cSegs)
2421 {
2422 for (uint32_t i = 0; i < cSegs && RT_SUCCESS(rc); i++)
2423 rc = dbgcKdCtxWrite(pThis, paSegs[i].pvSeg, paSegs[i].cbSeg);
2424
2425 if (RT_SUCCESS(rc))
2426 rc = dbgcKdCtxWrite(pThis, &bTrailer, sizeof(bTrailer));
2427 }
2428
2429 if (RT_SUCCESS(rc))
2430 {
2431 if (fAck)
2432 rc = dbgcKdCtxPktWaitForAck(pThis, 10 * 1000, &fResend);
2433
2434 if ( RT_SUCCESS(rc)
2435 && !fResend)
2436 break;
2437 }
2438 }
2439
2440 return rc;
2441}
2442
2443
2444/**
2445 * Sends the given packet header and optional body (the trailing byte is sent automatically).
2446 *
2447 * @returns VBox status code.
2448 * @param pThis The KD context.
2449 * @param u32Signature The signature to send.
2450 * @param u16SubType The sub type to send.
2451 * @param pvBody The body to send, optional.
2452 * @param cbBody Body size in bytes.
2453 * @param fAck Flag whether to wait for an acknowledge.
2454 */
2455DECLINLINE(int) dbgcKdCtxPktSend(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2456 const void *pvBody, size_t cbBody,
2457 bool fAck)
2458{
2459 RTSGSEG Seg;
2460
2461 Seg.pvSeg = (void *)pvBody;
2462 Seg.cbSeg = cbBody;
2463 return dbgcKdCtxPktSendSg(pThis, u32Signature, u16SubType, cbBody ? &Seg : NULL, cbBody ? 1 : 0, fAck);
2464}
2465
2466
2467/**
2468 * Sends a resend packet answer.
2469 *
2470 * @returns VBox status code.
2471 * @param pThis The KD context.
2472 */
2473DECLINLINE(int) dbgcKdCtxPktSendResend(PKDCTX pThis)
2474{
2475 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESEND,
2476 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2477}
2478
2479
2480/**
2481 * Sends a resend packet answer.
2482 *
2483 * @returns VBox status code.
2484 * @param pThis The KD context.
2485 */
2486DECLINLINE(int) dbgcKdCtxPktSendReset(PKDCTX pThis)
2487{
2488 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2489 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESET,
2490 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2491}
2492
2493
2494/**
2495 * Sends an acknowledge packet answer.
2496 *
2497 * @returns VBox status code.
2498 * @param pThis The KD context.
2499 */
2500DECLINLINE(int) dbgcKdCtxPktSendAck(PKDCTX pThis)
2501{
2502 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE,
2503 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2504}
2505
2506
2507/**
2508 * Resets the packet receive state machine.
2509 *
2510 * @returns nothing.
2511 * @param pThis The KD context.
2512 */
2513static void dbgcKdCtxPktRecvReset(PKDCTX pThis)
2514{
2515 pThis->enmState = KDRECVSTATE_PACKET_HDR_FIRST_BYTE;
2516 pThis->pbRecv = &pThis->PktHdr.ab[0];
2517 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[0]);
2518 pThis->msRecvTimeout = RT_INDEFINITE_WAIT;
2519 pThis->tsRecvLast = RTTimeMilliTS();
2520}
2521
2522
2523/**
2524 * Sends a Debug I/O string packet.
2525 *
2526 * @returns VBox status code.
2527 * @param pThis The KD context data.
2528 * @param idCpu The CPU ID generating this packet.
2529 * @param pachChars The characters to send (ASCII).
2530 * @param cbChars Number of characters to send.
2531 */
2532static int dbgcKdCtxDebugIoStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachChars, size_t cbChars)
2533{
2534 KDPACKETDEBUGIO DebugIo;
2535 RT_ZERO(DebugIo);
2536
2537 /* Fix your damn log strings if this exceeds 4GB... */
2538 if (cbChars != (uint32_t)cbChars)
2539 return VERR_BUFFER_OVERFLOW;
2540
2541 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2542 DebugIo.u16CpuLvl = 0x6;
2543 DebugIo.idCpu = (uint16_t)idCpu;
2544 DebugIo.u.Str.cbStr = (uint32_t)cbChars;
2545
2546 RTSGSEG aRespSegs[2];
2547
2548 aRespSegs[0].pvSeg = &DebugIo;
2549 aRespSegs[0].cbSeg = sizeof(DebugIo);
2550 aRespSegs[1].pvSeg = (void *)pachChars;
2551 aRespSegs[1].cbSeg = cbChars;
2552
2553 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2554 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2555 if (RT_SUCCESS(rc))
2556 pThis->idPktNext ^= 0x1;
2557
2558 return rc;
2559}
2560
2561
2562/**
2563 * Sends a message to the remotes end.
2564 *
2565 * @returns nothing.
2566 * @param pThis The KD context data.
2567 * @param fWarning Flag whether this is a warning or an informational message.
2568 * @param pszMsg The message to send.
2569 */
2570static void dbgcKdCtxMsgSend(PKDCTX pThis, bool fWarning, const char *pszMsg)
2571{
2572 size_t cchMsg = strlen(pszMsg);
2573
2574 KDPACKETDEBUGIO DebugIo;
2575 RT_ZERO(DebugIo);
2576
2577 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2578 DebugIo.u16CpuLvl = 0x6;
2579 DebugIo.idCpu = 0;
2580
2581 RTSGSEG aRespSegs[5];
2582
2583 aRespSegs[0].pvSeg = &DebugIo;
2584 aRespSegs[0].cbSeg = sizeof(DebugIo);
2585 aRespSegs[1].pvSeg = (void *)"VBoxDbg ";
2586 aRespSegs[1].cbSeg = sizeof("VBoxDbg ") - 1;
2587 if (fWarning)
2588 {
2589 aRespSegs[2].pvSeg = (void *)"WARNING ";
2590 aRespSegs[2].cbSeg = sizeof("WARNING ") - 1;
2591 }
2592 else
2593 {
2594 aRespSegs[2].pvSeg = (void *)"INFO ";
2595 aRespSegs[2].cbSeg = sizeof("INFO ") - 1;
2596 }
2597 aRespSegs[3].pvSeg = (void *)pszMsg;
2598 aRespSegs[3].cbSeg = cchMsg;
2599 aRespSegs[4].pvSeg = (void *)"\r\n";
2600 aRespSegs[4].cbSeg = 2;
2601
2602 DebugIo.u.Str.cbStr = (uint32_t)( aRespSegs[1].cbSeg
2603 + aRespSegs[2].cbSeg
2604 + aRespSegs[3].cbSeg
2605 + aRespSegs[4].cbSeg);
2606
2607 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2608 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2609 if (RT_SUCCESS(rc))
2610 pThis->idPktNext ^= 0x1;
2611}
2612
2613
2614/**
2615 * Queries some user input from the remotes end.
2616 *
2617 * @returns VBox status code.
2618 * @param pThis The KD context data.
2619 * @param idCpu The CPU ID generating this packet.
2620 * @param pachPrompt The prompt to send (ASCII).
2621 * @param cbPrompt Number of characters to send for the prompt.
2622 * @param cbResponseMax Maximum size for the response.
2623 */
2624static int dbgcKdCtxDebugIoGetStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachPrompt, size_t cbPrompt,
2625 size_t cbResponseMax)
2626{
2627 KDPACKETDEBUGIO DebugIo;
2628 RT_ZERO(DebugIo);
2629
2630 /* Fix your damn log strings if this exceeds 4GB... */
2631 if ( cbPrompt != (uint32_t)cbPrompt
2632 || cbResponseMax != (uint32_t)cbResponseMax)
2633 return VERR_BUFFER_OVERFLOW;
2634
2635 DebugIo.u32Type = KD_PACKET_DEBUG_IO_GET_STRING;
2636 DebugIo.u16CpuLvl = 0x6;
2637 DebugIo.idCpu = (uint16_t)idCpu;
2638 DebugIo.u.Prompt.cbPrompt = (uint32_t)cbPrompt;
2639 DebugIo.u.Prompt.cbReturn = (uint32_t)cbResponseMax;
2640
2641 RTSGSEG aRespSegs[2];
2642
2643 aRespSegs[0].pvSeg = &DebugIo;
2644 aRespSegs[0].cbSeg = sizeof(DebugIo);
2645 aRespSegs[1].pvSeg = (void *)pachPrompt;
2646 aRespSegs[1].cbSeg = cbPrompt;
2647
2648 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2649 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2650 if (RT_SUCCESS(rc))
2651 pThis->idPktNext ^= 0x1;
2652
2653 return rc;
2654}
2655
2656
2657/**
2658 * Sends a state change event packet.
2659 *
2660 * @returns VBox status code.
2661 * @param pThis The KD context data.
2662 * @param enmType The event type.
2663 */
2664static int dbgcKdCtxStateChangeSend(PKDCTX pThis, DBGFEVENTTYPE enmType)
2665{
2666 LogFlowFunc(("pThis=%p enmType=%u\n", pThis, enmType));
2667
2668 /* Select the record to send based on the CPU mode. */
2669 int rc = VINF_SUCCESS;
2670 KDPACKETSTATECHANGE64 StateChange64;
2671 RT_ZERO(StateChange64);
2672
2673 StateChange64.u32StateNew = KD_PACKET_STATE_CHANGE_EXCEPTION;
2674 StateChange64.u16CpuLvl = 0x6; /** @todo Figure this one out. */
2675 StateChange64.idCpu = pThis->Dbgc.idCpu;
2676 StateChange64.cCpus = (uint16_t)DBGFR3CpuGetCount(pThis->Dbgc.pUVM);
2677 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RIP, &StateChange64.u64RipThread);
2678 if (RT_SUCCESS(rc))
2679 {
2680 DBGFADDRESS AddrRip;
2681 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRip, StateChange64.u64RipThread);
2682
2683 StateChange64.u64RipThread = KD_PTR_CREATE(pThis, StateChange64.u64RipThread);
2684
2685 /** @todo Properly fill in the exception record. */
2686 switch (enmType)
2687 {
2688 case DBGFEVENT_HALT_DONE:
2689 case DBGFEVENT_BREAKPOINT:
2690 case DBGFEVENT_BREAKPOINT_IO:
2691 case DBGFEVENT_BREAKPOINT_MMIO:
2692 case DBGFEVENT_BREAKPOINT_HYPER:
2693 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_BKPT;
2694 break;
2695 case DBGFEVENT_STEPPED:
2696 case DBGFEVENT_STEPPED_HYPER:
2697 pThis->fSingleStepped = true; /* For emulation of DR6. */
2698 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_SINGLE_STEP;
2699 break;
2700 default:
2701 AssertMsgFailed(("Invalid DBGF event type for state change %d!\n", enmType));
2702 }
2703
2704 StateChange64.u.Exception.ExcpRec.cExcpParms = 3;
2705 StateChange64.u.Exception.u32FirstChance = 0x1;
2706
2707 /** @todo Properly fill in the control report. */
2708 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR6, &StateChange64.uCtrlReport.Amd64.u64RegDr6);
2709 if (RT_SUCCESS(rc))
2710 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR7, &StateChange64.uCtrlReport.Amd64.u64RegDr7);
2711 if (RT_SUCCESS(rc))
2712 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RFLAGS, &StateChange64.uCtrlReport.Amd64.u32RegEflags);
2713 if (RT_SUCCESS(rc))
2714 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_CS, &StateChange64.uCtrlReport.Amd64.u16SegCs);
2715 if (RT_SUCCESS(rc))
2716 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DS, &StateChange64.uCtrlReport.Amd64.u16SegDs);
2717 if (RT_SUCCESS(rc))
2718 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_ES, &StateChange64.uCtrlReport.Amd64.u16SegEs);
2719 if (RT_SUCCESS(rc))
2720 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_FS, &StateChange64.uCtrlReport.Amd64.u16SegFs);
2721
2722 /* Read instruction bytes. */
2723 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
2724 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
2725 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
2726 if (RT_SUCCESS(rc))
2727 {
2728 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2729 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
2730 &StateChange64, sizeof(StateChange64), false /*fAck*/);
2731 }
2732 }
2733
2734 LogFlowFunc(("returns %Rrc\n", rc));
2735 return rc;
2736}
2737
2738
2739/**
2740 * Processes a get version 64 request.
2741 *
2742 * @returns VBox status code.
2743 * @param pThis The KD context.
2744 * @param pPktManip The manipulate packet request.
2745 */
2746static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2747{
2748 KDPACKETMANIPULATE64 Resp;
2749 RT_ZERO(Resp);
2750
2751 /* Fill in the generic part. */
2752 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
2753 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2754 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
2755 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
2756
2757 /* Build our own response in case there is no Windows interface available. */
2758 uint32_t NtBuildNumber = 0x0f2800; /* Used when there is no NT interface available, which probably breaks symbol loading. */
2759 bool f32Bit = false;
2760 if (pThis->pIfWinNt)
2761 {
2762 int rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM,
2763 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
2764 &NtBuildNumber, &f32Bit);
2765 if (RT_SUCCESS(rc))
2766 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, &Resp.u.GetVersion.u64PtrKernBase,
2767 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2768 }
2769
2770 /* Fill in the request specific part. */
2771 Resp.u.GetVersion.u16VersMaj = NtBuildNumber >> 16;
2772 Resp.u.GetVersion.u16VersMin = NtBuildNumber & UINT32_C(0xffff);
2773 Resp.u.GetVersion.u8VersProtocol = 0x6; /* From a Windows 10 guest. */
2774 Resp.u.GetVersion.u8VersKdSecondary = pThis->f32Bit ? 0 : 0x2; /* amd64 has a versioned context (0 and 1 are obsolete). */
2775 Resp.u.GetVersion.fFlags = KD_PACKET_MANIPULATE64_GET_VERSION_F_MP;
2776 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
2777 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
2778 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_MAX - KD_PACKET_MANIPULATE_REQ_MIN;
2779 Resp.u.GetVersion.u64PtrDebuggerDataList = 0;
2780
2781 if (f32Bit)
2782 {
2783 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_I386;
2784 Resp.u.GetVersion.u64PtrKernBase = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrKernBase);
2785 Resp.u.GetVersion.u64PtrPsLoadedModuleList = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2786 }
2787 else
2788 {
2789 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
2790 Resp.u.GetVersion.fFlags |= KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64;
2791 }
2792
2793 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2794 &Resp, sizeof(Resp), true /*fAck*/);
2795}
2796
2797
2798/**
2799 * Processes a read memory 64 request.
2800 *
2801 * @returns VBox status code.
2802 * @param pThis The KD context.
2803 * @param pPktManip The manipulate packet request.
2804 */
2805static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2806{
2807 KDPACKETMANIPULATEHDR RespHdr;
2808 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2809 uint8_t abMem[_4K];
2810 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2811
2812 DBGFADDRESS AddrRead;
2813 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
2814 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
2815 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2816 else
2817 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2818
2819 RTSGSEG aRespSegs[3];
2820 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2821 RespHdr.idReq = pPktManip->Hdr.idReq;
2822 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2823 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2824 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2825
2826 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2827 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2828 XferMem64.cbXfered = (uint32_t)cbRead;
2829
2830 aRespSegs[0].pvSeg = &RespHdr;
2831 aRespSegs[0].cbSeg = sizeof(RespHdr);
2832 aRespSegs[1].pvSeg = &XferMem64;
2833 aRespSegs[1].cbSeg = sizeof(XferMem64);
2834
2835 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
2836 if (RT_SUCCESS(rc))
2837 {
2838 cSegs++;
2839 aRespSegs[2].pvSeg = &abMem[0];
2840 aRespSegs[2].cbSeg = cbRead;
2841 }
2842 else
2843 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2844
2845 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2846 &aRespSegs[0], cSegs, true /*fAck*/);
2847}
2848
2849
2850/**
2851 * Processes a write memory 64 request.
2852 *
2853 * @returns VBox status code.
2854 * @param pThis The KD context.
2855 * @param pPktManip The manipulate packet request.
2856 */
2857static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2858{
2859 KDPACKETMANIPULATEHDR RespHdr;
2860 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2861 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2862
2863 DBGFADDRESS AddrWrite;
2864 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2865 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
2866 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
2867 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2868 else
2869 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2870
2871 RTSGSEG aRespSegs[2];
2872 uint32_t cSegs = 2;
2873 RespHdr.idReq = pPktManip->Hdr.idReq;
2874 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2875 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2876 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2877
2878 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2879 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2880 XferMem64.cbXfered = (uint32_t)cbWrite;
2881
2882 aRespSegs[0].pvSeg = &RespHdr;
2883 aRespSegs[0].cbSeg = sizeof(RespHdr);
2884 aRespSegs[1].pvSeg = &XferMem64;
2885 aRespSegs[1].cbSeg = sizeof(XferMem64);
2886
2887 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
2888 if (RT_FAILURE(rc))
2889 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2890
2891 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2892 &aRespSegs[0], cSegs, true /*fAck*/);
2893}
2894
2895
2896/**
2897 * Processes a continue request.
2898 *
2899 * @returns VBox status code.
2900 * @param pThis The KD context.
2901 * @param pPktManip The manipulate packet request.
2902 */
2903static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2904{
2905 RT_NOREF(pPktManip);
2906 int rc = VINF_SUCCESS;
2907
2908 /* No response, just resume. */
2909 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2910 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2911
2912 return rc;
2913}
2914
2915
2916/**
2917 * Processes a continue request.
2918 *
2919 * @returns VBox status code.
2920 * @param pThis The KD context.
2921 * @param pPktManip The manipulate packet request.
2922 */
2923static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2924{
2925 int rc = VINF_SUCCESS;
2926
2927 /* Update DR7. */
2928 if (pThis->f32Bit)
2929 rc = dbgcKdCtxHwBpDr7Update(pThis, pPktManip->u.Continue2.u.x86.u32RegDr7);
2930 else
2931 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pPktManip->u.Continue2.u.amd64.u64RegDr7);
2932
2933 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
2934 if (pPktManip->u.Continue2.fTrace)
2935 {
2936 PDBGFADDRESS pStackPop = NULL;
2937 RTGCPTR cbStackPop = 0;
2938 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
2939 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
2940 }
2941 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2942 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2943
2944 return rc;
2945}
2946
2947
2948/**
2949 * Processes a set context request.
2950 *
2951 * @returns VBox status code.
2952 * @param pThis The KD context.
2953 * @param pPktManip The manipulate packet request.
2954 */
2955static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2956{
2957 KDPACKETMANIPULATEHDR RespHdr;
2958 KDPACKETMANIPULATE_SETCONTEXT SetContext;
2959 RT_ZERO(RespHdr); RT_ZERO(SetContext);
2960
2961 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2962
2963 RTSGSEG aRespSegs[2];
2964 uint32_t cSegs = 2;
2965 RespHdr.idReq = pPktManip->Hdr.idReq;
2966 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2967 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2968 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2969
2970 /** @todo What do these flags mean? Can't be the context state to set because the valid one is
2971 * in NTCONTEXT64::fContext (observed with WinDbg). */
2972 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
2973
2974 aRespSegs[0].pvSeg = &RespHdr;
2975 aRespSegs[0].cbSeg = sizeof(RespHdr);
2976 aRespSegs[1].pvSeg = &SetContext;
2977 aRespSegs[1].cbSeg = sizeof(SetContext);
2978
2979 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, pNtCtx->fContext);
2980 if (RT_FAILURE(rc))
2981 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2982
2983 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2984 &aRespSegs[0], cSegs, true /*fAck*/);
2985}
2986
2987
2988/**
2989 * Processes a read control space 64 request.
2990 *
2991 * @returns VBox status code.
2992 * @param pThis The KD context.
2993 * @param pPktManip The manipulate packet request.
2994 */
2995static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2996{
2997 KDPACKETMANIPULATEHDR RespHdr;
2998 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2999 uint8_t abResp[sizeof(NTKCONTEXT64)];
3000 uint32_t cbData = 0;
3001 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3002 RT_ZERO(abResp);
3003
3004 RTSGSEG aRespSegs[3];
3005 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
3006 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
3007 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3008 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3009 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3010
3011 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3012 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3013
3014 aRespSegs[0].pvSeg = &RespHdr;
3015 aRespSegs[0].cbSeg = sizeof(RespHdr);
3016 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3017 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3018
3019 int rc = VINF_SUCCESS;
3020 if (pThis->f32Bit)
3021 {
3022 if (pPktManip->u.XferCtrlSpace.u64IdXfer == sizeof(NTCONTEXT32))
3023 {
3024 /* Queries the kernel context. */
3025 rc = dbgcKdCtxQueryNtKCtx32(pThis, RespHdr.idCpu, (PNTKCONTEXT32)&abResp[0]);
3026 if (RT_SUCCESS(rc))
3027 cbData = sizeof(NTKCONTEXT32);
3028 }
3029 }
3030 else
3031 {
3032 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3033 {
3034 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3035 {
3036 if (pThis->pIfWinNt)
3037 {
3038 RTGCUINTPTR GCPtrKpcr = 0;
3039
3040 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
3041 &GCPtrKpcr, NULL /*pKpcrb*/);
3042 if (RT_SUCCESS(rc))
3043 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
3044 }
3045
3046 cbData = sizeof(RTGCUINTPTR);
3047 break;
3048 }
3049 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3050 {
3051 if (pThis->pIfWinNt)
3052 {
3053 RTGCUINTPTR GCPtrKpcrb = 0;
3054
3055 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
3056 NULL /*pKpcr*/, &GCPtrKpcrb);
3057 if (RT_SUCCESS(rc))
3058 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
3059 }
3060
3061 cbData = sizeof(RTGCUINTPTR);
3062 break;
3063 }
3064 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3065 {
3066 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
3067 if (RT_SUCCESS(rc))
3068 cbData = sizeof(NTKCONTEXT64);
3069 break;
3070 }
3071 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3072 {
3073 if (pThis->pIfWinNt)
3074 {
3075 RTGCUINTPTR GCPtrCurThrd = 0;
3076
3077 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, RespHdr.idCpu,
3078 &GCPtrCurThrd);
3079 if (RT_SUCCESS(rc))
3080 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
3081 }
3082
3083 cbData = sizeof(RTGCUINTPTR);
3084 break;
3085 }
3086 default:
3087 rc = VERR_NOT_SUPPORTED;
3088 break;
3089 }
3090 }
3091
3092 if ( RT_SUCCESS(rc)
3093 && cbData)
3094 {
3095 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
3096
3097 cSegs++;
3098 aRespSegs[2].pvSeg = &abResp[0];
3099 aRespSegs[2].cbSeg = cbData;
3100 }
3101 else if (RT_FAILURE(rc))
3102 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3103
3104 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3105 &aRespSegs[0], cSegs, true /*fAck*/);
3106}
3107
3108
3109/**
3110 * Processes a write control space 64 request.
3111 *
3112 * @returns VBox status code.
3113 * @param pThis The KD context.
3114 * @param pPktManip The manipulate packet request.
3115 */
3116static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3117{
3118 KDPACKETMANIPULATEHDR RespHdr;
3119 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
3120 uint32_t cbData = 0;
3121 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3122
3123 RTSGSEG aRespSegs[2];
3124 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
3125 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3126 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3127 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3128
3129 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3130 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3131
3132 aRespSegs[0].pvSeg = &RespHdr;
3133 aRespSegs[0].cbSeg = sizeof(RespHdr);
3134 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3135 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3136
3137 int rc = VINF_SUCCESS;
3138 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3139 {
3140 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3141 {
3142 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3143 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
3144 if (RT_SUCCESS(rc))
3145 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
3146 break;
3147 }
3148 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3149 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3150 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3151 default:
3152 rc = VERR_NOT_SUPPORTED;
3153 break;
3154 }
3155
3156 if (RT_FAILURE(rc))
3157 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3158 else
3159 XferCtrlSpace64.cbXfered = cbData;
3160
3161 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3162 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3163}
3164
3165
3166/**
3167 * Processes a restore breakpoint 64 request.
3168 *
3169 * @returns VBox status code.
3170 * @param pThis The KD context.
3171 * @param pPktManip The manipulate packet request.
3172 */
3173static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3174{
3175 KDPACKETMANIPULATEHDR RespHdr;
3176 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
3177 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
3178
3179 RTSGSEG aRespSegs[2];
3180 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
3181 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3182 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3183 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3184
3185 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
3186
3187 aRespSegs[0].pvSeg = &RespHdr;
3188 aRespSegs[0].cbSeg = sizeof(RespHdr);
3189 aRespSegs[1].pvSeg = &RestoreBkpt64;
3190 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
3191
3192 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
3193 if (RT_SUCCESS(rc))
3194 {
3195 rc = dbgcBpDelete(&pThis->Dbgc, pPktManip->u.RestoreBkpt.u32HndBkpt);
3196 AssertRC(rc);
3197 }
3198 else if (rc != VERR_DBGF_BP_NOT_FOUND)
3199 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3200
3201 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3202 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3203}
3204
3205
3206/**
3207 * Processes a write breakpoint 64 request.
3208 *
3209 * @returns VBox status code.
3210 * @param pThis The KD context.
3211 * @param pPktManip The manipulate packet request.
3212 */
3213static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3214{
3215 KDPACKETMANIPULATEHDR RespHdr;
3216 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
3217 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
3218
3219 RTSGSEG aRespSegs[2];
3220 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
3221 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3222 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3223 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3224
3225 aRespSegs[0].pvSeg = &RespHdr;
3226 aRespSegs[0].cbSeg = sizeof(RespHdr);
3227 aRespSegs[1].pvSeg = &WriteBkpt64;
3228 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
3229
3230 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
3231
3232 DBGFADDRESS BpAddr;
3233 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, KD_PTR_GET(pThis, pPktManip->u.WriteBkpt.u64PtrBkpt));
3234 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
3235 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
3236 if (RT_SUCCESS(rc))
3237 {
3238 rc = dbgcBpAdd(&pThis->Dbgc, WriteBkpt64.u32HndBkpt, NULL /*pszCmd*/);
3239 if (RT_FAILURE(rc))
3240 DBGFR3BpClear(pThis->Dbgc.pUVM, WriteBkpt64.u32HndBkpt);
3241 }
3242 else
3243 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3244
3245 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3246 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3247}
3248
3249
3250/**
3251 * Processes a get context extended 64 request.
3252 *
3253 * @returns VBox status code.
3254 * @param pThis The KD context.
3255 * @param pPktManip The manipulate packet request.
3256 */
3257static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3258{
3259 KDPACKETMANIPULATEHDR RespHdr;
3260 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
3261 union
3262 {
3263 NTCONTEXT64 v64;
3264 NTCONTEXT32 v32;
3265 } NtCtx;
3266 RT_ZERO(RespHdr); RT_ZERO(ContextEx); RT_ZERO(NtCtx);
3267
3268 RTSGSEG aRespSegs[3];
3269 uint32_t cSegs = 2;
3270 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
3271 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3272 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3273 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3274
3275 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
3276 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
3277 ContextEx.cbXfered = 0;
3278
3279 aRespSegs[0].pvSeg = &RespHdr;
3280 aRespSegs[0].cbSeg = sizeof(RespHdr);
3281 aRespSegs[1].pvSeg = &ContextEx;
3282 aRespSegs[1].cbSeg = sizeof(ContextEx);
3283
3284 int rc = VINF_SUCCESS;
3285 uint32_t cbCtx = pThis->f32Bit ? sizeof(NtCtx.v32) : sizeof(NtCtx.v64);
3286 if (pThis->f32Bit)
3287 dbgcKdCtxQueryNtCtx32(pThis, pPktManip->Hdr.idCpu, &NtCtx.v32, NTCONTEXT32_F_FULL);
3288 else
3289 dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx.v64, NTCONTEXT64_F_FULL);
3290 if ( RT_SUCCESS(rc)
3291 && pPktManip->u.ContextEx.offStart < cbCtx)
3292 {
3293 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3294 ContextEx.cbXfered = RT_MIN(cbCtx - ContextEx.offStart, ContextEx.cbXfer);
3295
3296 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
3297 aRespSegs[2].cbSeg = ContextEx.cbXfered;
3298 cSegs++;
3299 }
3300
3301 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3302 &aRespSegs[0], cSegs, true /*fAck*/);
3303}
3304
3305
3306/**
3307 * Processes a query memory 64 request.
3308 *
3309 * @returns VBox status code.
3310 * @param pThis The KD context.
3311 * @param pPktManip The manipulate packet request.
3312 */
3313static int dbgcKdCtxPktManipulate64QueryMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3314{
3315 KDPACKETMANIPULATEHDR RespHdr;
3316 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
3317 RT_ZERO(RespHdr); RT_ZERO(QueryMemory);
3318
3319 RTSGSEG aRespSegs[2];
3320 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY;
3321 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3322 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3323 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3324
3325 /** @todo Need DBGF API to query protection and privilege level from guest page tables. */
3326 QueryMemory.u64GCPtr = pPktManip->u.QueryMemory.u64GCPtr;
3327 QueryMemory.u32AddrSpace = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_KERNEL;
3328 QueryMemory.u32Flags = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_READ
3329 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_WRITE
3330 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_EXEC;
3331
3332 aRespSegs[0].pvSeg = &RespHdr;
3333 aRespSegs[0].cbSeg = sizeof(RespHdr);
3334 aRespSegs[1].pvSeg = &QueryMemory;
3335 aRespSegs[1].cbSeg = sizeof(QueryMemory);
3336
3337 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3338 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3339}
3340
3341
3342/**
3343 * Processes a search memory 64 request.
3344 *
3345 * @returns VBox status code.
3346 * @param pThis The KD context.
3347 * @param pPktManip The manipulate packet request.
3348 */
3349static int dbgcKdCtxPktManipulate64SearchMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3350{
3351 KDPACKETMANIPULATEHDR RespHdr;
3352 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
3353 RT_ZERO(RespHdr); RT_ZERO(SearchMemory);
3354
3355 RTSGSEG aRespSegs[2];
3356 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY;
3357 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3358 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3359 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3360
3361 SearchMemory.u64GCPtr = pPktManip->u.SearchMemory.u64GCPtr;
3362 SearchMemory.cbSearch = pPktManip->u.SearchMemory.cbSearch;
3363 SearchMemory.cbPattern = pPktManip->u.SearchMemory.cbPattern;
3364
3365 /* Validate the pattern length and start searching. */
3366 if (pPktManip->u.SearchMemory.cbPattern < sizeof(pThis->abBody) - sizeof(*pPktManip))
3367 {
3368 DBGFADDRESS StartAddress;
3369 DBGFADDRESS HitAddress;
3370 VMCPUID idCpu = pPktManip->Hdr.idCpu;
3371 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &StartAddress, pPktManip->u.SearchMemory.u64GCPtr);
3372
3373 /** @todo WindDbg sends CPU ID 32 sometimes, maybe that means continue search on last used CPU?. */
3374 if (idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM))
3375 idCpu = pThis->Dbgc.idCpu;
3376
3377 int rc = DBGFR3MemScan(pThis->Dbgc.pUVM, idCpu, &StartAddress, pPktManip->u.SearchMemory.cbSearch, 1,
3378 &pThis->abBody[sizeof(*pPktManip)], pPktManip->u.SearchMemory.cbPattern, &HitAddress);
3379 if (RT_SUCCESS(rc))
3380 SearchMemory.u64GCPtr = HitAddress.FlatPtr;
3381 else if (rc == VERR_DBGF_MEM_NOT_FOUND)
3382 RespHdr.u32NtStatus = NTSTATUS_NOT_FOUND;
3383 else
3384 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3385 }
3386 else
3387 RespHdr.u32NtStatus = NTSTATUS_BUFFER_OVERFLOW;
3388
3389 aRespSegs[0].pvSeg = &RespHdr;
3390 aRespSegs[0].cbSeg = sizeof(RespHdr);
3391 aRespSegs[1].pvSeg = &SearchMemory;
3392 aRespSegs[1].cbSeg = sizeof(SearchMemory);
3393
3394 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3395 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3396}
3397
3398
3399/**
3400 * Processes a cause bugcheck 64 request.
3401 *
3402 * @returns VBox status code.
3403 * @param pThis The KD context.
3404 * @param pPktManip The manipulate packet request.
3405 *
3406 * @note We abuse this request to initiate a native VBox debugger command prompt from the remote end
3407 * (There is monitor/Rcmd equivalent like with GDB unfortunately).
3408 */
3409static int dbgcKdCtxPktManipulate64CauseBugCheck(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3410{
3411 RT_NOREF(pPktManip);
3412 pThis->fInVBoxDbg = true;
3413 return dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3414 512 /*cbResponseMax*/);
3415}
3416
3417
3418/**
3419 * Processes a switch processor request.
3420 *
3421 * @returns VBox status code.
3422 * @param pThis The KD context.
3423 * @param pPktManip The manipulate packet request.
3424 */
3425static int dbgcKdCtxPktManipulate64SwitchProcessor(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3426{
3427 int rc = VINF_SUCCESS;
3428
3429 if (RT_UNLIKELY(pPktManip->Hdr.idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM)))
3430 {
3431 KDPACKETMANIPULATEHDR RespHdr;
3432 RT_ZERO(RespHdr);
3433
3434 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR;
3435 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3436 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3437 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Test this path. */
3438 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3439 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3440 }
3441 else
3442 {
3443 pThis->Dbgc.idCpu = pPktManip->Hdr.idCpu;
3444 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3445 }
3446
3447 return rc;
3448}
3449
3450
3451/**
3452 * Processes a manipulate packet.
3453 *
3454 * @returns VBox status code.
3455 * @param pThis The KD context.
3456 */
3457static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
3458{
3459 int rc = VINF_SUCCESS;
3460 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
3461
3462 switch (pPktManip->Hdr.idReq)
3463 {
3464 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
3465 {
3466 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
3467 break;
3468 }
3469 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
3470 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
3471 {
3472 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
3473 break;
3474 }
3475 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
3476 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
3477 {
3478 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
3479 break;
3480 }
3481 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
3482 {
3483 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
3484 break;
3485 }
3486 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
3487 {
3488 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
3489 break;
3490 }
3491 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
3492 {
3493 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
3494 break;
3495 }
3496 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
3497 {
3498 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
3499 break;
3500 }
3501 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
3502 {
3503 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
3504 break;
3505 }
3506 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
3507 {
3508 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
3509 break;
3510 }
3511 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
3512 {
3513 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
3514 break;
3515 }
3516 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
3517 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
3518 break;
3519 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
3520 {
3521 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
3522 break;
3523 }
3524 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
3525 {
3526 rc = dbgcKdCtxPktManipulate64QueryMemory(pThis, pPktManip);
3527 break;
3528 }
3529 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
3530 {
3531 rc = dbgcKdCtxPktManipulate64SearchMemory(pThis, pPktManip);
3532 break;
3533 }
3534 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK:
3535 {
3536 rc = dbgcKdCtxPktManipulate64CauseBugCheck(pThis, pPktManip);
3537 break;
3538 }
3539 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR:
3540 {
3541 rc = dbgcKdCtxPktManipulate64SwitchProcessor(pThis, pPktManip);
3542 break;
3543 }
3544 case KD_PACKET_MANIPULATE_REQ_REBOOT:
3545 {
3546 rc = VMR3Reset(pThis->Dbgc.pUVM); /* Doesn't expect an answer here. */
3547 if ( RT_SUCCESS(rc)
3548 && DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3549 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3550 break;
3551 }
3552 default:
3553 KDPACKETMANIPULATEHDR RespHdr;
3554 RT_ZERO(RespHdr);
3555
3556 RespHdr.idReq = pPktManip->Hdr.idReq;
3557 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3558 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3559 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
3560 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3561 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3562 break;
3563 }
3564
3565 return rc;
3566}
3567
3568
3569/**
3570 * Tries to detect the guest OS running in the VM looking specifically for the Windows NT kind.
3571 *
3572 * @returns Nothing.
3573 * @param pThis The KD context.
3574 */
3575static void dbgcKdCtxDetectGstOs(PKDCTX pThis)
3576{
3577 pThis->pIfWinNt = NULL;
3578
3579 /* Try detecting a Windows NT guest. */
3580 char szName[64];
3581 int rc = DBGFR3OSDetect(pThis->Dbgc.pUVM, szName, sizeof(szName));
3582 if (RT_SUCCESS(rc))
3583 {
3584 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pThis->Dbgc.pUVM, DBGFOSINTERFACE_WINNT);
3585 if (pThis->pIfWinNt)
3586 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3587 else
3588 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3589 }
3590 else
3591 {
3592 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3593 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3594 }
3595
3596 if (pThis->pIfWinNt)
3597 {
3598 rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM,
3599 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
3600 NULL /*puBuildNumber*/, &pThis->f32Bit);
3601 AssertRC(rc);
3602 }
3603 else
3604 {
3605 /*
3606 * Try to detect bitness based on the current CPU mode which might fool us (32bit process running
3607 * inside of 64bit host).
3608 */
3609 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
3610 if (enmMode == CPUMMODE_PROTECTED)
3611 pThis->f32Bit = true;
3612 else if (enmMode == CPUMMODE_LONG)
3613 pThis->f32Bit = false;
3614 else
3615 LogRel(("DBGC/Kd: Heh, trying to debug real mode code with WinDbg are we? Good luck with that...\n"));
3616 }
3617}
3618
3619
3620/**
3621 * Processes a fully received packet.
3622 *
3623 * @returns VBox status code.
3624 * @param pThis The KD context.
3625 */
3626static int dbgcKdCtxPktProcess(PKDCTX pThis)
3627{
3628 int rc = VINF_SUCCESS;
3629
3630 pThis->fBreakinRecv = false;
3631
3632 /* Verify checksum. */
3633 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
3634 {
3635 /** @todo Check packet id. */
3636 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
3637 {
3638 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3639 rc = dbgcKdCtxPktSendAck(pThis);
3640 }
3641 if (RT_SUCCESS(rc))
3642 {
3643#ifdef LOG_ENABLED
3644 RTSGSEG Seg;
3645 Seg.pvSeg = &pThis->abBody[0];
3646 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
3647 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
3648#endif
3649
3650 switch (pThis->PktHdr.Fields.u16SubType)
3651 {
3652 case KD_PACKET_HDR_SUB_TYPE_RESET:
3653 {
3654 dbgcKdCtxDetectGstOs(pThis);
3655
3656 pThis->idPktNext = 0;
3657 rc = dbgcKdCtxPktSendReset(pThis);
3658 if (RT_SUCCESS(rc))
3659 {
3660 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3661 if (rc == VWRN_DBGF_ALREADY_HALTED)
3662 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3663 }
3664 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
3665 break;
3666 }
3667 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
3668 {
3669 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3670 rc = dbgcKdCtxPktManipulate64Process(pThis);
3671 break;
3672 }
3673 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
3674 case KD_PACKET_HDR_SUB_TYPE_RESEND:
3675 {
3676 /* Don't do anything. */
3677 rc = VINF_SUCCESS;
3678 break;
3679 }
3680 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO:
3681 {
3682 if (pThis->fInVBoxDbg)
3683 {
3684 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3685 /* Get the string and execute it. */
3686 PCKDPACKETDEBUGIO pPktDbgIo = (PCKDPACKETDEBUGIO)&pThis->abBody[0];
3687 if ( pPktDbgIo->u32Type == KD_PACKET_DEBUG_IO_GET_STRING
3688 && pPktDbgIo->u.Prompt.cbReturn <= sizeof(pThis->abBody) - sizeof(*pPktDbgIo) - 1)
3689 {
3690 if (pPktDbgIo->u.Prompt.cbReturn)
3691 {
3692 /* Terminate return value. */
3693 pThis->abBody[sizeof(*pPktDbgIo) + pPktDbgIo->u.Prompt.cbReturn] = '\0';
3694
3695 const char *pszCmd = (const char *)&pThis->abBody[sizeof(*pPktDbgIo)];
3696 /* Filter out 'exit' which is handled here directly and exits the debug loop. */
3697 if (!strcmp(pszCmd, "exit"))
3698 pThis->fInVBoxDbg = false;
3699 else
3700 {
3701 rc = pThis->Dbgc.CmdHlp.pfnExec(&pThis->Dbgc.CmdHlp, pszCmd);
3702 if (RT_SUCCESS(rc))
3703 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3704 512 /*cbResponseMax*/);
3705 else
3706 LogRel(("DBGC/Kd: Executing command \"%s\" failed with rc=%Rrc\n", pszCmd, rc));
3707 }
3708 }
3709 else
3710 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3711 512 /*cbResponseMax*/);
3712 }
3713 else
3714 LogRel(("DBGC/Kd: Received invalid DEBUG_IO packet from remote end, ignoring\n"));
3715 }
3716 else
3717 LogRel(("DBGC/Kd: Received out of band DEBUG_IO packet from remote end, ignoring\n"));
3718 break;
3719 }
3720 default:
3721 rc = VERR_NOT_IMPLEMENTED;
3722 }
3723 }
3724 }
3725 else
3726 {
3727 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3728 rc = dbgcKdCtxPktSendResend(pThis);
3729 }
3730
3731 if (pThis->fBreakinRecv)
3732 {
3733 pThis->fBreakinRecv = false;
3734 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3735 if (rc == VWRN_DBGF_ALREADY_HALTED)
3736 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3737 }
3738
3739 /* Next packet. */
3740 dbgcKdCtxPktRecvReset(pThis);
3741 return rc;
3742}
3743
3744
3745/**
3746 * Processes the received data based on the current state.
3747 *
3748 * @returns VBox status code.
3749 * @param pThis The KD context.
3750 */
3751static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
3752{
3753 int rc = VINF_SUCCESS;
3754
3755 switch (pThis->enmState)
3756 {
3757 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
3758 {
3759 /* Does it look like a valid packet start?. */
3760 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
3761 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
3762 {
3763 pThis->pbRecv = &pThis->PktHdr.ab[1];
3764 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3765 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
3766 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
3767 }
3768 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3769 {
3770 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3771 if (rc == VWRN_DBGF_ALREADY_HALTED)
3772 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3773 dbgcKdCtxPktRecvReset(pThis);
3774 }
3775 /* else: Ignore and continue. */
3776 break;
3777 }
3778 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
3779 {
3780 /*
3781 * If the first and second byte differ there might be a single breakin
3782 * packet byte received and this is actually the start of a new packet.
3783 */
3784 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
3785 {
3786 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3787 {
3788 /* Halt the VM and rearrange the packet receiving state machine. */
3789 LogFlow(("DbgKd: Halting VM!\n"));
3790
3791 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3792 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
3793 pThis->pbRecv = &pThis->PktHdr.ab[1];
3794 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3795 }
3796 else
3797 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
3798 }
3799 else
3800 {
3801 /* Normal packet receive continues with the rest of the header. */
3802 pThis->pbRecv = &pThis->PktHdr.ab[2];
3803 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
3804 pThis->enmState = KDRECVSTATE_PACKET_HDR;
3805 }
3806 break;
3807 }
3808 case KDRECVSTATE_PACKET_HDR:
3809 {
3810 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
3811 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
3812 {
3813 /* Start receiving the body. */
3814 if (pThis->PktHdr.Fields.cbBody)
3815 {
3816 pThis->pbRecv = &pThis->abBody[0];
3817 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
3818 pThis->enmState = KDRECVSTATE_PACKET_BODY;
3819 }
3820 else /* No body means no trailer byte it looks like. */
3821 rc = dbgcKdCtxPktProcess(pThis);
3822 }
3823 else
3824 rc = VERR_NET_PROTOCOL_ERROR;
3825 break;
3826 }
3827 case KDRECVSTATE_PACKET_BODY:
3828 {
3829 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
3830 pThis->bTrailer = 0;
3831 pThis->pbRecv = &pThis->bTrailer;
3832 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
3833 break;
3834 }
3835 case KDRECVSTATE_PACKET_TRAILER:
3836 {
3837 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
3838 rc = dbgcKdCtxPktProcess(pThis);
3839 else
3840 rc = VERR_NET_PROTOCOL_ERROR;
3841 break;
3842 }
3843 default:
3844 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
3845 }
3846
3847 return rc;
3848}
3849
3850
3851/**
3852 * Receive data and processes complete packets.
3853 *
3854 * @returns Status code.
3855 * @param pThis The KD context.
3856 */
3857static int dbgcKdCtxRecv(PKDCTX pThis)
3858{
3859 int rc = VINF_SUCCESS;
3860
3861 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
3862
3863 if (pThis->cbRecvLeft)
3864 {
3865 size_t cbRead = 0;
3866 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
3867 if (RT_SUCCESS(rc))
3868 {
3869 pThis->tsRecvLast = RTTimeMilliTS();
3870 pThis->cbRecvLeft -= cbRead;
3871 pThis->pbRecv += cbRead;
3872 if (!pThis->cbRecvLeft)
3873 rc = dbgcKdCtxRecvDataProcess(pThis);
3874 }
3875 }
3876
3877 LogFlowFunc(("returns rc=%Rrc\n", rc));
3878 return rc;
3879}
3880
3881
3882/**
3883 * Processes debugger events.
3884 *
3885 * @returns VBox status code.
3886 * @param pThis The KD context data.
3887 * @param pEvent Pointer to event data.
3888 */
3889static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
3890{
3891 /*
3892 * Process the event.
3893 */
3894 PDBGC pDbgc = &pThis->Dbgc;
3895 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
3896 pThis->Dbgc.iArg = 0;
3897 int rc = VINF_SUCCESS;
3898 VMCPUID idCpuOld = pDbgc->idCpu;
3899 pDbgc->idCpu = pEvent->idCpu;
3900 switch (pEvent->enmType)
3901 {
3902 /*
3903 * The first part is events we have initiated with commands.
3904 */
3905 case DBGFEVENT_HALT_DONE:
3906 {
3907 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3908 break;
3909 }
3910
3911 /*
3912 * The second part is events which can occur at any time.
3913 */
3914 case DBGFEVENT_FATAL_ERROR:
3915 {
3916 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
3917 dbgcGetEventCtx(pEvent->enmCtx));
3918 if (RT_SUCCESS(rc))
3919 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3920 break;
3921 }
3922
3923 case DBGFEVENT_BREAKPOINT:
3924 case DBGFEVENT_BREAKPOINT_IO:
3925 case DBGFEVENT_BREAKPOINT_MMIO:
3926 case DBGFEVENT_BREAKPOINT_HYPER:
3927 {
3928 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.hBp);
3929 switch (rc)
3930 {
3931 case VERR_DBGC_BP_NOT_FOUND:
3932 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
3933 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
3934 break;
3935
3936 case VINF_DBGC_BP_NO_COMMAND:
3937 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
3938 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
3939 break;
3940
3941 case VINF_BUFFER_OVERFLOW:
3942 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
3943 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
3944 break;
3945
3946 default:
3947 break;
3948 }
3949 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL))
3950 {
3951 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3952
3953 /* Set the resume flag to ignore the breakpoint when resuming execution. */
3954 if ( RT_SUCCESS(rc)
3955 && pEvent->enmType == DBGFEVENT_BREAKPOINT)
3956 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
3957 }
3958
3959 /* Figure out the breakpoint and set the triggered flag for emulation of DR6. */
3960 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
3961 {
3962 if (pThis->aHwBp[i].hDbgfBp == pEvent->u.Bp.hBp)
3963 {
3964 pThis->aHwBp[i].fTriggered = true;
3965 break;
3966 }
3967 }
3968
3969 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3970 break;
3971 }
3972
3973 case DBGFEVENT_STEPPED:
3974 case DBGFEVENT_STEPPED_HYPER:
3975 {
3976 pThis->fSingleStepped = true; /* For emulation of DR6. */
3977 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3978 break;
3979 }
3980
3981 case DBGFEVENT_ASSERTION_HYPER:
3982 {
3983 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3984 "\ndbgf event: Hypervisor Assertion! (%s)\n"
3985 "%s"
3986 "%s"
3987 "\n",
3988 dbgcGetEventCtx(pEvent->enmCtx),
3989 pEvent->u.Assert.pszMsg1,
3990 pEvent->u.Assert.pszMsg2);
3991 if (RT_SUCCESS(rc))
3992 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3993 break;
3994 }
3995
3996 case DBGFEVENT_DEV_STOP:
3997 {
3998 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3999 "\n"
4000 "dbgf event: DBGFSTOP (%s)\n"
4001 "File: %s\n"
4002 "Line: %d\n"
4003 "Function: %s\n",
4004 dbgcGetEventCtx(pEvent->enmCtx),
4005 pEvent->u.Src.pszFile,
4006 pEvent->u.Src.uLine,
4007 pEvent->u.Src.pszFunction);
4008 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
4009 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4010 "Message: %s\n",
4011 pEvent->u.Src.pszMessage);
4012 if (RT_SUCCESS(rc))
4013 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4014 break;
4015 }
4016
4017
4018 case DBGFEVENT_INVALID_COMMAND:
4019 {
4020 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
4021 break;
4022 }
4023
4024 case DBGFEVENT_POWERING_OFF:
4025 {
4026 pThis->Dbgc.fReady = false;
4027 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, false);
4028 rc = VERR_GENERAL_FAILURE;
4029 break;
4030 }
4031
4032 default:
4033 {
4034 /*
4035 * Probably a generic event. Look it up to find its name.
4036 */
4037 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
4038 if (pEvtDesc)
4039 {
4040 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
4041 {
4042 Assert(pEvtDesc->pszDesc);
4043 Assert(pEvent->u.Generic.cArgs == 1);
4044 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
4045 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
4046 }
4047 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
4048 {
4049 Assert(pEvent->u.Generic.cArgs >= 5);
4050 char szDetails[512];
4051 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
4052 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
4053 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
4054 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
4055 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
4056 szDetails);
4057 }
4058 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
4059 || pEvent->u.Generic.cArgs > 1
4060 || ( pEvent->u.Generic.cArgs == 1
4061 && pEvent->u.Generic.auArgs[0] != 0))
4062 {
4063 if (pEvtDesc->pszDesc)
4064 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
4065 pEvtDesc->pszName, pEvtDesc->pszDesc);
4066 else
4067 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
4068 if (pEvent->u.Generic.cArgs <= 1)
4069 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
4070 else
4071 {
4072 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
4073 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
4074 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
4075 }
4076 }
4077 else
4078 {
4079 if (pEvtDesc->pszDesc)
4080 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
4081 pEvtDesc->pszName, pEvtDesc->pszDesc);
4082 else
4083 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
4084 }
4085 }
4086 else
4087 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
4088 break;
4089 }
4090 }
4091
4092 pDbgc->idCpu = idCpuOld;
4093 return rc;
4094}
4095
4096
4097/**
4098 * Handle a receive timeout.
4099 *
4100 * @returns VBox status code.
4101 * @param pThis Pointer to the KD context.
4102 */
4103static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
4104{
4105 int rc = VINF_SUCCESS;
4106
4107 LogFlowFunc(("pThis=%p\n", pThis));
4108
4109 /*
4110 * If a single breakin packet byte was received but the header is otherwise incomplete
4111 * the VM is halted and a state change will be sent in the event processing loop.
4112 */
4113 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
4114 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
4115 {
4116 LogFlow(("DbgKd: Halting VM!\n"));
4117 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
4118 }
4119 else /* Send a reset packet */ /** @todo Figure out the semantics in this case exactly. */
4120 rc = dbgcKdCtxPktSendReset(pThis);
4121
4122 dbgcKdCtxPktRecvReset(pThis);
4123
4124 LogFlowFunc(("rc=%Rrc\n", rc));
4125 return rc;
4126}
4127
4128
4129/**
4130 * @copydoc DBGC::pfnOutput
4131 */
4132static DECLCALLBACK(int) dbgcKdOutput(void *pvUser, const char *pachChars, size_t cbChars)
4133{
4134 PKDCTX pThis = (PKDCTX)pvUser;
4135
4136 return dbgcKdCtxDebugIoStrSend(pThis, pThis->Dbgc.idCpu, pachChars, cbChars);
4137}
4138
4139
4140/**
4141 * Run the debugger console.
4142 *
4143 * @returns VBox status code.
4144 * @param pThis Pointer to the KD context.
4145 */
4146int dbgcKdRun(PKDCTX pThis)
4147{
4148 /*
4149 * We're ready for commands now.
4150 */
4151 pThis->Dbgc.fReady = true;
4152 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, true);
4153
4154 /*
4155 * Main Debugger Loop.
4156 *
4157 * This loop will either block on waiting for input or on waiting on
4158 * debug events. If we're forwarding the log we cannot wait for long
4159 * before we must flush the log.
4160 */
4161 int rc;
4162 for (;;)
4163 {
4164 rc = VERR_SEM_OUT_OF_TURN;
4165 if (pThis->Dbgc.pUVM)
4166 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
4167
4168 if (RT_SUCCESS(rc))
4169 {
4170 /*
4171 * Wait for a debug event.
4172 */
4173 DBGFEVENT Evt;
4174 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
4175 if (RT_SUCCESS(rc))
4176 {
4177 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
4178 if (RT_FAILURE(rc))
4179 break;
4180 }
4181 else if (rc != VERR_TIMEOUT)
4182 break;
4183
4184 /*
4185 * Check for input.
4186 */
4187 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 0))
4188 {
4189 rc = dbgcKdCtxRecv(pThis);
4190 if (RT_FAILURE(rc))
4191 break;
4192 }
4193 }
4194 else if (rc == VERR_SEM_OUT_OF_TURN)
4195 {
4196 /*
4197 * Wait for input.
4198 */
4199 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 1000))
4200 {
4201 rc = dbgcKdCtxRecv(pThis);
4202 if (RT_FAILURE(rc))
4203 break;
4204 }
4205 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
4206 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
4207 rc = dbgcKdCtxRecvTimeout(pThis);
4208 }
4209 else
4210 break;
4211 }
4212
4213 return rc;
4214}
4215
4216
4217/**
4218 * Creates a KD context instance with the given backend.
4219 *
4220 * @returns VBox status code.
4221 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
4222 * @param pIo Pointer to the I/O callback table.
4223 * @param fFlags Flags controlling the behavior.
4224 */
4225static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PCDBGCIO pIo, unsigned fFlags)
4226{
4227 /*
4228 * Validate input.
4229 */
4230 AssertPtrReturn(pIo, VERR_INVALID_POINTER);
4231 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
4232
4233 /*
4234 * Allocate and initialize.
4235 */
4236 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
4237 if (!pThis)
4238 return VERR_NO_MEMORY;
4239
4240 dbgcInitCmdHlp(&pThis->Dbgc);
4241 /*
4242 * This is compied from the native debug console (will be used for monitor commands)
4243 * in DBGCConsole.cpp. Try to keep both functions in sync.
4244 */
4245 pThis->Dbgc.pIo = pIo;
4246 pThis->Dbgc.pfnOutput = dbgcKdOutput;
4247 pThis->Dbgc.pvOutputUser = pThis;
4248 pThis->Dbgc.pVM = NULL;
4249 pThis->Dbgc.pUVM = NULL;
4250 pThis->Dbgc.idCpu = 0;
4251 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
4252 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
4253 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
4254 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
4255 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
4256 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
4257 //pThis->Dbgc.fLog = false;
4258 pThis->Dbgc.fRegTerse = true;
4259 pThis->Dbgc.fStepTraceRegs = true;
4260 //pThis->Dbgc.cPagingHierarchyDumps = 0;
4261 //pThis->Dbgc.DisasmPos = {0};
4262 //pThis->Dbgc.SourcePos = {0};
4263 //pThis->Dbgc.DumpPos = {0};
4264 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
4265 //pThis->Dbgc.cbDumpElement = 0;
4266 //pThis->Dbgc.cVars = 0;
4267 //pThis->Dbgc.paVars = NULL;
4268 //pThis->Dbgc.pPlugInHead = NULL;
4269 //pThis->Dbgc.pFirstBp = NULL;
4270 //pThis->Dbgc.abSearch = {0};
4271 //pThis->Dbgc.cbSearch = 0;
4272 pThis->Dbgc.cbSearchUnit = 1;
4273 pThis->Dbgc.cMaxSearchHits = 1;
4274 //pThis->Dbgc.SearchAddr = {0};
4275 //pThis->Dbgc.cbSearchRange = 0;
4276
4277 //pThis->Dbgc.uInputZero = 0;
4278 //pThis->Dbgc.iRead = 0;
4279 //pThis->Dbgc.iWrite = 0;
4280 //pThis->Dbgc.cInputLines = 0;
4281 //pThis->Dbgc.fInputOverflow = false;
4282 pThis->Dbgc.fReady = true;
4283 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
4284 //pThis->Dbgc.iArg = 0;
4285 //pThis->Dbgc.rcOutput = 0;
4286 //pThis->Dbgc.rcCmd = 0;
4287
4288 //pThis->Dbgc.pszHistoryFile = NULL;
4289 //pThis->Dbgc.pszGlobalInitScript = NULL;
4290 //pThis->Dbgc.pszLocalInitScript = NULL;
4291
4292 dbgcEvalInit();
4293
4294 pThis->fBreakinRecv = false;
4295 pThis->fInVBoxDbg = false;
4296 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
4297 pThis->pIfWinNt = NULL;
4298 pThis->f32Bit = false;
4299 dbgcKdCtxPktRecvReset(pThis);
4300
4301 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
4302 {
4303 PKDCTXHWBP pBp = &pThis->aHwBp[i];
4304 pBp->hDbgfBp = NIL_DBGFBP;
4305 }
4306
4307 dbgcKdCtxHwBpReset(pThis);
4308
4309 *ppKdCtx = pThis;
4310 return VINF_SUCCESS;
4311}
4312
4313
4314/**
4315 * Destroys the given KD context.
4316 *
4317 * @returns nothing.
4318 * @param pThis The KD context to destroy.
4319 */
4320static void dbgcKdCtxDestroy(PKDCTX pThis)
4321{
4322 AssertPtr(pThis);
4323
4324 pThis->pIfWinNt = NULL;
4325
4326 /* Detach from the VM. */
4327 if (pThis->Dbgc.pUVM)
4328 DBGFR3Detach(pThis->Dbgc.pUVM);
4329
4330 /* Free config strings. */
4331 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
4332 pThis->Dbgc.pszGlobalInitScript = NULL;
4333 RTStrFree(pThis->Dbgc.pszLocalInitScript);
4334 pThis->Dbgc.pszLocalInitScript = NULL;
4335 RTStrFree(pThis->Dbgc.pszHistoryFile);
4336 pThis->Dbgc.pszHistoryFile = NULL;
4337
4338 /* Finally, free the instance memory. */
4339 RTMemFree(pThis);
4340}
4341
4342
4343DECL_HIDDEN_CALLBACK(int) dbgcKdStubRunloop(PUVM pUVM, PCDBGCIO pIo, unsigned fFlags)
4344{
4345 /*
4346 * Validate input.
4347 */
4348 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
4349 PVM pVM = NULL;
4350 if (pUVM)
4351 {
4352 pVM = VMR3GetVM(pUVM);
4353 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
4354 }
4355
4356 /*
4357 * Allocate and initialize instance data
4358 */
4359 PKDCTX pThis;
4360 int rc = dbgcKdCtxCreate(&pThis, pIo, fFlags);
4361 if (RT_FAILURE(rc))
4362 return rc;
4363 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
4364 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
4365
4366 /*
4367 * Attach to the specified VM.
4368 */
4369 if (RT_SUCCESS(rc) && pUVM)
4370 {
4371 rc = DBGFR3Attach(pUVM);
4372 if (RT_SUCCESS(rc))
4373 {
4374 pThis->Dbgc.pVM = pVM;
4375 pThis->Dbgc.pUVM = pUVM;
4376 pThis->Dbgc.idCpu = 0;
4377 }
4378 else
4379 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
4380 }
4381
4382 /*
4383 * Load plugins.
4384 */
4385 if (RT_SUCCESS(rc))
4386 {
4387 if (pVM)
4388 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
4389 dbgcEventInit(&pThis->Dbgc);
4390
4391 /*
4392 * Run the debugger main loop.
4393 */
4394 rc = dbgcKdRun(pThis);
4395 dbgcEventTerm(&pThis->Dbgc);
4396 }
4397
4398 /*
4399 * Cleanup console debugger session.
4400 */
4401 dbgcKdCtxDestroy(pThis);
4402 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
4403}
4404
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