VirtualBox

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

Last change on this file since 93470 was 93470, checked in by vboxsync, 3 years ago

DbgPlugInDiggers,VMM,Main: Refactored the diggers and related interfaces to work via the VMM function table. Removed non-working tstVBoxDbg (needs proper COM now). bugref:10072

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 160.5 KB
Line 
1/* $Id: DBGCRemoteKd.cpp 93470 2022-01-27 23:51:28Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Windows Kd Remote Stub.
4 */
5
6/*
7 * Copyright (C) 2020-2022 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 /** The DBGF breakpoint handle if active, NIL_DBGFBP if not active. */
1163 DBGFBP hDbgfBp;
1164 /** The linear address of the breakpoint if active. */
1165 RTGCPTR GCPtrBp;
1166 /** Access type of the breakpoint, see X86_DR7_RW_*. */
1167 uint8_t fAcc;
1168 /** Length flags of the breakpoint. */
1169 uint8_t fLen;
1170 /** Flag whether it is a local breakpoint. */
1171 bool fLocal;
1172 /** Flag whether it is a global breakpoint. */
1173 bool fGlobal;
1174 /** Flag whether the breakpoint has triggered since the last time of the reset. */
1175 bool fTriggered;
1176} KDCTXHWBP;
1177/** Pointer to an emulated hardware breakpoint. */
1178typedef KDCTXHWBP *PKDCTXHWBP;
1179/** Pointer to a const emulated hardware breakpoint. */
1180typedef const KDCTXHWBP *PCKDCTXHWBP;
1181
1182
1183/**
1184 * KD context data.
1185 */
1186typedef struct KDCTX
1187{
1188 /** Internal debugger console data. */
1189 DBGC Dbgc;
1190 /** Number of bytes received left for the current state. */
1191 size_t cbRecvLeft;
1192 /** Pointer where to write the next received data. */
1193 uint8_t *pbRecv;
1194 /** The current state when receiving a new packet. */
1195 KDRECVSTATE enmState;
1196 /** The timeout waiting for new data. */
1197 RTMSINTERVAL msRecvTimeout;
1198 /** Timestamp when we last received data from the remote end. */
1199 uint64_t tsRecvLast;
1200 /** Packet header being received. */
1201 union
1202 {
1203 KDPACKETHDR Fields;
1204 uint8_t ab[16];
1205 } PktHdr;
1206 /** The next packet ID to send. */
1207 uint32_t idPktNext;
1208 /** Offset into the body receive buffer. */
1209 size_t offBodyRecv;
1210 /** Body data. */
1211 uint8_t abBody[_4K];
1212 /** The trailer byte storage. */
1213 uint8_t bTrailer;
1214 /** Flag whether a breakin packet was received since the last time it was reset. */
1215 bool fBreakinRecv;
1216 /** Flag whether we entered the native VBox hypervisor through a bugcheck request. */
1217 bool fInVBoxDbg;
1218
1219 /** Emulated hardware breakpoint handling. */
1220 KDCTXHWBP aHwBp[4];
1221 /** Flag whether a single step completed since last time this was cleared. */
1222 bool fSingleStepped;
1223
1224 /** Pointer to the OS digger WinNt interface if a matching guest was detected. */
1225 PDBGFOSIWINNT pIfWinNt;
1226 /** Flag whether the detected guest is 32bit (false if 64bit). */
1227 bool f32Bit;
1228} KDCTX;
1229/** Pointer to the KD context data. */
1230typedef KDCTX *PKDCTX;
1231/** Pointer to const KD context data. */
1232typedef const KDCTX *PCKDCTX;
1233/** Pointer to a KD context data pointer. */
1234typedef PKDCTX *PPKDCTX;
1235
1236
1237/** Creates a possibly sign extended guest context pointer which is required for 32bit targets. */
1238#define KD_PTR_CREATE(a_pThis, a_GCPtr) ((a_pThis)->f32Bit && ((a_GCPtr) & RT_BIT_32(31)) ? (a_GCPtr) | UINT64_C(0xffffffff00000000) : (a_GCPtr))
1239/** Returns the value of a possibly sign extended guest context pointer received for 32bit targets. */
1240#define KD_PTR_GET(a_pThis, a_GCPtr) ((a_pThis)->f32Bit ? (a_GCPtr) & ~UINT64_C(0xffffffff00000000) : (a_GCPtr))
1241
1242
1243/*********************************************************************************************************************************
1244* Internal Functions *
1245*********************************************************************************************************************************/
1246static void dbgcKdCtxMsgSend(PKDCTX pThis, bool fWarning, const char *pszMsg);
1247
1248
1249#ifdef LOG_ENABLED
1250/**
1251 * Returns a human readable string of the given packet sub type.
1252 *
1253 * @returns Pointer to sub type string.
1254 * @param u16SubType The sub type to convert to a string.
1255 */
1256static const char *dbgcKdPktDumpSubTypeToStr(uint16_t u16SubType)
1257{
1258 switch (u16SubType)
1259 {
1260 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE32: return "StateChange32";
1261 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE: return "Manipulate";
1262 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO: return "DebugIo";
1263 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE: return "Ack";
1264 case KD_PACKET_HDR_SUB_TYPE_RESEND: return "Resend";
1265 case KD_PACKET_HDR_SUB_TYPE_RESET: return "Reset";
1266 case KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64: return "StateChange64";
1267 case KD_PACKET_HDR_SUB_TYPE_POLL_BREAKIN: return "PollBreakin";
1268 case KD_PACKET_HDR_SUB_TYPE_TRACE_IO: return "TraceIo";
1269 case KD_PACKET_HDR_SUB_TYPE_CONTROL_REQUEST: return "ControlRequest";
1270 case KD_PACKET_HDR_SUB_TYPE_FILE_IO: return "FileIo";
1271 default: break;
1272 }
1273
1274 return "<UNKNOWN>";
1275}
1276
1277
1278/**
1279 * Returns a human readable string of the given manipulate request ID.
1280 *
1281 * @returns nothing.
1282 * @param idReq Request ID (API number in KD speak).
1283 */
1284static const char *dbgcKdPktDumpManipulateReqToStr(uint32_t idReq)
1285{
1286 switch (idReq)
1287 {
1288 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM: return "ReadVirtMem";
1289 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM: return "WriteVirtMem";
1290 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT: return "GetContext";
1291 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT: return "SetContext";
1292 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT: return "WriteBkpt";
1293 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT: return "RestoreBkpt";
1294 case KD_PACKET_MANIPULATE_REQ_CONTINUE: return "Continue";
1295 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE: return "ReadCtrlSpace";
1296 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE: return "WriteCtrlSpace";
1297 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE: return "ReadIoSpace";
1298 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE: return "WriteIoSpace";
1299 case KD_PACKET_MANIPULATE_REQ_REBOOT: return "Reboot";
1300 case KD_PACKET_MANIPULATE_REQ_CONTINUE2: return "Continue2";
1301 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM: return "ReadPhysMem";
1302 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM: return "WritePhysMem";
1303 case KD_PACKET_MANIPULATE_REQ_QUERY_SPEC_CALLS: return "QuerySpecCalls";
1304 case KD_PACKET_MANIPULATE_REQ_SET_SPEC_CALLS: return "SetSpecCalls";
1305 case KD_PACKET_MANIPULATE_REQ_CLEAR_SPEC_CALLS: return "ClrSpecCalls";
1306 case KD_PACKET_MANIPULATE_REQ_SET_INTERNAL_BKPT: return "SetIntBkpt";
1307 case KD_PACKET_MANIPULATE_REQ_GET_INTERNAL_BKPT: return "GetIntBkpt";
1308 case KD_PACKET_MANIPULATE_REQ_READ_IO_SPACE_EX: return "ReadIoSpaceEx";
1309 case KD_PACKET_MANIPULATE_REQ_WRITE_IO_SPACE_EX: return "WriteIoSpaceEx";
1310 case KD_PACKET_MANIPULATE_REQ_GET_VERSION: return "GetVersion";
1311 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT: return "ClrAllIntBkpt";
1312 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX: return "GetContextEx";
1313 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY: return "QueryMemory";
1314 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK: return "CauseBugCheck";
1315 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR: return "SwitchProcessor";
1316 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY: return "SearchMemory";
1317 default: break;
1318 }
1319
1320 return "<UNKNOWN>";
1321}
1322
1323
1324/**
1325 * Dumps the content of a manipulate packet.
1326 *
1327 * @returns nothing.
1328 * @param pSgBuf S/G buffer containing the manipulate packet payload.
1329 */
1330static void dbgcKdPktDumpManipulate(PRTSGBUF pSgBuf)
1331{
1332 KDPACKETMANIPULATEHDR Hdr;
1333 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, &Hdr, sizeof(Hdr));
1334
1335 if (cbCopied == sizeof(Hdr))
1336 {
1337 const char *pszReq = dbgcKdPktDumpManipulateReqToStr(Hdr.idReq);
1338
1339 Log3((" MANIPULATE(%#x (%s), %#x, %u, %#x)\n",
1340 Hdr.idReq, pszReq, Hdr.u16CpuLvl, Hdr.idCpu, Hdr.u32NtStatus));
1341
1342 switch (Hdr.idReq)
1343 {
1344 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
1345 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
1346 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
1347 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
1348 {
1349 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
1350 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferMem64, sizeof(XferMem64));
1351 if (cbCopied == sizeof(XferMem64))
1352 {
1353 Log3((" u64PtrTarget: %RX64\n"
1354 " cbXferReq: %RX32\n"
1355 " cbXfered: %RX32\n",
1356 XferMem64.u64PtrTarget, XferMem64.cbXferReq, XferMem64.cbXfered));
1357 }
1358 else
1359 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferMem64), cbCopied));
1360 break;
1361 }
1362 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
1363 {
1364 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
1365 cbCopied = RTSgBufCopyToBuf(pSgBuf, &RestoreBkpt64, sizeof(RestoreBkpt64));
1366 if (cbCopied == sizeof(RestoreBkpt64))
1367 Log3((" u32HndBkpt: %RX32\n", RestoreBkpt64.u32HndBkpt));
1368 else
1369 Log3((" Payload to small, expected %u, got %zu\n", sizeof(RestoreBkpt64), cbCopied));
1370 break;
1371 }
1372 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
1373 {
1374 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
1375 cbCopied = RTSgBufCopyToBuf(pSgBuf, &WriteBkpt64, sizeof(WriteBkpt64));
1376 if (cbCopied == sizeof(WriteBkpt64))
1377 Log3((" u64PtrBkpt: %RX64\n"
1378 " u32HndBkpt: %RX32\n",
1379 WriteBkpt64.u64PtrBkpt, WriteBkpt64.u32HndBkpt));
1380 else
1381 Log3((" Payload to small, expected %u, got %zu\n", sizeof(WriteBkpt64), cbCopied));
1382 break;
1383 }
1384 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
1385 {
1386 KDPACKETMANIPULATE_CONTINUE Continue;
1387 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1388 if (cbCopied == sizeof(Continue))
1389 Log3((" u32NtContSts: %RX32\n", Continue.u32NtContSts));
1390 else
1391 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1392 break;
1393 }
1394 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
1395 {
1396 KDPACKETMANIPULATE_CONTINUE2 Continue;
1397 cbCopied = RTSgBufCopyToBuf(pSgBuf, &Continue, sizeof(Continue));
1398 if (cbCopied == sizeof(Continue))
1399 Log3((" u32NtContSts: %RX32\n"
1400 " fTrace: %RX32\n",
1401 Continue.u32NtContSts, Continue.fTrace));
1402 else
1403 Log3((" Payload to small, expected %u, got %zu\n", sizeof(Continue), cbCopied));
1404 break;
1405 }
1406 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
1407 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
1408 {
1409 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
1410 cbCopied = RTSgBufCopyToBuf(pSgBuf, &XferCtrlSpace64, sizeof(XferCtrlSpace64));
1411 if (cbCopied == sizeof(XferCtrlSpace64))
1412 {
1413 Log3((" u64IdXfer: %RX64\n"
1414 " cbXferReq: %RX32\n"
1415 " cbXfered: %RX32\n",
1416 XferCtrlSpace64.u64IdXfer, XferCtrlSpace64.cbXferReq, XferCtrlSpace64.cbXfered));
1417 }
1418 else
1419 Log3((" Payload to small, expected %u, got %zu\n", sizeof(XferCtrlSpace64), cbCopied));
1420 break;
1421 }
1422 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
1423 {
1424 KDPACKETMANIPULATE_CONTEXTEX GetContextEx;
1425 cbCopied = RTSgBufCopyToBuf(pSgBuf, &GetContextEx, sizeof(GetContextEx));
1426 if (cbCopied == sizeof(GetContextEx))
1427 {
1428 Log3((" offStart: %RX32\n"
1429 " cbXferReq: %RX32\n"
1430 " cbXfered: %RX32\n",
1431 GetContextEx.offStart, GetContextEx.cbXfer, GetContextEx.cbXfered));
1432 }
1433 else
1434 Log3((" Payload to small, expected %u, got %zu\n", sizeof(GetContextEx), cbCopied));
1435 break;
1436 }
1437 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
1438 {
1439 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
1440 cbCopied = RTSgBufCopyToBuf(pSgBuf, &QueryMemory, sizeof(QueryMemory));
1441 if (cbCopied == sizeof(QueryMemory))
1442 {
1443 Log3((" u64GCPtr: %RX64\n"
1444 " u32AddrSpace: %RX32\n"
1445 " u32Flags: %RX32\n",
1446 QueryMemory.u64GCPtr, QueryMemory.u32AddrSpace, QueryMemory.u32Flags));
1447 }
1448 else
1449 Log3((" Payload to small, expected %u, got %zu\n", sizeof(QueryMemory), cbCopied));
1450 break;
1451 }
1452 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
1453 {
1454 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
1455 cbCopied = RTSgBufCopyToBuf(pSgBuf, &SearchMemory, sizeof(SearchMemory));
1456 if (cbCopied == sizeof(SearchMemory))
1457 {
1458 Log3((" u64GCPtr: %RX64\n"
1459 " cbSearch: %RX64\n"
1460 " cbPattern: %RX32\n",
1461 SearchMemory.u64GCPtr, SearchMemory.cbSearch, SearchMemory.cbPattern));
1462 }
1463 else
1464 Log3((" Payload to small, expected %u, got %zu\n", sizeof(SearchMemory), cbCopied));
1465 break;
1466 }
1467 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR:
1468 default:
1469 break;
1470 }
1471 }
1472 else
1473 Log3((" MANIPULATE(Header too small, expected %u, got %zu)\n", sizeof(Hdr), cbCopied));
1474}
1475
1476
1477/**
1478 * Dumps the received packet to the debug log.
1479 *
1480 * @returns VBox status code.
1481 * @param pPktHdr The packet header to dump.
1482 * @param fRx Flag whether the packet was received (false indicates an outgoing packet).
1483 */
1484static void dbgcKdPktDump(PCKDPACKETHDR pPktHdr, PCRTSGSEG paSegs, uint32_t cSegs, bool fRx)
1485{
1486 RTSGBUF SgBuf;
1487
1488 RTSgBufInit(&SgBuf, paSegs, cSegs);
1489
1490 Log3(("%s KDPKTHDR(%#x, %#x (%s), %u, %#x, %#x)\n",
1491 fRx ? "=>" : "<=",
1492 pPktHdr->u32Signature, pPktHdr->u16SubType, dbgcKdPktDumpSubTypeToStr(pPktHdr->u16SubType),
1493 pPktHdr->cbBody, pPktHdr->idPacket, pPktHdr->u32ChkSum));
1494 switch (pPktHdr->u16SubType)
1495 {
1496 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
1497 dbgcKdPktDumpManipulate(&SgBuf);
1498 break;
1499 default:
1500 break;
1501 }
1502}
1503#endif
1504
1505
1506/**
1507 * Resets the emulated hardware breakpoint state to a state similar after a reboot.
1508 *
1509 * @returns nothing.
1510 * @param pThis The KD context.
1511 */
1512static void dbgcKdCtxHwBpReset(PKDCTX pThis)
1513{
1514 pThis->fSingleStepped = false;
1515
1516 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1517 {
1518 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1519
1520 if (pBp->hDbgfBp != NIL_DBGFBP)
1521 {
1522 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->hDbgfBp);
1523 AssertRC(rc);
1524 }
1525
1526 pBp->hDbgfBp = NIL_DBGFBP;
1527 pBp->GCPtrBp = 0;
1528 pBp->fAcc = 0;
1529 pBp->fLen = 0;
1530 pBp->fLocal = false;
1531 pBp->fGlobal = false;
1532 pBp->fTriggered = false;
1533 }
1534}
1535
1536
1537/**
1538 * Updates the given breakpoint with the given properties.
1539 *
1540 * @returns VBox status code.
1541 * @param pThis The KD context.
1542 * @param pBp The breakpoint to update.
1543 * @param fAcc Access mode.
1544 * @param fLen Access length.
1545 * @param fGlobal Global breakpoint.
1546 * @param fLocal Local breakpoint.
1547 * @param GCPtrBp Linear address of the breakpoint.
1548 */
1549static int dbgcKdCtxHwBpUpdate(PKDCTX pThis, PKDCTXHWBP pBp, uint8_t fAcc, uint8_t fLen,
1550 bool fGlobal, bool fLocal, RTGCPTR GCPtrBp)
1551{
1552 int rc = VINF_SUCCESS;
1553
1554 /* Did anything actually change?. */
1555 if ( pBp->fAcc != fAcc
1556 || pBp->fLen != fLen
1557 || pBp->fGlobal != fGlobal
1558 || pBp->fLocal != fLocal
1559 || pBp->GCPtrBp != GCPtrBp)
1560 {
1561 /* Clear the old breakpoint. */
1562 if (pBp->hDbgfBp != NIL_DBGFBP)
1563 {
1564 rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pBp->hDbgfBp);
1565 AssertRC(rc);
1566 pBp->hDbgfBp = NIL_DBGFBP;
1567 }
1568
1569 pBp->fAcc = fAcc;
1570 pBp->fLen = fLen;
1571 pBp->fGlobal = fGlobal;
1572 pBp->fLocal = fLocal;
1573 pBp->GCPtrBp = GCPtrBp;
1574 if (pBp->fGlobal || pBp->fLocal)
1575 {
1576 DBGFADDRESS AddrBp;
1577 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrBp, GCPtrBp);
1578
1579 uint8_t cb = 0;
1580 switch (pBp->fLen)
1581 {
1582 case X86_DR7_LEN_BYTE:
1583 cb = 1;
1584 break;
1585 case X86_DR7_LEN_WORD:
1586 cb = 2;
1587 break;
1588 case X86_DR7_LEN_DWORD:
1589 cb = 4;
1590 break;
1591 case X86_DR7_LEN_QWORD:
1592 cb = 8;
1593 break;
1594 default:
1595 AssertFailed();
1596 return VERR_NET_PROTOCOL_ERROR;
1597 }
1598
1599 rc = DBGFR3BpSetReg(pThis->Dbgc.pUVM, &AddrBp, 0 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/,
1600 pBp->fAcc, cb, &pBp->hDbgfBp);
1601 }
1602 }
1603
1604 return rc;
1605}
1606
1607
1608/**
1609 * Updates emulated hardware breakpoints based on the written DR7 value.
1610 *
1611 * @returns VBox status code.
1612 * @param pThis The KD context.
1613 * @param uDr7 The DR7 value which is written.
1614 */
1615static int dbgcKdCtxHwBpDr7Update(PKDCTX pThis, uint32_t uDr7)
1616{
1617 int rc = VINF_SUCCESS;
1618
1619 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
1620 {
1621 PKDCTXHWBP pBp = &pThis->aHwBp[i];
1622 uint8_t fAcc = X86_DR7_GET_RW(uDr7, i);
1623 uint8_t fLen = X86_DR7_GET_LEN(uDr7, i);
1624 bool fGlobal = (uDr7 & RT_BIT_32(1 + i * 2)) ? true : false;
1625 bool fLocal = (uDr7 & RT_BIT_32(i * 2)) ? true : false;
1626
1627 int rc2 = dbgcKdCtxHwBpUpdate(pThis, pBp, fAcc, fLen, fGlobal, fLocal, pThis->aHwBp[i].GCPtrBp);
1628 if ( RT_FAILURE(rc2)
1629 && RT_SUCCESS(rc))
1630 rc = rc2;
1631 }
1632
1633 return rc;
1634}
1635
1636
1637/**
1638 * Updates the linear guest pointer for the given hardware breakpoint.
1639 *
1640 * @returns VBox status code.
1641 * @param pThis The KD context.
1642 * @param pBp The breakpoint to update.
1643 * @param GCPtrBp The linear breakpoint address.
1644 */
1645DECLINLINE(int) dbgcKdCtxHwBpGCPtrUpdate(PKDCTX pThis, PKDCTXHWBP pBp, RTGCPTR GCPtrBp)
1646{
1647 return dbgcKdCtxHwBpUpdate(pThis, pBp, pBp->fAcc, pBp->fLen, pBp->fGlobal, pBp->fLocal, GCPtrBp);
1648}
1649
1650
1651/**
1652 * Calculates the DR7 value based on the emulated hardware breakpoint state and returns it.
1653 *
1654 * @returns The emulated DR7 value.
1655 * @param pThis The KD context.
1656 */
1657static uint32_t dbgcKdCtxHwBpDr7Get(PKDCTX pThis)
1658{
1659 uint32_t uDr7 = 0;
1660
1661 uDr7 |= X86_DR7_RW(0, pThis->aHwBp[0].fAcc);
1662 uDr7 |= X86_DR7_RW(1, pThis->aHwBp[1].fAcc);
1663 uDr7 |= X86_DR7_RW(2, pThis->aHwBp[2].fAcc);
1664 uDr7 |= X86_DR7_RW(3, pThis->aHwBp[3].fAcc);
1665
1666 uDr7 |= X86_DR7_LEN(0, pThis->aHwBp[0].fLen);
1667 uDr7 |= X86_DR7_LEN(1, pThis->aHwBp[1].fLen);
1668 uDr7 |= X86_DR7_LEN(2, pThis->aHwBp[2].fLen);
1669 uDr7 |= X86_DR7_LEN(3, pThis->aHwBp[3].fLen);
1670
1671 uDr7 |= pThis->aHwBp[0].fGlobal ? X86_DR7_G(0) : 0;
1672 uDr7 |= pThis->aHwBp[1].fGlobal ? X86_DR7_G(1) : 0;
1673 uDr7 |= pThis->aHwBp[2].fGlobal ? X86_DR7_G(2) : 0;
1674 uDr7 |= pThis->aHwBp[3].fGlobal ? X86_DR7_G(3) : 0;
1675
1676 uDr7 |= pThis->aHwBp[0].fLocal ? X86_DR7_L(0) : 0;
1677 uDr7 |= pThis->aHwBp[1].fLocal ? X86_DR7_L(1) : 0;
1678 uDr7 |= pThis->aHwBp[2].fLocal ? X86_DR7_L(2) : 0;
1679 uDr7 |= pThis->aHwBp[3].fLocal ? X86_DR7_L(3) : 0;
1680
1681 return uDr7;
1682}
1683
1684
1685/**
1686 * Updates emulated hardware breakpoints based on the written DR6 value.
1687 *
1688 * @returns nothing.
1689 * @param pThis The KD context.
1690 * @param uDr6 The DR7 value which is written.
1691 */
1692static void dbgcKdCtxHwBpDr6Update(PKDCTX pThis, uint32_t uDr6)
1693{
1694 pThis->aHwBp[0].fTriggered = (uDr6 & X86_DR6_B0) ? true : false;
1695 pThis->aHwBp[1].fTriggered = (uDr6 & X86_DR6_B1) ? true : false;
1696 pThis->aHwBp[2].fTriggered = (uDr6 & X86_DR6_B2) ? true : false;
1697 pThis->aHwBp[3].fTriggered = (uDr6 & X86_DR6_B3) ? true : false;
1698 pThis->fSingleStepped = (uDr6 & X86_DR6_BS) ? true : false;
1699}
1700
1701
1702/**
1703 * Calculates the DR6 value based on the emulated hardware breakpoint state and returns it.
1704 *
1705 * @returns The emulated DR6 value.
1706 * @param pThis The KD context.
1707 */
1708static uint32_t dbgcKdCtxHwBpDr6Get(PKDCTX pThis)
1709{
1710 uint32_t uDr6 = 0;
1711
1712 if (pThis->aHwBp[0].fTriggered)
1713 uDr6 |= X86_DR6_B0;
1714 if (pThis->aHwBp[1].fTriggered)
1715 uDr6 |= X86_DR6_B1;
1716 if (pThis->aHwBp[2].fTriggered)
1717 uDr6 |= X86_DR6_B2;
1718 if (pThis->aHwBp[3].fTriggered)
1719 uDr6 |= X86_DR6_B3;
1720 if (pThis->fSingleStepped)
1721 uDr6 |= X86_DR6_BS;
1722
1723 return uDr6;
1724}
1725
1726
1727/**
1728 * Wrapper for the I/O interface write callback.
1729 *
1730 * @returns Status code.
1731 * @param pThis The KD context.
1732 * @param pvPkt The packet data to send.
1733 * @param cbPkt Size of the packet in bytes.
1734 */
1735DECLINLINE(int) dbgcKdCtxWrite(PKDCTX pThis, const void *pvPkt, size_t cbPkt)
1736{
1737 return pThis->Dbgc.pIo->pfnWrite(pThis->Dbgc.pIo, pvPkt, cbPkt, NULL /*pcbWritten*/);
1738}
1739
1740
1741/**
1742 * Fills in the given 64bit NT context structure with the requested values.
1743 *
1744 * @returns VBox status code.
1745 * @param pThis The KD context.
1746 * @param idCpu The CPU to query the context for.
1747 * @param pNtCtx The NT context structure to fill in.
1748 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1749 */
1750static int dbgcKdCtxQueryNtCtx64(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1751{
1752 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1753
1754 pNtCtx->fContext = NTCONTEXT_F_AMD64;
1755 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pNtCtx->u32RegMxCsr);
1756
1757 if ( RT_SUCCESS(rc)
1758 && fCtxFlags & NTCONTEXT_F_CONTROL)
1759 {
1760 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u16SegCs);
1761 if (RT_SUCCESS(rc))
1762 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u16SegSs);
1763 if (RT_SUCCESS(rc))
1764 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RIP, &pNtCtx->u64RegRip);
1765 if (RT_SUCCESS(rc))
1766 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSP, &pNtCtx->u64RegRsp);
1767 if (RT_SUCCESS(rc))
1768 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBP, &pNtCtx->u64RegRbp);
1769 if (RT_SUCCESS(rc))
1770 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1771 if (RT_SUCCESS(rc))
1772 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1773 }
1774
1775 if ( RT_SUCCESS(rc)
1776 && fCtxFlags & NTCONTEXT_F_INTEGER)
1777 {
1778 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RAX, &pNtCtx->u64RegRax);
1779 if (RT_SUCCESS(rc))
1780 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RCX, &pNtCtx->u64RegRcx);
1781 if (RT_SUCCESS(rc))
1782 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDX, &pNtCtx->u64RegRdx);
1783 if (RT_SUCCESS(rc))
1784 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RBX, &pNtCtx->u64RegRbx);
1785 if (RT_SUCCESS(rc))
1786 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RSI, &pNtCtx->u64RegRsi);
1787 if (RT_SUCCESS(rc))
1788 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_RDI, &pNtCtx->u64RegRdi);
1789 if (RT_SUCCESS(rc))
1790 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R8, &pNtCtx->u64RegR8);
1791 if (RT_SUCCESS(rc))
1792 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R9, &pNtCtx->u64RegR9);
1793 if (RT_SUCCESS(rc))
1794 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R10, &pNtCtx->u64RegR10);
1795 if (RT_SUCCESS(rc))
1796 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R11, &pNtCtx->u64RegR11);
1797 if (RT_SUCCESS(rc))
1798 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R12, &pNtCtx->u64RegR12);
1799 if (RT_SUCCESS(rc))
1800 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R13, &pNtCtx->u64RegR13);
1801 if (RT_SUCCESS(rc))
1802 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R14, &pNtCtx->u64RegR14);
1803 if (RT_SUCCESS(rc))
1804 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_R15, &pNtCtx->u64RegR15);
1805 if (RT_SUCCESS(rc))
1806 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1807 }
1808
1809 if ( RT_SUCCESS(rc)
1810 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1811 {
1812 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u16SegDs);
1813 if (RT_SUCCESS(rc))
1814 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u16SegEs);
1815 if (RT_SUCCESS(rc))
1816 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u16SegFs);
1817 if (RT_SUCCESS(rc))
1818 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u16SegGs);
1819 if (RT_SUCCESS(rc))
1820 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1821 }
1822
1823 if ( RT_SUCCESS(rc)
1824 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1825 {
1826 /** @todo NTCONTEXT_F_FLOATING_POINT. */
1827 }
1828
1829 if ( RT_SUCCESS(rc)
1830 && fCtxFlags & NTCONTEXT_F_DEBUG)
1831 {
1832 /** @todo NTCONTEXT_F_DEBUG */
1833 }
1834
1835 return rc;
1836}
1837
1838
1839/**
1840 * Fills in the given 32bit NT context structure with the requested values.
1841 *
1842 * @returns VBox status code.
1843 * @param pThis The KD context.
1844 * @param idCpu The CPU to query the context for.
1845 * @param pNtCtx The NT context structure to fill in.
1846 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
1847 */
1848static int dbgcKdCtxQueryNtCtx32(PKDCTX pThis, VMCPUID idCpu, PNTCONTEXT32 pNtCtx, uint32_t fCtxFlags)
1849{
1850 RT_BZERO(pNtCtx, sizeof(*pNtCtx));
1851
1852 pNtCtx->fContext = NTCONTEXT_F_X86;
1853
1854 int rc = VINF_SUCCESS;
1855 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1856 {
1857 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CS, &pNtCtx->u32SegCs);
1858 if (RT_SUCCESS(rc))
1859 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_SS, &pNtCtx->u32SegSs);
1860 if (RT_SUCCESS(rc))
1861 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EIP, &pNtCtx->u32RegEip);
1862 if (RT_SUCCESS(rc))
1863 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESP, &pNtCtx->u32RegEsp);
1864 if (RT_SUCCESS(rc))
1865 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBP, &pNtCtx->u32RegEbp);
1866 if (RT_SUCCESS(rc))
1867 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EFLAGS, &pNtCtx->u32RegEflags);
1868 if (RT_SUCCESS(rc))
1869 pNtCtx->fContext |= NTCONTEXT_F_CONTROL;
1870 }
1871
1872 if ( RT_SUCCESS(rc)
1873 && fCtxFlags & NTCONTEXT_F_INTEGER)
1874 {
1875 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EAX, &pNtCtx->u32RegEax);
1876 if (RT_SUCCESS(rc))
1877 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ECX, &pNtCtx->u32RegEcx);
1878 if (RT_SUCCESS(rc))
1879 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDX, &pNtCtx->u32RegEdx);
1880 if (RT_SUCCESS(rc))
1881 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EBX, &pNtCtx->u32RegEbx);
1882 if (RT_SUCCESS(rc))
1883 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ESI, &pNtCtx->u32RegEsi);
1884 if (RT_SUCCESS(rc))
1885 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_EDI, &pNtCtx->u32RegEdi);
1886 if (RT_SUCCESS(rc))
1887 pNtCtx->fContext |= NTCONTEXT_F_INTEGER;
1888 }
1889
1890 if ( RT_SUCCESS(rc)
1891 && fCtxFlags & NTCONTEXT_F_SEGMENTS)
1892 {
1893 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DS, &pNtCtx->u32SegDs);
1894 if (RT_SUCCESS(rc))
1895 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_ES, &pNtCtx->u32SegEs);
1896 if (RT_SUCCESS(rc))
1897 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_FS, &pNtCtx->u32SegFs);
1898 if (RT_SUCCESS(rc))
1899 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GS, &pNtCtx->u32SegGs);
1900 if (RT_SUCCESS(rc))
1901 pNtCtx->fContext |= NTCONTEXT_F_SEGMENTS;
1902 }
1903
1904 if ( RT_SUCCESS(rc)
1905 && fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
1906 {
1907 /** @todo NTCONTEXT_F_FLOATING_POINT. */
1908 }
1909
1910 if ( RT_SUCCESS(rc)
1911 && fCtxFlags & NTCONTEXT_F_DEBUG)
1912 {
1913 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR0, &pNtCtx->u32RegDr0);
1914 if (RT_SUCCESS(rc))
1915 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR1, &pNtCtx->u32RegDr1);
1916 if (RT_SUCCESS(rc))
1917 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR3, &pNtCtx->u32RegDr3);
1918 if (RT_SUCCESS(rc))
1919 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR6, &pNtCtx->u32RegDr6);
1920 if (RT_SUCCESS(rc))
1921 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_DR7, &pNtCtx->u32RegDr7);
1922 if (RT_SUCCESS(rc))
1923 pNtCtx->fContext |= NTCONTEXT_F_DEBUG;
1924 }
1925
1926 return rc;
1927}
1928
1929
1930#define KD_REG_INIT(a_pszName, a_enmType, a_ValMember, a_Val) \
1931 do \
1932 { \
1933 aRegsSet[idxReg].pszName = a_pszName; \
1934 aRegsSet[idxReg].enmType = a_enmType; \
1935 aRegsSet[idxReg].Val.a_ValMember = a_Val; \
1936 idxReg++; \
1937 } while (0)
1938#define KD_REG_INIT_DTR(a_pszName, a_Base, a_Limit) \
1939 do \
1940 { \
1941 aRegsSet[idxReg].pszName = a_pszName; \
1942 aRegsSet[idxReg].enmType = DBGFREGVALTYPE_DTR; \
1943 aRegsSet[idxReg].Val.dtr.u64Base = a_Base; \
1944 aRegsSet[idxReg].Val.dtr.u32Limit = a_Limit; \
1945 idxReg++; \
1946 } while (0)
1947#define KD_REG_INIT_U16(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U16, u16, a_Val)
1948#define KD_REG_INIT_U32(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U32, u32, a_Val)
1949#define KD_REG_INIT_U64(a_pszName, a_Val) KD_REG_INIT(a_pszName, DBGFREGVALTYPE_U64, u64, a_Val)
1950
1951
1952/**
1953 * Writes the indicated values from the given context structure to the guests register set.
1954 *
1955 * @returns VBox status code.
1956 * @param pThis The KD context.
1957 * @param idCpu The CPU to query the context for.
1958 * @param pNtCtx The NT context structure to set.
1959 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to set.
1960 */
1961static int dbgcKdCtxSetNtCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTCONTEXT64 pNtCtx, uint32_t fCtxFlags)
1962{
1963 uint32_t idxReg = 0;
1964 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
1965
1966 KD_REG_INIT_U32("mxcsr", pNtCtx->u32RegMxCsr);
1967
1968 if (fCtxFlags & NTCONTEXT_F_CONTROL)
1969 {
1970#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
1971 KD_REG_INIT_U16("cs", pNtCtx->u16SegCs);
1972 KD_REG_INIT_U16("ss", pNtCtx->u16SegSs);
1973#endif
1974 KD_REG_INIT_U64("rip", pNtCtx->u64RegRip);
1975 KD_REG_INIT_U64("rsp", pNtCtx->u64RegRsp);
1976 KD_REG_INIT_U64("rbp", pNtCtx->u64RegRbp);
1977 KD_REG_INIT_U32("rflags", pNtCtx->u32RegEflags);
1978 }
1979
1980 if (fCtxFlags & NTCONTEXT_F_INTEGER)
1981 {
1982 KD_REG_INIT_U64("rax", pNtCtx->u64RegRax);
1983 KD_REG_INIT_U64("rcx", pNtCtx->u64RegRcx);
1984 KD_REG_INIT_U64("rdx", pNtCtx->u64RegRdx);
1985 KD_REG_INIT_U64("rbx", pNtCtx->u64RegRbx);
1986 KD_REG_INIT_U64("rsi", pNtCtx->u64RegRsi);
1987 KD_REG_INIT_U64("rdi", pNtCtx->u64RegRdi);
1988 KD_REG_INIT_U64("r8", pNtCtx->u64RegR8);
1989 KD_REG_INIT_U64("r9", pNtCtx->u64RegR9);
1990 KD_REG_INIT_U64("r10", pNtCtx->u64RegR10);
1991 KD_REG_INIT_U64("r11", pNtCtx->u64RegR11);
1992 KD_REG_INIT_U64("r12", pNtCtx->u64RegR12);
1993 KD_REG_INIT_U64("r13", pNtCtx->u64RegR13);
1994 KD_REG_INIT_U64("r14", pNtCtx->u64RegR14);
1995 KD_REG_INIT_U64("r15", pNtCtx->u64RegR15);
1996 }
1997
1998 if (fCtxFlags & NTCONTEXT_F_SEGMENTS)
1999 {
2000#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2001 KD_REG_INIT_U16("ds", pNtCtx->u16SegDs);
2002 KD_REG_INIT_U16("es", pNtCtx->u16SegEs);
2003 KD_REG_INIT_U16("fs", pNtCtx->u16SegFs);
2004 KD_REG_INIT_U16("gs", pNtCtx->u16SegGs);
2005#endif
2006 }
2007
2008 if (fCtxFlags & NTCONTEXT_F_FLOATING_POINT)
2009 {
2010 /** @todo NTCONTEXT_F_FLOATING_POINT. */
2011 }
2012
2013 if (fCtxFlags & NTCONTEXT_F_DEBUG)
2014 dbgcKdCtxMsgSend(pThis, true /*fWarning*/, "Setting local DR registers does not work!");
2015
2016 return DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2017}
2018
2019
2020/**
2021 * Fills in the given 64bit NT kernel context structure with the requested values.
2022 *
2023 * @returns VBox status code.
2024 * @param pThis The KD context.
2025 * @param idCpu The CPU to query the context for.
2026 * @param pKNtCtx The NT context structure to fill in.
2027 * @param fCtxFlags Combination of NTCONTEXT_F_XXX determining what to fill in.
2028 */
2029static int dbgcKdCtxQueryNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT64 pKNtCtx, uint32_t fCtxFlags)
2030{
2031 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2032
2033 int rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u64RegCr0);
2034 if (RT_SUCCESS(rc))
2035 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u64RegCr2);
2036 if (RT_SUCCESS(rc))
2037 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u64RegCr3);
2038 if (RT_SUCCESS(rc))
2039 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u64RegCr4);
2040 if (RT_SUCCESS(rc))
2041 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR8, &pKNtCtx->u64RegCr8);
2042 if (RT_SUCCESS(rc))
2043 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2044 if (RT_SUCCESS(rc))
2045 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u64PtrBase);
2046 if (RT_SUCCESS(rc))
2047 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2048 if (RT_SUCCESS(rc))
2049 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u64PtrBase);
2050 if (RT_SUCCESS(rc))
2051 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2052 if (RT_SUCCESS(rc))
2053 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2054 if (RT_SUCCESS(rc))
2055 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_MXCSR, &pKNtCtx->u32RegMxCsr);
2056
2057 if (RT_SUCCESS(rc))
2058 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_GS_BASE, &pKNtCtx->u64MsrGsBase);
2059 if (RT_SUCCESS(rc))
2060 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_KERNEL_GS_BASE, &pKNtCtx->u64MsrKernelGsBase);
2061 if (RT_SUCCESS(rc))
2062 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K6_STAR, &pKNtCtx->u64MsrStar);
2063 if (RT_SUCCESS(rc))
2064 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_LSTAR, &pKNtCtx->u64MsrLstar);
2065 if (RT_SUCCESS(rc))
2066 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_CSTAR, &pKNtCtx->u64MsrCstar);
2067 if (RT_SUCCESS(rc))
2068 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, idCpu, DBGFREG_MSR_K8_SF_MASK, &pKNtCtx->u64MsrSfMask);
2069 /** @todo XCR0 */
2070
2071 /* Get the emulated DR register state. */
2072 pKNtCtx->u64RegDr0 = pThis->aHwBp[0].GCPtrBp;
2073 pKNtCtx->u64RegDr1 = pThis->aHwBp[1].GCPtrBp;
2074 pKNtCtx->u64RegDr2 = pThis->aHwBp[2].GCPtrBp;
2075 pKNtCtx->u64RegDr3 = pThis->aHwBp[3].GCPtrBp;
2076 pKNtCtx->u64RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2077 pKNtCtx->u64RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2078
2079 if (RT_SUCCESS(rc))
2080 rc = dbgcKdCtxQueryNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, fCtxFlags);
2081
2082 return rc;
2083}
2084
2085
2086/**
2087 * Fills in the given 32bit NT kernel context structure with the requested values.
2088 *
2089 * @returns VBox status code.
2090 * @param pThis The KD context.
2091 * @param idCpu The CPU to query the context for.
2092 * @param pKNtCtx The NT context structure to fill in.
2093 */
2094static int dbgcKdCtxQueryNtKCtx32(PKDCTX pThis, VMCPUID idCpu, PNTKCONTEXT32 pKNtCtx)
2095{
2096 RT_BZERO(pKNtCtx, sizeof(*pKNtCtx));
2097
2098 int rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR0, &pKNtCtx->u32RegCr0);
2099 if (RT_SUCCESS(rc))
2100 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR2, &pKNtCtx->u32RegCr2);
2101 if (RT_SUCCESS(rc))
2102 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR3, &pKNtCtx->u32RegCr3);
2103 if (RT_SUCCESS(rc))
2104 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_CR4, &pKNtCtx->u32RegCr4);
2105
2106 if (RT_SUCCESS(rc))
2107 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_LIMIT, &pKNtCtx->Gdtr.u16Limit);
2108 if (RT_SUCCESS(rc))
2109 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_GDTR_BASE, &pKNtCtx->Gdtr.u32PtrBase);
2110 if (RT_SUCCESS(rc))
2111 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_LIMIT, &pKNtCtx->Idtr.u16Limit);
2112 if (RT_SUCCESS(rc))
2113 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, idCpu, DBGFREG_IDTR_BASE, &pKNtCtx->Idtr.u32PtrBase);
2114 if (RT_SUCCESS(rc))
2115 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_TR, &pKNtCtx->u16RegTr);
2116 if (RT_SUCCESS(rc))
2117 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, idCpu, DBGFREG_LDTR, &pKNtCtx->u16RegLdtr);
2118
2119 /* Get the emulated DR register state. */
2120 pKNtCtx->u32RegDr0 = (uint32_t)pThis->aHwBp[0].GCPtrBp;
2121 pKNtCtx->u32RegDr1 = (uint32_t)pThis->aHwBp[1].GCPtrBp;
2122 pKNtCtx->u32RegDr2 = (uint32_t)pThis->aHwBp[2].GCPtrBp;
2123 pKNtCtx->u32RegDr3 = (uint32_t)pThis->aHwBp[3].GCPtrBp;
2124 pKNtCtx->u32RegDr6 = dbgcKdCtxHwBpDr6Get(pThis);
2125 pKNtCtx->u32RegDr7 = dbgcKdCtxHwBpDr7Get(pThis);
2126
2127 return rc;
2128}
2129
2130
2131/**
2132 * Fills in the given 64bit NT kernel context structure with the requested values.
2133 *
2134 * @returns VBox status code.
2135 * @param pThis The KD context.
2136 * @param idCpu The CPU to query the context for.
2137 * @param pKNtCtx The NT context structure to fill in.
2138 * @param cbSet How many bytes of the context are valid.
2139 */
2140static int dbgcKdCtxSetNtKCtx64(PKDCTX pThis, VMCPUID idCpu, PCNTKCONTEXT64 pKNtCtx, size_t cbSet)
2141{
2142 AssertReturn(cbSet >= RT_UOFFSETOF(NTKCONTEXT64, Ctx), VERR_INVALID_PARAMETER);
2143
2144 uint32_t idxReg = 0;
2145 DBGFREGENTRYNM aRegsSet[64]; /** @todo Verify that this is enough when fully implemented. */
2146
2147 KD_REG_INIT_U64("cr0", pKNtCtx->u64RegCr0);
2148 KD_REG_INIT_U64("cr2", pKNtCtx->u64RegCr2);
2149 KD_REG_INIT_U64("cr3", pKNtCtx->u64RegCr3);
2150 KD_REG_INIT_U64("cr4", pKNtCtx->u64RegCr4);
2151 KD_REG_INIT_U64("cr8", pKNtCtx->u64RegCr8);
2152
2153 KD_REG_INIT_DTR("gdtr", pKNtCtx->Gdtr.u64PtrBase, pKNtCtx->Gdtr.u16Limit);
2154 KD_REG_INIT_DTR("idtr", pKNtCtx->Idtr.u64PtrBase, pKNtCtx->Idtr.u16Limit);
2155
2156#if 0 /** @todo CPUM returns VERR_NOT_IMPLEMENTED */
2157 KD_REG_INIT_U16("tr", pKNtCtx->u16RegTr);
2158 KD_REG_INIT_U16("ldtr", pKNtCtx->u16RegLdtr);
2159#endif
2160 KD_REG_INIT_U32("mxcsr", pKNtCtx->u32RegMxCsr);
2161
2162 KD_REG_INIT_U64("msr_gs_base", pKNtCtx->u64MsrGsBase);
2163 KD_REG_INIT_U64("krnl_gs_base", pKNtCtx->u64MsrKernelGsBase);
2164 KD_REG_INIT_U64("star", pKNtCtx->u64MsrStar);
2165 KD_REG_INIT_U64("lstar", pKNtCtx->u64MsrLstar);
2166 KD_REG_INIT_U64("cstar", pKNtCtx->u64MsrCstar);
2167 KD_REG_INIT_U64("sf_mask", pKNtCtx->u64MsrSfMask);
2168
2169 int rc = DBGFR3RegNmSetBatch(pThis->Dbgc.pUVM, idCpu, &aRegsSet[0], idxReg);
2170 if ( RT_SUCCESS(rc)
2171 && cbSet > RT_UOFFSETOF(NTKCONTEXT64, Ctx)) /** @todo Probably wrong. */
2172 rc = dbgcKdCtxSetNtCtx64(pThis, idCpu, &pKNtCtx->Ctx, pKNtCtx->Ctx.fContext);
2173
2174 if (RT_SUCCESS(rc))
2175 {
2176 /* Update emulated hardware breakpoint state. */
2177 dbgcKdCtxHwBpDr6Update(pThis, (uint32_t)pKNtCtx->u64RegDr6);
2178 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pKNtCtx->u64RegDr7);
2179 if (RT_SUCCESS(rc))
2180 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[0], pKNtCtx->u64RegDr0);
2181 if (RT_SUCCESS(rc))
2182 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[1], pKNtCtx->u64RegDr1);
2183 if (RT_SUCCESS(rc))
2184 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[2], pKNtCtx->u64RegDr2);
2185 if (RT_SUCCESS(rc))
2186 rc = dbgcKdCtxHwBpGCPtrUpdate(pThis, &pThis->aHwBp[3], pKNtCtx->u64RegDr3);
2187 }
2188
2189 return rc;
2190}
2191
2192#undef KD_REG_INIT_64
2193#undef KD_REG_INIT_32
2194#undef KD_REG_INIT_16
2195#undef KD_REG_INIT_DTR
2196#undef KD_REG_INIT
2197
2198
2199/**
2200 * Validates the given KD packet header.
2201 *
2202 * @returns Flag whether the packet header is valid, false if invalid.
2203 * @param pPktHdr The packet header to validate.
2204 */
2205static bool dbgcKdPktHdrValidate(PCKDPACKETHDR pPktHdr)
2206{
2207 if ( pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_DATA
2208 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_CONTROL
2209 && pPktHdr->u32Signature != KD_PACKET_HDR_SIGNATURE_BREAKIN)
2210 return false;
2211
2212 if (pPktHdr->u16SubType >= KD_PACKET_HDR_SUB_TYPE_MAX)
2213 return false;
2214
2215 uint32_t idPacket = pPktHdr->idPacket & UINT32_C(0xfffffffe);
2216 if ( idPacket != KD_PACKET_HDR_ID_INITIAL
2217 && idPacket != KD_PACKET_HDR_ID_RESET
2218 && idPacket != 0 /* Happens on the very first packet */)
2219 return false;
2220
2221 return true;
2222}
2223
2224
2225/**
2226 * Generates a checksum from the given buffer.
2227 *
2228 * @returns Generated checksum.
2229 * @param pv The data to generate a checksum from.
2230 * @param cb Number of bytes to checksum.
2231 */
2232static uint32_t dbgcKdPktChkSumGen(const void *pv, size_t cb)
2233{
2234 const uint8_t *pb = (const uint8_t *)pv;
2235 uint32_t u32ChkSum = 0;
2236
2237 while (cb--)
2238 u32ChkSum += *pb++;
2239
2240 return u32ChkSum;
2241}
2242
2243
2244/**
2245 * Generates a checksum from the given segments.
2246 *
2247 * @returns Generated checksum.
2248 * @param paSegs Pointer to the array of segments containing the data.
2249 * @param cSegs Number of segments.
2250 * @param pcbChkSum Where to store the number of bytes checksummed, optional.
2251 */
2252static uint32_t dbgcKdPktChkSumGenSg(PCRTSGSEG paSegs, uint32_t cSegs, size_t *pcbChkSum)
2253{
2254 size_t cbChkSum = 0;
2255 uint32_t u32ChkSum = 0;
2256
2257 for (uint32_t i = 0; i < cSegs; i++)
2258 {
2259 u32ChkSum += dbgcKdPktChkSumGen(paSegs[i].pvSeg, paSegs[i].cbSeg);
2260 cbChkSum += paSegs[i].cbSeg;
2261 }
2262
2263 if (pcbChkSum)
2264 *pcbChkSum = cbChkSum;
2265
2266 return u32ChkSum;
2267}
2268
2269
2270/**
2271 * Waits for an acknowledgment.
2272 *
2273 * @returns VBox status code.
2274 * @param pThis The KD context.
2275 * @param msWait Maximum number of milliseconds to wait for an acknowledge.
2276 * @param pfResend Where to store the resend requested flag on success.
2277 */
2278static int dbgcKdCtxPktWaitForAck(PKDCTX pThis, RTMSINTERVAL msWait, bool *pfResend)
2279{
2280 KDPACKETHDR PktAck;
2281 uint8_t *pbCur = (uint8_t *)&PktAck;
2282 size_t cbLeft = sizeof(PktAck);
2283 uint64_t tsStartMs = RTTimeMilliTS();
2284 int rc = VINF_SUCCESS;
2285
2286 LogFlowFunc(("pThis=%p msWait=%u pfResend=%p\n", pThis, msWait, pfResend));
2287
2288 RT_ZERO(PktAck);
2289
2290 /* There might be breakin packets in the queue, read until we get something else. */
2291 while ( msWait
2292 && RT_SUCCESS(rc))
2293 {
2294 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, msWait))
2295 {
2296 size_t cbRead = 0;
2297 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pbCur, 1, &cbRead);
2298 if ( RT_SUCCESS(rc)
2299 && cbRead == 1)
2300 {
2301 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2302 msWait -= RT_MIN(msWait, tsSpanMs);
2303 tsStartMs = RTTimeMilliTS();
2304
2305 if (*pbCur == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
2306 pThis->fBreakinRecv = true;
2307 else
2308 {
2309 pbCur++;
2310 cbLeft--;
2311 break;
2312 }
2313 }
2314 }
2315 else
2316 rc = VERR_TIMEOUT;
2317 }
2318
2319 if ( RT_SUCCESS(rc)
2320 && !msWait)
2321 rc = VERR_TIMEOUT;
2322
2323 if (RT_SUCCESS(rc))
2324 {
2325 while ( msWait
2326 && RT_SUCCESS(rc)
2327 && cbLeft)
2328 {
2329 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, msWait))
2330 {
2331 size_t cbRead = 0;
2332 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pbCur, cbLeft, &cbRead);
2333 if (RT_SUCCESS(rc))
2334 {
2335 uint64_t tsSpanMs = RTTimeMilliTS() - tsStartMs;
2336 msWait -= RT_MIN(msWait, tsSpanMs);
2337 tsStartMs = RTTimeMilliTS();
2338
2339 cbLeft -= cbRead;
2340 pbCur += cbRead;
2341 }
2342 }
2343 else
2344 rc = VERR_TIMEOUT;
2345 }
2346
2347 if (RT_SUCCESS(rc))
2348 {
2349 if (PktAck.u32Signature == KD_PACKET_HDR_SIGNATURE_CONTROL)
2350 {
2351 if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE)
2352 rc = VINF_SUCCESS;
2353 else if (PktAck.u16SubType == KD_PACKET_HDR_SUB_TYPE_RESEND)
2354 {
2355 *pfResend = true;
2356 rc = VINF_SUCCESS;
2357 }
2358 else
2359 rc = VERR_NET_PROTOCOL_ERROR;
2360 }
2361 else
2362 rc = VERR_NET_PROTOCOL_ERROR;
2363 }
2364 }
2365
2366 LogFlowFunc(("returns rc=%Rrc *pfResend=%RTbool\n", rc, *pfResend));
2367 return rc;
2368}
2369
2370
2371/**
2372 * Sends the given packet header and optional segmented body (the trailing byte is sent automatically).
2373 *
2374 * @returns VBox status code.
2375 * @param pThis The KD context.
2376 * @param u32Signature The signature to send.
2377 * @param u16SubType The sub type to send.
2378 * @param paSegs Pointer to the array of segments to send in the body, optional.
2379 * @param cSegs Number of segments.
2380 * @param fAck Flag whether to wait for an acknowledge.
2381 */
2382static int dbgcKdCtxPktSendSg(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2383 PCRTSGSEG paSegs, uint32_t cSegs, bool fAck)
2384{
2385 int rc = VINF_SUCCESS;
2386 uint32_t cRetriesLeft = 3;
2387 uint8_t bTrailer = KD_PACKET_TRAILING_BYTE;
2388 KDPACKETHDR Hdr;
2389
2390 size_t cbChkSum = 0;
2391 uint32_t u32ChkSum = dbgcKdPktChkSumGenSg(paSegs, cSegs, &cbChkSum);
2392
2393 Hdr.u32Signature = u32Signature;
2394 Hdr.u16SubType = u16SubType;
2395 Hdr.cbBody = (uint16_t)cbChkSum;
2396 Hdr.idPacket = pThis->idPktNext;
2397 Hdr.u32ChkSum = u32ChkSum;
2398
2399#ifdef LOG_ENABLED
2400 dbgcKdPktDump(&Hdr, paSegs, cSegs, false /*fRx*/);
2401#endif
2402
2403 while (cRetriesLeft--)
2404 {
2405 bool fResend = false;
2406
2407 rc = dbgcKdCtxWrite(pThis, &Hdr, sizeof(Hdr));
2408 if ( RT_SUCCESS(rc)
2409 && paSegs
2410 && cSegs)
2411 {
2412 for (uint32_t i = 0; i < cSegs && RT_SUCCESS(rc); i++)
2413 rc = dbgcKdCtxWrite(pThis, paSegs[i].pvSeg, paSegs[i].cbSeg);
2414
2415 if (RT_SUCCESS(rc))
2416 rc = dbgcKdCtxWrite(pThis, &bTrailer, sizeof(bTrailer));
2417 }
2418
2419 if (RT_SUCCESS(rc))
2420 {
2421 if (fAck)
2422 rc = dbgcKdCtxPktWaitForAck(pThis, 10 * 1000, &fResend);
2423
2424 if ( RT_SUCCESS(rc)
2425 && !fResend)
2426 break;
2427 }
2428 }
2429
2430 return rc;
2431}
2432
2433
2434/**
2435 * Sends the given packet header and optional body (the trailing byte is sent automatically).
2436 *
2437 * @returns VBox status code.
2438 * @param pThis The KD context.
2439 * @param u32Signature The signature to send.
2440 * @param u16SubType The sub type to send.
2441 * @param pvBody The body to send, optional.
2442 * @param cbBody Body size in bytes.
2443 * @param fAck Flag whether to wait for an acknowledge.
2444 */
2445DECLINLINE(int) dbgcKdCtxPktSend(PKDCTX pThis, uint32_t u32Signature, uint16_t u16SubType,
2446 const void *pvBody, size_t cbBody,
2447 bool fAck)
2448{
2449 RTSGSEG Seg;
2450
2451 Seg.pvSeg = (void *)pvBody;
2452 Seg.cbSeg = cbBody;
2453 return dbgcKdCtxPktSendSg(pThis, u32Signature, u16SubType, cbBody ? &Seg : NULL, cbBody ? 1 : 0, fAck);
2454}
2455
2456
2457/**
2458 * Sends a resend packet answer.
2459 *
2460 * @returns VBox status code.
2461 * @param pThis The KD context.
2462 */
2463DECLINLINE(int) dbgcKdCtxPktSendResend(PKDCTX pThis)
2464{
2465 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESEND,
2466 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2467}
2468
2469
2470/**
2471 * Sends a resend packet answer.
2472 *
2473 * @returns VBox status code.
2474 * @param pThis The KD context.
2475 */
2476DECLINLINE(int) dbgcKdCtxPktSendReset(PKDCTX pThis)
2477{
2478 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2479 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_RESET,
2480 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2481}
2482
2483
2484/**
2485 * Sends an acknowledge packet answer.
2486 *
2487 * @returns VBox status code.
2488 * @param pThis The KD context.
2489 */
2490DECLINLINE(int) dbgcKdCtxPktSendAck(PKDCTX pThis)
2491{
2492 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_CONTROL, KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE,
2493 NULL /*pvBody*/, 0 /*cbBody*/, false /*fAck*/);
2494}
2495
2496
2497/**
2498 * Resets the packet receive state machine.
2499 *
2500 * @returns nothing.
2501 * @param pThis The KD context.
2502 */
2503static void dbgcKdCtxPktRecvReset(PKDCTX pThis)
2504{
2505 pThis->enmState = KDRECVSTATE_PACKET_HDR_FIRST_BYTE;
2506 pThis->pbRecv = &pThis->PktHdr.ab[0];
2507 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[0]);
2508 pThis->msRecvTimeout = RT_INDEFINITE_WAIT;
2509 pThis->tsRecvLast = RTTimeMilliTS();
2510}
2511
2512
2513/**
2514 * Sends a Debug I/O string packet.
2515 *
2516 * @returns VBox status code.
2517 * @param pThis The KD context data.
2518 * @param idCpu The CPU ID generating this packet.
2519 * @param pachChars The characters to send (ASCII).
2520 * @param cbChars Number of characters to send.
2521 */
2522static int dbgcKdCtxDebugIoStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachChars, size_t cbChars)
2523{
2524 KDPACKETDEBUGIO DebugIo;
2525 RT_ZERO(DebugIo);
2526
2527 /* Fix your damn log strings if this exceeds 4GB... */
2528 if (cbChars != (uint32_t)cbChars)
2529 return VERR_BUFFER_OVERFLOW;
2530
2531 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2532 DebugIo.u16CpuLvl = 0x6;
2533 DebugIo.idCpu = (uint16_t)idCpu;
2534 DebugIo.u.Str.cbStr = (uint32_t)cbChars;
2535
2536 RTSGSEG aRespSegs[2];
2537
2538 aRespSegs[0].pvSeg = &DebugIo;
2539 aRespSegs[0].cbSeg = sizeof(DebugIo);
2540 aRespSegs[1].pvSeg = (void *)pachChars;
2541 aRespSegs[1].cbSeg = cbChars;
2542
2543 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2544 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2545 if (RT_SUCCESS(rc))
2546 pThis->idPktNext ^= 0x1;
2547
2548 return rc;
2549}
2550
2551
2552/**
2553 * Sends a message to the remotes end.
2554 *
2555 * @returns nothing.
2556 * @param pThis The KD context data.
2557 * @param fWarning Flag whether this is a warning or an informational message.
2558 * @param pszMsg The message to send.
2559 */
2560static void dbgcKdCtxMsgSend(PKDCTX pThis, bool fWarning, const char *pszMsg)
2561{
2562 size_t cchMsg = strlen(pszMsg);
2563
2564 KDPACKETDEBUGIO DebugIo;
2565 RT_ZERO(DebugIo);
2566
2567 DebugIo.u32Type = KD_PACKET_DEBUG_IO_STRING;
2568 DebugIo.u16CpuLvl = 0x6;
2569 DebugIo.idCpu = 0;
2570
2571 RTSGSEG aRespSegs[5];
2572
2573 aRespSegs[0].pvSeg = &DebugIo;
2574 aRespSegs[0].cbSeg = sizeof(DebugIo);
2575 aRespSegs[1].pvSeg = (void *)"VBoxDbg ";
2576 aRespSegs[1].cbSeg = sizeof("VBoxDbg ") - 1;
2577 if (fWarning)
2578 {
2579 aRespSegs[2].pvSeg = (void *)"WARNING ";
2580 aRespSegs[2].cbSeg = sizeof("WARNING ") - 1;
2581 }
2582 else
2583 {
2584 aRespSegs[2].pvSeg = (void *)"INFO ";
2585 aRespSegs[2].cbSeg = sizeof("INFO ") - 1;
2586 }
2587 aRespSegs[3].pvSeg = (void *)pszMsg;
2588 aRespSegs[3].cbSeg = cchMsg;
2589 aRespSegs[4].pvSeg = (void *)"\r\n";
2590 aRespSegs[4].cbSeg = 2;
2591
2592 DebugIo.u.Str.cbStr = (uint32_t)( aRespSegs[1].cbSeg
2593 + aRespSegs[2].cbSeg
2594 + aRespSegs[3].cbSeg
2595 + aRespSegs[4].cbSeg);
2596
2597 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2598 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2599 if (RT_SUCCESS(rc))
2600 pThis->idPktNext ^= 0x1;
2601}
2602
2603
2604/**
2605 * Queries some user input from the remotes end.
2606 *
2607 * @returns VBox status code.
2608 * @param pThis The KD context data.
2609 * @param idCpu The CPU ID generating this packet.
2610 * @param pachPrompt The prompt to send (ASCII).
2611 * @param cbPrompt Number of characters to send for the prompt.
2612 * @param cbResponseMax Maximum size for the response.
2613 */
2614static int dbgcKdCtxDebugIoGetStrSend(PKDCTX pThis, VMCPUID idCpu, const char *pachPrompt, size_t cbPrompt,
2615 size_t cbResponseMax)
2616{
2617 KDPACKETDEBUGIO DebugIo;
2618 RT_ZERO(DebugIo);
2619
2620 /* Fix your damn log strings if this exceeds 4GB... */
2621 if ( cbPrompt != (uint32_t)cbPrompt
2622 || cbResponseMax != (uint32_t)cbResponseMax)
2623 return VERR_BUFFER_OVERFLOW;
2624
2625 DebugIo.u32Type = KD_PACKET_DEBUG_IO_GET_STRING;
2626 DebugIo.u16CpuLvl = 0x6;
2627 DebugIo.idCpu = (uint16_t)idCpu;
2628 DebugIo.u.Prompt.cbPrompt = (uint32_t)cbPrompt;
2629 DebugIo.u.Prompt.cbReturn = (uint32_t)cbResponseMax;
2630
2631 RTSGSEG aRespSegs[2];
2632
2633 aRespSegs[0].pvSeg = &DebugIo;
2634 aRespSegs[0].cbSeg = sizeof(DebugIo);
2635 aRespSegs[1].pvSeg = (void *)pachPrompt;
2636 aRespSegs[1].cbSeg = cbPrompt;
2637
2638 int rc = dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_DEBUG_IO,
2639 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
2640 if (RT_SUCCESS(rc))
2641 pThis->idPktNext ^= 0x1;
2642
2643 return rc;
2644}
2645
2646
2647/**
2648 * Sends a state change event packet.
2649 *
2650 * @returns VBox status code.
2651 * @param pThis The KD context data.
2652 * @param enmType The event type.
2653 */
2654static int dbgcKdCtxStateChangeSend(PKDCTX pThis, DBGFEVENTTYPE enmType)
2655{
2656 LogFlowFunc(("pThis=%p enmType=%u\n", pThis, enmType));
2657
2658 /* Select the record to send based on the CPU mode. */
2659 int rc = VINF_SUCCESS;
2660 KDPACKETSTATECHANGE64 StateChange64;
2661 RT_ZERO(StateChange64);
2662
2663 StateChange64.u32StateNew = KD_PACKET_STATE_CHANGE_EXCEPTION;
2664 StateChange64.u16CpuLvl = 0x6; /** @todo Figure this one out. */
2665 StateChange64.idCpu = pThis->Dbgc.idCpu;
2666 StateChange64.cCpus = (uint16_t)DBGFR3CpuGetCount(pThis->Dbgc.pUVM);
2667 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RIP, &StateChange64.u64RipThread);
2668 if (RT_SUCCESS(rc))
2669 {
2670 DBGFADDRESS AddrRip;
2671 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRip, StateChange64.u64RipThread);
2672
2673 StateChange64.u64RipThread = KD_PTR_CREATE(pThis, StateChange64.u64RipThread);
2674
2675 /** @todo Properly fill in the exception record. */
2676 switch (enmType)
2677 {
2678 case DBGFEVENT_HALT_DONE:
2679 case DBGFEVENT_BREAKPOINT:
2680 case DBGFEVENT_BREAKPOINT_IO:
2681 case DBGFEVENT_BREAKPOINT_MMIO:
2682 case DBGFEVENT_BREAKPOINT_HYPER:
2683 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_BKPT;
2684 break;
2685 case DBGFEVENT_STEPPED:
2686 case DBGFEVENT_STEPPED_HYPER:
2687 pThis->fSingleStepped = true; /* For emulation of DR6. */
2688 StateChange64.u.Exception.ExcpRec.u32ExcpCode = KD_PACKET_EXCP_CODE_SINGLE_STEP;
2689 break;
2690 default:
2691 AssertMsgFailed(("Invalid DBGF event type for state change %d!\n", enmType));
2692 }
2693
2694 StateChange64.u.Exception.ExcpRec.cExcpParms = 3;
2695 StateChange64.u.Exception.u32FirstChance = 0x1;
2696
2697 /** @todo Properly fill in the control report. */
2698 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR6, &StateChange64.uCtrlReport.Amd64.u64RegDr6);
2699 if (RT_SUCCESS(rc))
2700 rc = DBGFR3RegCpuQueryU64(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DR7, &StateChange64.uCtrlReport.Amd64.u64RegDr7);
2701 if (RT_SUCCESS(rc))
2702 rc = DBGFR3RegCpuQueryU32(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_RFLAGS, &StateChange64.uCtrlReport.Amd64.u32RegEflags);
2703 if (RT_SUCCESS(rc))
2704 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_CS, &StateChange64.uCtrlReport.Amd64.u16SegCs);
2705 if (RT_SUCCESS(rc))
2706 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_DS, &StateChange64.uCtrlReport.Amd64.u16SegDs);
2707 if (RT_SUCCESS(rc))
2708 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_ES, &StateChange64.uCtrlReport.Amd64.u16SegEs);
2709 if (RT_SUCCESS(rc))
2710 rc = DBGFR3RegCpuQueryU16(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGFREG_FS, &StateChange64.uCtrlReport.Amd64.u16SegFs);
2711
2712 /* Read instruction bytes. */
2713 StateChange64.uCtrlReport.Amd64.cbInsnStream = sizeof(StateChange64.uCtrlReport.Amd64.abInsn);
2714 rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRip,
2715 &StateChange64.uCtrlReport.Amd64.abInsn[0], StateChange64.uCtrlReport.Amd64.cbInsnStream);
2716 if (RT_SUCCESS(rc))
2717 {
2718 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
2719 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_CHANGE64,
2720 &StateChange64, sizeof(StateChange64), false /*fAck*/);
2721 }
2722 }
2723
2724 LogFlowFunc(("returns %Rrc\n", rc));
2725 return rc;
2726}
2727
2728
2729/**
2730 * Processes a get version 64 request.
2731 *
2732 * @returns VBox status code.
2733 * @param pThis The KD context.
2734 * @param pPktManip The manipulate packet request.
2735 */
2736static int dbgcKdCtxPktManipulate64GetVersion(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2737{
2738 KDPACKETMANIPULATE64 Resp;
2739 RT_ZERO(Resp);
2740
2741 /* Fill in the generic part. */
2742 Resp.Hdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_VERSION;
2743 Resp.Hdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2744 Resp.Hdr.idCpu = pPktManip->Hdr.idCpu;
2745 Resp.Hdr.u32NtStatus = NTSTATUS_SUCCESS;
2746
2747 /* Build our own response in case there is no Windows interface available. */
2748 uint32_t NtBuildNumber = 0x0f2800; /* Used when there is no NT interface available, which probably breaks symbol loading. */
2749 bool f32Bit = false;
2750 if (pThis->pIfWinNt)
2751 {
2752 int rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
2753 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
2754 &NtBuildNumber, &f32Bit);
2755 if (RT_SUCCESS(rc))
2756 rc = pThis->pIfWinNt->pfnQueryKernelPtrs(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
2757 &Resp.u.GetVersion.u64PtrKernBase,
2758 &Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2759 }
2760
2761 /* Fill in the request specific part. */
2762 Resp.u.GetVersion.u16VersMaj = NtBuildNumber >> 16;
2763 Resp.u.GetVersion.u16VersMin = NtBuildNumber & UINT32_C(0xffff);
2764 Resp.u.GetVersion.u8VersProtocol = 0x6; /* From a Windows 10 guest. */
2765 Resp.u.GetVersion.u8VersKdSecondary = pThis->f32Bit ? 0 : 0x2; /* amd64 has a versioned context (0 and 1 are obsolete). */
2766 Resp.u.GetVersion.fFlags = KD_PACKET_MANIPULATE64_GET_VERSION_F_MP;
2767 Resp.u.GetVersion.u8MaxPktType = KD_PACKET_HDR_SUB_TYPE_MAX;
2768 Resp.u.GetVersion.u8MaxStateChange = KD_PACKET_STATE_CHANGE_MAX - KD_PACKET_STATE_CHANGE_MIN;
2769 Resp.u.GetVersion.u8MaxManipulate = KD_PACKET_MANIPULATE_REQ_MAX - KD_PACKET_MANIPULATE_REQ_MIN;
2770 Resp.u.GetVersion.u64PtrDebuggerDataList = 0;
2771
2772 if (f32Bit)
2773 {
2774 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_I386;
2775 Resp.u.GetVersion.u64PtrKernBase = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrKernBase);
2776 Resp.u.GetVersion.u64PtrPsLoadedModuleList = KD_PTR_CREATE(pThis, Resp.u.GetVersion.u64PtrPsLoadedModuleList);
2777 }
2778 else
2779 {
2780 Resp.u.GetVersion.u16MachineType = IMAGE_FILE_MACHINE_AMD64;
2781 Resp.u.GetVersion.fFlags |= KD_PACKET_MANIPULATE64_GET_VERSION_F_PTR64;
2782 }
2783
2784 return dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2785 &Resp, sizeof(Resp), true /*fAck*/);
2786}
2787
2788
2789/**
2790 * Processes a read memory 64 request.
2791 *
2792 * @returns VBox status code.
2793 * @param pThis The KD context.
2794 * @param pPktManip The manipulate packet request.
2795 */
2796static int dbgcKdCtxPktManipulate64ReadMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2797{
2798 KDPACKETMANIPULATEHDR RespHdr;
2799 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2800 uint8_t abMem[_4K];
2801 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2802
2803 DBGFADDRESS AddrRead;
2804 uint32_t cbRead = RT_MIN(sizeof(abMem), pPktManip->u.XferMem.cbXferReq);
2805 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM)
2806 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2807 else
2808 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrRead, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2809
2810 RTSGSEG aRespSegs[3];
2811 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2812 RespHdr.idReq = pPktManip->Hdr.idReq;
2813 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2814 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2815 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2816
2817 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2818 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2819 XferMem64.cbXfered = (uint32_t)cbRead;
2820
2821 aRespSegs[0].pvSeg = &RespHdr;
2822 aRespSegs[0].cbSeg = sizeof(RespHdr);
2823 aRespSegs[1].pvSeg = &XferMem64;
2824 aRespSegs[1].cbSeg = sizeof(XferMem64);
2825
2826 int rc = DBGFR3MemRead(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrRead, &abMem[0], cbRead);
2827 if (RT_SUCCESS(rc))
2828 {
2829 cSegs++;
2830 aRespSegs[2].pvSeg = &abMem[0];
2831 aRespSegs[2].cbSeg = cbRead;
2832 }
2833 else
2834 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2835
2836 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2837 &aRespSegs[0], cSegs, true /*fAck*/);
2838}
2839
2840
2841/**
2842 * Processes a write memory 64 request.
2843 *
2844 * @returns VBox status code.
2845 * @param pThis The KD context.
2846 * @param pPktManip The manipulate packet request.
2847 */
2848static int dbgcKdCtxPktManipulate64WriteMem(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2849{
2850 KDPACKETMANIPULATEHDR RespHdr;
2851 KDPACKETMANIPULATE_XFERMEM64 XferMem64;
2852 RT_ZERO(RespHdr); RT_ZERO(XferMem64);
2853
2854 DBGFADDRESS AddrWrite;
2855 const void *pv = &pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2856 uint32_t cbWrite = RT_MIN(sizeof(pThis->abBody) - sizeof(*pPktManip), pPktManip->u.XferMem.cbXferReq);
2857 if (pPktManip->Hdr.idReq == KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM)
2858 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2859 else
2860 DBGFR3AddrFromPhys(pThis->Dbgc.pUVM, &AddrWrite, KD_PTR_GET(pThis, pPktManip->u.XferMem.u64PtrTarget));
2861
2862 RTSGSEG aRespSegs[2];
2863 uint32_t cSegs = 2;
2864 RespHdr.idReq = pPktManip->Hdr.idReq;
2865 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2866 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2867 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2868
2869 XferMem64.u64PtrTarget = pPktManip->u.XferMem.u64PtrTarget;
2870 XferMem64.cbXferReq = pPktManip->u.XferMem.cbXferReq;
2871 XferMem64.cbXfered = (uint32_t)cbWrite;
2872
2873 aRespSegs[0].pvSeg = &RespHdr;
2874 aRespSegs[0].cbSeg = sizeof(RespHdr);
2875 aRespSegs[1].pvSeg = &XferMem64;
2876 aRespSegs[1].cbSeg = sizeof(XferMem64);
2877
2878 int rc = DBGFR3MemWrite(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &AddrWrite, pv, cbWrite);
2879 if (RT_FAILURE(rc))
2880 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2881
2882 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2883 &aRespSegs[0], cSegs, true /*fAck*/);
2884}
2885
2886
2887/**
2888 * Processes a continue request.
2889 *
2890 * @returns VBox status code.
2891 * @param pThis The KD context.
2892 * @param pPktManip The manipulate packet request.
2893 */
2894static int dbgcKdCtxPktManipulate64Continue(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2895{
2896 RT_NOREF(pPktManip);
2897 int rc = VINF_SUCCESS;
2898
2899 /* No response, just resume. */
2900 if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2901 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2902
2903 return rc;
2904}
2905
2906
2907/**
2908 * Processes a continue request.
2909 *
2910 * @returns VBox status code.
2911 * @param pThis The KD context.
2912 * @param pPktManip The manipulate packet request.
2913 */
2914static int dbgcKdCtxPktManipulate64Continue2(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2915{
2916 int rc = VINF_SUCCESS;
2917
2918 /* Update DR7. */
2919 if (pThis->f32Bit)
2920 rc = dbgcKdCtxHwBpDr7Update(pThis, pPktManip->u.Continue2.u.x86.u32RegDr7);
2921 else
2922 rc = dbgcKdCtxHwBpDr7Update(pThis, (uint32_t)pPktManip->u.Continue2.u.amd64.u64RegDr7);
2923
2924 /* Resume if not single stepping, the single step will get a state change when the VM stepped. */
2925 if (pPktManip->u.Continue2.fTrace)
2926 {
2927 PDBGFADDRESS pStackPop = NULL;
2928 RTGCPTR cbStackPop = 0;
2929 rc = DBGFR3StepEx(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, DBGF_STEP_F_INTO, NULL,
2930 pStackPop, cbStackPop, 1 /*cMaxSteps*/);
2931 }
2932 else if (DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
2933 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
2934
2935 return rc;
2936}
2937
2938
2939/**
2940 * Processes a set context request.
2941 *
2942 * @returns VBox status code.
2943 * @param pThis The KD context.
2944 * @param pPktManip The manipulate packet request.
2945 */
2946static int dbgcKdCtxPktManipulate64SetContext(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2947{
2948 KDPACKETMANIPULATEHDR RespHdr;
2949 KDPACKETMANIPULATE_SETCONTEXT SetContext;
2950 RT_ZERO(RespHdr); RT_ZERO(SetContext);
2951
2952 PCNTCONTEXT64 pNtCtx = (PCNTCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
2953
2954 RTSGSEG aRespSegs[2];
2955 uint32_t cSegs = 2;
2956 RespHdr.idReq = pPktManip->Hdr.idReq;
2957 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2958 RespHdr.idCpu = pPktManip->Hdr.idCpu;
2959 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
2960
2961 /** @todo What do these flags mean? Can't be the context state to set because the valid one is
2962 * in NTCONTEXT64::fContext (observed with WinDbg). */
2963 SetContext.u32CtxFlags = pPktManip->u.SetContext.u32CtxFlags;
2964
2965 aRespSegs[0].pvSeg = &RespHdr;
2966 aRespSegs[0].cbSeg = sizeof(RespHdr);
2967 aRespSegs[1].pvSeg = &SetContext;
2968 aRespSegs[1].cbSeg = sizeof(SetContext);
2969
2970 int rc = dbgcKdCtxSetNtCtx64(pThis, pPktManip->Hdr.idCpu, pNtCtx, pNtCtx->fContext);
2971 if (RT_FAILURE(rc))
2972 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
2973
2974 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
2975 &aRespSegs[0], cSegs, true /*fAck*/);
2976}
2977
2978
2979/**
2980 * Processes a read control space 64 request.
2981 *
2982 * @returns VBox status code.
2983 * @param pThis The KD context.
2984 * @param pPktManip The manipulate packet request.
2985 */
2986static int dbgcKdCtxPktManipulate64ReadCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
2987{
2988 KDPACKETMANIPULATEHDR RespHdr;
2989 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
2990 uint8_t abResp[sizeof(NTKCONTEXT64)];
2991 uint32_t cbData = 0;
2992 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
2993 RT_ZERO(abResp);
2994
2995 RTSGSEG aRespSegs[3];
2996 uint32_t cSegs = 2; /* Gets incremented when read is successful. */
2997 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE;
2998 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
2999 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3000 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3001
3002 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3003 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3004
3005 aRespSegs[0].pvSeg = &RespHdr;
3006 aRespSegs[0].cbSeg = sizeof(RespHdr);
3007 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3008 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3009
3010 int rc = VINF_SUCCESS;
3011 if (pThis->f32Bit)
3012 {
3013 if (pPktManip->u.XferCtrlSpace.u64IdXfer == sizeof(NTCONTEXT32))
3014 {
3015 /* Queries the kernel context. */
3016 rc = dbgcKdCtxQueryNtKCtx32(pThis, RespHdr.idCpu, (PNTKCONTEXT32)&abResp[0]);
3017 if (RT_SUCCESS(rc))
3018 cbData = sizeof(NTKCONTEXT32);
3019 }
3020 }
3021 else
3022 {
3023 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3024 {
3025 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3026 {
3027 if (pThis->pIfWinNt)
3028 {
3029 RTGCUINTPTR GCPtrKpcr = 0;
3030
3031 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(), RespHdr.idCpu,
3032 &GCPtrKpcr, NULL /*pKpcrb*/);
3033 if (RT_SUCCESS(rc))
3034 memcpy(&abResp[0], &GCPtrKpcr, sizeof(GCPtrKpcr));
3035 }
3036
3037 cbData = sizeof(RTGCUINTPTR);
3038 break;
3039 }
3040 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3041 {
3042 if (pThis->pIfWinNt)
3043 {
3044 RTGCUINTPTR GCPtrKpcrb = 0;
3045
3046 rc = pThis->pIfWinNt->pfnQueryKpcrForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(), RespHdr.idCpu,
3047 NULL /*pKpcr*/, &GCPtrKpcrb);
3048 if (RT_SUCCESS(rc))
3049 memcpy(&abResp[0], &GCPtrKpcrb, sizeof(GCPtrKpcrb));
3050 }
3051
3052 cbData = sizeof(RTGCUINTPTR);
3053 break;
3054 }
3055 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3056 {
3057 rc = dbgcKdCtxQueryNtKCtx64(pThis, RespHdr.idCpu, (PNTKCONTEXT64)&abResp[0], NTCONTEXT64_F_FULL);
3058 if (RT_SUCCESS(rc))
3059 cbData = sizeof(NTKCONTEXT64);
3060 break;
3061 }
3062 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3063 {
3064 if (pThis->pIfWinNt)
3065 {
3066 RTGCUINTPTR GCPtrCurThrd = 0;
3067
3068 rc = pThis->pIfWinNt->pfnQueryCurThrdForVCpu(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
3069 RespHdr.idCpu, &GCPtrCurThrd);
3070 if (RT_SUCCESS(rc))
3071 memcpy(&abResp[0], &GCPtrCurThrd, sizeof(GCPtrCurThrd));
3072 }
3073
3074 cbData = sizeof(RTGCUINTPTR);
3075 break;
3076 }
3077 default:
3078 rc = VERR_NOT_SUPPORTED;
3079 break;
3080 }
3081 }
3082
3083 if ( RT_SUCCESS(rc)
3084 && cbData)
3085 {
3086 XferCtrlSpace64.cbXfered = RT_MIN(cbData, XferCtrlSpace64.cbXferReq);
3087
3088 cSegs++;
3089 aRespSegs[2].pvSeg = &abResp[0];
3090 aRespSegs[2].cbSeg = cbData;
3091 }
3092 else if (RT_FAILURE(rc))
3093 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3094
3095 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3096 &aRespSegs[0], cSegs, true /*fAck*/);
3097}
3098
3099
3100/**
3101 * Processes a write control space 64 request.
3102 *
3103 * @returns VBox status code.
3104 * @param pThis The KD context.
3105 * @param pPktManip The manipulate packet request.
3106 */
3107static int dbgcKdCtxPktManipulate64WriteCtrlSpace(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3108{
3109 KDPACKETMANIPULATEHDR RespHdr;
3110 KDPACKETMANIPULATE_XFERCTRLSPACE64 XferCtrlSpace64;
3111 uint32_t cbData = 0;
3112 RT_ZERO(RespHdr); RT_ZERO(XferCtrlSpace64);
3113
3114 RTSGSEG aRespSegs[2];
3115 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE;
3116 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3117 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3118 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3119
3120 XferCtrlSpace64.u64IdXfer = pPktManip->u.XferCtrlSpace.u64IdXfer;
3121 XferCtrlSpace64.cbXferReq = pPktManip->u.XferCtrlSpace.cbXferReq;
3122
3123 aRespSegs[0].pvSeg = &RespHdr;
3124 aRespSegs[0].cbSeg = sizeof(RespHdr);
3125 aRespSegs[1].pvSeg = &XferCtrlSpace64;
3126 aRespSegs[1].cbSeg = sizeof(XferCtrlSpace64);
3127
3128 int rc = VINF_SUCCESS;
3129 switch (pPktManip->u.XferCtrlSpace.u64IdXfer)
3130 {
3131 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KCTX:
3132 {
3133 PCNTKCONTEXT64 pNtKCtx = (PCNTKCONTEXT64)&pThis->abBody[sizeof(*pPktManip)]; /* Data comes directly after the manipulate state body. */
3134 rc = dbgcKdCtxSetNtKCtx64(pThis, RespHdr.idCpu, pNtKCtx, XferCtrlSpace64.cbXferReq);
3135 if (RT_SUCCESS(rc))
3136 cbData = RT_MIN(XferCtrlSpace64.cbXferReq, sizeof(NTKCONTEXT64));
3137 break;
3138 }
3139 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCR:
3140 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KPCRB:
3141 case KD_PACKET_MANIPULATE64_CTRL_SPACE_ID_KTHRD:
3142 default:
3143 rc = VERR_NOT_SUPPORTED;
3144 break;
3145 }
3146
3147 if (RT_FAILURE(rc))
3148 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Convert to an appropriate NT status code. */
3149 else
3150 XferCtrlSpace64.cbXfered = cbData;
3151
3152 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3153 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3154}
3155
3156
3157/**
3158 * Processes a restore breakpoint 64 request.
3159 *
3160 * @returns VBox status code.
3161 * @param pThis The KD context.
3162 * @param pPktManip The manipulate packet request.
3163 */
3164static int dbgcKdCtxPktManipulate64RestoreBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3165{
3166 KDPACKETMANIPULATEHDR RespHdr;
3167 KDPACKETMANIPULATE_RESTOREBKPT64 RestoreBkpt64;
3168 RT_ZERO(RespHdr); RT_ZERO(RestoreBkpt64);
3169
3170 RTSGSEG aRespSegs[2];
3171 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT;
3172 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3173 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3174 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3175
3176 RestoreBkpt64.u32HndBkpt = pPktManip->u.RestoreBkpt.u32HndBkpt;
3177
3178 aRespSegs[0].pvSeg = &RespHdr;
3179 aRespSegs[0].cbSeg = sizeof(RespHdr);
3180 aRespSegs[1].pvSeg = &RestoreBkpt64;
3181 aRespSegs[1].cbSeg = sizeof(RestoreBkpt64);
3182
3183 int rc = DBGFR3BpClear(pThis->Dbgc.pUVM, pPktManip->u.RestoreBkpt.u32HndBkpt);
3184 if (RT_SUCCESS(rc))
3185 {
3186 rc = dbgcBpDelete(&pThis->Dbgc, pPktManip->u.RestoreBkpt.u32HndBkpt);
3187 AssertRC(rc);
3188 }
3189 else if (rc != VERR_DBGF_BP_NOT_FOUND)
3190 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3191
3192 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3193 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3194}
3195
3196
3197/**
3198 * Processes a write breakpoint 64 request.
3199 *
3200 * @returns VBox status code.
3201 * @param pThis The KD context.
3202 * @param pPktManip The manipulate packet request.
3203 */
3204static int dbgcKdCtxPktManipulate64WriteBkpt(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3205{
3206 KDPACKETMANIPULATEHDR RespHdr;
3207 KDPACKETMANIPULATE_WRITEBKPT64 WriteBkpt64;
3208 RT_ZERO(RespHdr); RT_ZERO(WriteBkpt64);
3209
3210 RTSGSEG aRespSegs[2];
3211 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_WRITE_BKPT;
3212 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3213 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3214 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3215
3216 aRespSegs[0].pvSeg = &RespHdr;
3217 aRespSegs[0].cbSeg = sizeof(RespHdr);
3218 aRespSegs[1].pvSeg = &WriteBkpt64;
3219 aRespSegs[1].cbSeg = sizeof(WriteBkpt64);
3220
3221 WriteBkpt64.u64PtrBkpt = pPktManip->u.WriteBkpt.u64PtrBkpt;
3222
3223 DBGFADDRESS BpAddr;
3224 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &BpAddr, KD_PTR_GET(pThis, pPktManip->u.WriteBkpt.u64PtrBkpt));
3225 int rc = DBGFR3BpSetInt3(pThis->Dbgc.pUVM, pThis->Dbgc.idCpu, &BpAddr,
3226 1 /*iHitTrigger*/, UINT64_MAX /*iHitDisable*/, &WriteBkpt64.u32HndBkpt);
3227 if (RT_SUCCESS(rc))
3228 {
3229 rc = dbgcBpAdd(&pThis->Dbgc, WriteBkpt64.u32HndBkpt, NULL /*pszCmd*/);
3230 if (RT_FAILURE(rc))
3231 DBGFR3BpClear(pThis->Dbgc.pUVM, WriteBkpt64.u32HndBkpt);
3232 }
3233 else
3234 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3235
3236 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3237 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3238}
3239
3240
3241/**
3242 * Processes a get context extended 64 request.
3243 *
3244 * @returns VBox status code.
3245 * @param pThis The KD context.
3246 * @param pPktManip The manipulate packet request.
3247 */
3248static int dbgcKdCtxPktManipulate64GetContextEx(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3249{
3250 KDPACKETMANIPULATEHDR RespHdr;
3251 KDPACKETMANIPULATE_CONTEXTEX ContextEx;
3252 union
3253 {
3254 NTCONTEXT64 v64;
3255 NTCONTEXT32 v32;
3256 } NtCtx;
3257 RT_ZERO(RespHdr); RT_ZERO(ContextEx); RT_ZERO(NtCtx);
3258
3259 RTSGSEG aRespSegs[3];
3260 uint32_t cSegs = 2;
3261 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX;
3262 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3263 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3264 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3265
3266 ContextEx.offStart = pPktManip->u.ContextEx.offStart;
3267 ContextEx.cbXfer = pPktManip->u.ContextEx.cbXfer;
3268 ContextEx.cbXfered = 0;
3269
3270 aRespSegs[0].pvSeg = &RespHdr;
3271 aRespSegs[0].cbSeg = sizeof(RespHdr);
3272 aRespSegs[1].pvSeg = &ContextEx;
3273 aRespSegs[1].cbSeg = sizeof(ContextEx);
3274
3275 int rc = VINF_SUCCESS;
3276 uint32_t cbCtx = pThis->f32Bit ? sizeof(NtCtx.v32) : sizeof(NtCtx.v64);
3277 if (pThis->f32Bit)
3278 dbgcKdCtxQueryNtCtx32(pThis, pPktManip->Hdr.idCpu, &NtCtx.v32, NTCONTEXT32_F_FULL);
3279 else
3280 dbgcKdCtxQueryNtCtx64(pThis, pPktManip->Hdr.idCpu, &NtCtx.v64, NTCONTEXT64_F_FULL);
3281 if ( RT_SUCCESS(rc)
3282 && pPktManip->u.ContextEx.offStart < cbCtx)
3283 {
3284 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3285 ContextEx.cbXfered = RT_MIN(cbCtx - ContextEx.offStart, ContextEx.cbXfer);
3286
3287 aRespSegs[2].pvSeg = (uint8_t *)&NtCtx + ContextEx.offStart;
3288 aRespSegs[2].cbSeg = ContextEx.cbXfered;
3289 cSegs++;
3290 }
3291
3292 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3293 &aRespSegs[0], cSegs, true /*fAck*/);
3294}
3295
3296
3297/**
3298 * Processes a query memory 64 request.
3299 *
3300 * @returns VBox status code.
3301 * @param pThis The KD context.
3302 * @param pPktManip The manipulate packet request.
3303 */
3304static int dbgcKdCtxPktManipulate64QueryMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3305{
3306 KDPACKETMANIPULATEHDR RespHdr;
3307 KDPACKETMANIPULATE_QUERYMEMORY QueryMemory;
3308 RT_ZERO(RespHdr); RT_ZERO(QueryMemory);
3309
3310 RTSGSEG aRespSegs[2];
3311 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY;
3312 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3313 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3314 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3315
3316 /** @todo Need DBGF API to query protection and privilege level from guest page tables. */
3317 QueryMemory.u64GCPtr = pPktManip->u.QueryMemory.u64GCPtr;
3318 QueryMemory.u32AddrSpace = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_SPACE_KERNEL;
3319 QueryMemory.u32Flags = KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_READ
3320 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_WRITE
3321 | KD_PACKET_MANIPULATE64_QUERY_MEMORY_ADDR_F_EXEC;
3322
3323 aRespSegs[0].pvSeg = &RespHdr;
3324 aRespSegs[0].cbSeg = sizeof(RespHdr);
3325 aRespSegs[1].pvSeg = &QueryMemory;
3326 aRespSegs[1].cbSeg = sizeof(QueryMemory);
3327
3328 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3329 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3330}
3331
3332
3333/**
3334 * Processes a search memory 64 request.
3335 *
3336 * @returns VBox status code.
3337 * @param pThis The KD context.
3338 * @param pPktManip The manipulate packet request.
3339 */
3340static int dbgcKdCtxPktManipulate64SearchMemory(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3341{
3342 KDPACKETMANIPULATEHDR RespHdr;
3343 KDPACKETMANIPULATE_SEARCHMEMORY SearchMemory;
3344 RT_ZERO(RespHdr); RT_ZERO(SearchMemory);
3345
3346 RTSGSEG aRespSegs[2];
3347 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY;
3348 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3349 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3350 RespHdr.u32NtStatus = NTSTATUS_SUCCESS;
3351
3352 SearchMemory.u64GCPtr = pPktManip->u.SearchMemory.u64GCPtr;
3353 SearchMemory.cbSearch = pPktManip->u.SearchMemory.cbSearch;
3354 SearchMemory.cbPattern = pPktManip->u.SearchMemory.cbPattern;
3355
3356 /* Validate the pattern length and start searching. */
3357 if (pPktManip->u.SearchMemory.cbPattern < sizeof(pThis->abBody) - sizeof(*pPktManip))
3358 {
3359 DBGFADDRESS StartAddress;
3360 DBGFADDRESS HitAddress;
3361 VMCPUID idCpu = pPktManip->Hdr.idCpu;
3362 DBGFR3AddrFromFlat(pThis->Dbgc.pUVM, &StartAddress, pPktManip->u.SearchMemory.u64GCPtr);
3363
3364 /** @todo WindDbg sends CPU ID 32 sometimes, maybe that means continue search on last used CPU?. */
3365 if (idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM))
3366 idCpu = pThis->Dbgc.idCpu;
3367
3368 int rc = DBGFR3MemScan(pThis->Dbgc.pUVM, idCpu, &StartAddress, pPktManip->u.SearchMemory.cbSearch, 1,
3369 &pThis->abBody[sizeof(*pPktManip)], pPktManip->u.SearchMemory.cbPattern, &HitAddress);
3370 if (RT_SUCCESS(rc))
3371 SearchMemory.u64GCPtr = HitAddress.FlatPtr;
3372 else if (rc == VERR_DBGF_MEM_NOT_FOUND)
3373 RespHdr.u32NtStatus = NTSTATUS_NOT_FOUND;
3374 else
3375 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL;
3376 }
3377 else
3378 RespHdr.u32NtStatus = NTSTATUS_BUFFER_OVERFLOW;
3379
3380 aRespSegs[0].pvSeg = &RespHdr;
3381 aRespSegs[0].cbSeg = sizeof(RespHdr);
3382 aRespSegs[1].pvSeg = &SearchMemory;
3383 aRespSegs[1].cbSeg = sizeof(SearchMemory);
3384
3385 return dbgcKdCtxPktSendSg(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3386 &aRespSegs[0], RT_ELEMENTS(aRespSegs), true /*fAck*/);
3387}
3388
3389
3390/**
3391 * Processes a cause bugcheck 64 request.
3392 *
3393 * @returns VBox status code.
3394 * @param pThis The KD context.
3395 * @param pPktManip The manipulate packet request.
3396 *
3397 * @note We abuse this request to initiate a native VBox debugger command prompt from the remote end
3398 * (There is monitor/Rcmd equivalent like with GDB unfortunately).
3399 */
3400static int dbgcKdCtxPktManipulate64CauseBugCheck(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3401{
3402 RT_NOREF(pPktManip);
3403 pThis->fInVBoxDbg = true;
3404 return dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3405 512 /*cbResponseMax*/);
3406}
3407
3408
3409/**
3410 * Processes a switch processor request.
3411 *
3412 * @returns VBox status code.
3413 * @param pThis The KD context.
3414 * @param pPktManip The manipulate packet request.
3415 */
3416static int dbgcKdCtxPktManipulate64SwitchProcessor(PKDCTX pThis, PCKDPACKETMANIPULATE64 pPktManip)
3417{
3418 int rc = VINF_SUCCESS;
3419
3420 if (RT_UNLIKELY(pPktManip->Hdr.idCpu >= DBGFR3CpuGetCount(pThis->Dbgc.pUVM)))
3421 {
3422 KDPACKETMANIPULATEHDR RespHdr;
3423 RT_ZERO(RespHdr);
3424
3425 RespHdr.idReq = KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR;
3426 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3427 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3428 RespHdr.u32NtStatus = NTSTATUS_UNSUCCESSFUL; /** @todo Test this path. */
3429 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3430 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3431 }
3432 else
3433 {
3434 pThis->Dbgc.idCpu = pPktManip->Hdr.idCpu;
3435 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3436 }
3437
3438 return rc;
3439}
3440
3441
3442/**
3443 * Processes a manipulate packet.
3444 *
3445 * @returns VBox status code.
3446 * @param pThis The KD context.
3447 */
3448static int dbgcKdCtxPktManipulate64Process(PKDCTX pThis)
3449{
3450 int rc = VINF_SUCCESS;
3451 PCKDPACKETMANIPULATE64 pPktManip = (PCKDPACKETMANIPULATE64)&pThis->abBody[0];
3452
3453 switch (pPktManip->Hdr.idReq)
3454 {
3455 case KD_PACKET_MANIPULATE_REQ_GET_VERSION:
3456 {
3457 rc = dbgcKdCtxPktManipulate64GetVersion(pThis, pPktManip);
3458 break;
3459 }
3460 case KD_PACKET_MANIPULATE_REQ_READ_VIRT_MEM:
3461 case KD_PACKET_MANIPULATE_REQ_READ_PHYS_MEM:
3462 {
3463 rc = dbgcKdCtxPktManipulate64ReadMem(pThis, pPktManip);
3464 break;
3465 }
3466 case KD_PACKET_MANIPULATE_REQ_WRITE_VIRT_MEM:
3467 case KD_PACKET_MANIPULATE_REQ_WRITE_PHYS_MEM:
3468 {
3469 rc = dbgcKdCtxPktManipulate64WriteMem(pThis, pPktManip);
3470 break;
3471 }
3472 case KD_PACKET_MANIPULATE_REQ_CONTINUE:
3473 {
3474 rc = dbgcKdCtxPktManipulate64Continue(pThis, pPktManip);
3475 break;
3476 }
3477 case KD_PACKET_MANIPULATE_REQ_CONTINUE2:
3478 {
3479 rc = dbgcKdCtxPktManipulate64Continue2(pThis, pPktManip);
3480 break;
3481 }
3482 case KD_PACKET_MANIPULATE_REQ_SET_CONTEXT:
3483 {
3484 rc = dbgcKdCtxPktManipulate64SetContext(pThis, pPktManip);
3485 break;
3486 }
3487 case KD_PACKET_MANIPULATE_REQ_READ_CTRL_SPACE:
3488 {
3489 rc = dbgcKdCtxPktManipulate64ReadCtrlSpace(pThis, pPktManip);
3490 break;
3491 }
3492 case KD_PACKET_MANIPULATE_REQ_WRITE_CTRL_SPACE:
3493 {
3494 rc = dbgcKdCtxPktManipulate64WriteCtrlSpace(pThis, pPktManip);
3495 break;
3496 }
3497 case KD_PACKET_MANIPULATE_REQ_RESTORE_BKPT:
3498 {
3499 rc = dbgcKdCtxPktManipulate64RestoreBkpt(pThis, pPktManip);
3500 break;
3501 }
3502 case KD_PACKET_MANIPULATE_REQ_WRITE_BKPT:
3503 {
3504 rc = dbgcKdCtxPktManipulate64WriteBkpt(pThis, pPktManip);
3505 break;
3506 }
3507 case KD_PACKET_MANIPULATE_REQ_CLEAR_ALL_INTERNAL_BKPT:
3508 /* WinDbg doesn't seem to expect an answer apart from the ACK here. */
3509 break;
3510 case KD_PACKET_MANIPULATE_REQ_GET_CONTEXT_EX:
3511 {
3512 rc = dbgcKdCtxPktManipulate64GetContextEx(pThis, pPktManip);
3513 break;
3514 }
3515 case KD_PACKET_MANIPULATE_REQ_QUERY_MEMORY:
3516 {
3517 rc = dbgcKdCtxPktManipulate64QueryMemory(pThis, pPktManip);
3518 break;
3519 }
3520 case KD_PACKET_MANIPULATE_REQ_SEARCH_MEMORY:
3521 {
3522 rc = dbgcKdCtxPktManipulate64SearchMemory(pThis, pPktManip);
3523 break;
3524 }
3525 case KD_PACKET_MANIPULATE_REQ_CAUSE_BUGCHECK:
3526 {
3527 rc = dbgcKdCtxPktManipulate64CauseBugCheck(pThis, pPktManip);
3528 break;
3529 }
3530 case KD_PACKET_MANIPULATE_REQ_SWITCH_PROCESSOR:
3531 {
3532 rc = dbgcKdCtxPktManipulate64SwitchProcessor(pThis, pPktManip);
3533 break;
3534 }
3535 case KD_PACKET_MANIPULATE_REQ_REBOOT:
3536 {
3537 rc = VMR3Reset(pThis->Dbgc.pUVM); /* Doesn't expect an answer here. */
3538 if ( RT_SUCCESS(rc)
3539 && DBGFR3IsHalted(pThis->Dbgc.pUVM, VMCPUID_ALL))
3540 rc = DBGFR3Resume(pThis->Dbgc.pUVM, VMCPUID_ALL);
3541 break;
3542 }
3543 default:
3544 KDPACKETMANIPULATEHDR RespHdr;
3545 RT_ZERO(RespHdr);
3546
3547 RespHdr.idReq = pPktManip->Hdr.idReq;
3548 RespHdr.u16CpuLvl = pPktManip->Hdr.u16CpuLvl;
3549 RespHdr.idCpu = pPktManip->Hdr.idCpu;
3550 RespHdr.u32NtStatus = NTSTATUS_NOT_IMPLEMENTED;
3551 rc = dbgcKdCtxPktSend(pThis, KD_PACKET_HDR_SIGNATURE_DATA, KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE,
3552 &RespHdr, sizeof(RespHdr), true /*fAck*/);
3553 break;
3554 }
3555
3556 return rc;
3557}
3558
3559
3560/**
3561 * Tries to detect the guest OS running in the VM looking specifically for the Windows NT kind.
3562 *
3563 * @returns Nothing.
3564 * @param pThis The KD context.
3565 */
3566static void dbgcKdCtxDetectGstOs(PKDCTX pThis)
3567{
3568 pThis->pIfWinNt = NULL;
3569
3570 /* Try detecting a Windows NT guest. */
3571 char szName[64];
3572 int rc = DBGFR3OSDetect(pThis->Dbgc.pUVM, szName, sizeof(szName));
3573 if (RT_SUCCESS(rc))
3574 {
3575 pThis->pIfWinNt = (PDBGFOSIWINNT)DBGFR3OSQueryInterface(pThis->Dbgc.pUVM, DBGFOSINTERFACE_WINNT);
3576 if (pThis->pIfWinNt)
3577 LogRel(("DBGC/Kd: Detected Windows NT guest OS (%s)\n", &szName[0]));
3578 else
3579 LogRel(("DBGC/Kd: Detected guest OS is not of the Windows NT kind (%s)\n", &szName[0]));
3580 }
3581 else
3582 {
3583 LogRel(("DBGC/Kd: Unable to detect any guest operating system type, rc=%Rrc\n", rc));
3584 rc = VINF_SUCCESS; /* Try to continue nevertheless. */
3585 }
3586
3587 if (pThis->pIfWinNt)
3588 {
3589 rc = pThis->pIfWinNt->pfnQueryVersion(pThis->pIfWinNt, pThis->Dbgc.pUVM, VMMR3GetVTable(),
3590 NULL /*puVersMajor*/, NULL /*puVersMinor*/,
3591 NULL /*puBuildNumber*/, &pThis->f32Bit);
3592 AssertRC(rc);
3593 }
3594 else
3595 {
3596 /*
3597 * Try to detect bitness based on the current CPU mode which might fool us (32bit process running
3598 * inside of 64bit host).
3599 */
3600 CPUMMODE enmMode = DBGCCmdHlpGetCpuMode(&pThis->Dbgc.CmdHlp);
3601 if (enmMode == CPUMMODE_PROTECTED)
3602 pThis->f32Bit = true;
3603 else if (enmMode == CPUMMODE_LONG)
3604 pThis->f32Bit = false;
3605 else
3606 LogRel(("DBGC/Kd: Heh, trying to debug real mode code with WinDbg are we? Good luck with that...\n"));
3607 }
3608}
3609
3610
3611/**
3612 * Processes a fully received packet.
3613 *
3614 * @returns VBox status code.
3615 * @param pThis The KD context.
3616 */
3617static int dbgcKdCtxPktProcess(PKDCTX pThis)
3618{
3619 int rc = VINF_SUCCESS;
3620
3621 pThis->fBreakinRecv = false;
3622
3623 /* Verify checksum. */
3624 if (dbgcKdPktChkSumGen(&pThis->abBody[0], pThis->PktHdr.Fields.cbBody) == pThis->PktHdr.Fields.u32ChkSum)
3625 {
3626 /** @todo Check packet id. */
3627 if (pThis->PktHdr.Fields.u16SubType != KD_PACKET_HDR_SUB_TYPE_RESET)
3628 {
3629 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3630 rc = dbgcKdCtxPktSendAck(pThis);
3631 }
3632 if (RT_SUCCESS(rc))
3633 {
3634#ifdef LOG_ENABLED
3635 RTSGSEG Seg;
3636 Seg.pvSeg = &pThis->abBody[0];
3637 Seg.cbSeg = pThis->PktHdr.Fields.cbBody;
3638 dbgcKdPktDump(&pThis->PktHdr.Fields, &Seg, 1 /*cSegs*/, true /*fRx*/);
3639#endif
3640
3641 switch (pThis->PktHdr.Fields.u16SubType)
3642 {
3643 case KD_PACKET_HDR_SUB_TYPE_RESET:
3644 {
3645 dbgcKdCtxDetectGstOs(pThis);
3646
3647 pThis->idPktNext = 0;
3648 rc = dbgcKdCtxPktSendReset(pThis);
3649 if (RT_SUCCESS(rc))
3650 {
3651 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3652 if (rc == VWRN_DBGF_ALREADY_HALTED)
3653 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3654 }
3655 pThis->idPktNext = KD_PACKET_HDR_ID_RESET;
3656 break;
3657 }
3658 case KD_PACKET_HDR_SUB_TYPE_STATE_MANIPULATE:
3659 {
3660 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3661 rc = dbgcKdCtxPktManipulate64Process(pThis);
3662 break;
3663 }
3664 case KD_PACKET_HDR_SUB_TYPE_ACKNOWLEDGE:
3665 case KD_PACKET_HDR_SUB_TYPE_RESEND:
3666 {
3667 /* Don't do anything. */
3668 rc = VINF_SUCCESS;
3669 break;
3670 }
3671 case KD_PACKET_HDR_SUB_TYPE_DEBUG_IO:
3672 {
3673 if (pThis->fInVBoxDbg)
3674 {
3675 pThis->idPktNext = pThis->PktHdr.Fields.idPacket ^ 0x1;
3676 /* Get the string and execute it. */
3677 PCKDPACKETDEBUGIO pPktDbgIo = (PCKDPACKETDEBUGIO)&pThis->abBody[0];
3678 if ( pPktDbgIo->u32Type == KD_PACKET_DEBUG_IO_GET_STRING
3679 && pPktDbgIo->u.Prompt.cbReturn <= sizeof(pThis->abBody) - sizeof(*pPktDbgIo) - 1)
3680 {
3681 if (pPktDbgIo->u.Prompt.cbReturn)
3682 {
3683 /* Terminate return value. */
3684 pThis->abBody[sizeof(*pPktDbgIo) + pPktDbgIo->u.Prompt.cbReturn] = '\0';
3685
3686 const char *pszCmd = (const char *)&pThis->abBody[sizeof(*pPktDbgIo)];
3687 /* Filter out 'exit' which is handled here directly and exits the debug loop. */
3688 if (!strcmp(pszCmd, "exit"))
3689 pThis->fInVBoxDbg = false;
3690 else
3691 {
3692 rc = pThis->Dbgc.CmdHlp.pfnExec(&pThis->Dbgc.CmdHlp, pszCmd);
3693 if (RT_SUCCESS(rc))
3694 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3695 512 /*cbResponseMax*/);
3696 else
3697 LogRel(("DBGC/Kd: Executing command \"%s\" failed with rc=%Rrc\n", pszCmd, rc));
3698 }
3699 }
3700 else
3701 rc = dbgcKdCtxDebugIoGetStrSend(pThis, pThis->Dbgc.idCpu, "VBoxDbg>", sizeof("VBoxDbg>") - 1,
3702 512 /*cbResponseMax*/);
3703 }
3704 else
3705 LogRel(("DBGC/Kd: Received invalid DEBUG_IO packet from remote end, ignoring\n"));
3706 }
3707 else
3708 LogRel(("DBGC/Kd: Received out of band DEBUG_IO packet from remote end, ignoring\n"));
3709 break;
3710 }
3711 default:
3712 rc = VERR_NOT_IMPLEMENTED;
3713 }
3714 }
3715 }
3716 else
3717 {
3718 pThis->idPktNext = pThis->PktHdr.Fields.idPacket;
3719 rc = dbgcKdCtxPktSendResend(pThis);
3720 }
3721
3722 if (pThis->fBreakinRecv)
3723 {
3724 pThis->fBreakinRecv = false;
3725 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3726 if (rc == VWRN_DBGF_ALREADY_HALTED)
3727 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3728 }
3729
3730 /* Next packet. */
3731 dbgcKdCtxPktRecvReset(pThis);
3732 return rc;
3733}
3734
3735
3736/**
3737 * Processes the received data based on the current state.
3738 *
3739 * @returns VBox status code.
3740 * @param pThis The KD context.
3741 */
3742static int dbgcKdCtxRecvDataProcess(PKDCTX pThis)
3743{
3744 int rc = VINF_SUCCESS;
3745
3746 switch (pThis->enmState)
3747 {
3748 case KDRECVSTATE_PACKET_HDR_FIRST_BYTE:
3749 {
3750 /* Does it look like a valid packet start?. */
3751 if ( pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_DATA_BYTE
3752 || pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_CONTROL_BYTE)
3753 {
3754 pThis->pbRecv = &pThis->PktHdr.ab[1];
3755 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3756 pThis->enmState = KDRECVSTATE_PACKET_HDR_SECOND_BYTE;
3757 pThis->msRecvTimeout = DBGC_KD_RECV_TIMEOUT_MS;
3758 }
3759 else if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3760 {
3761 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3762 if (rc == VWRN_DBGF_ALREADY_HALTED)
3763 rc = dbgcKdCtxStateChangeSend(pThis, DBGFEVENT_HALT_DONE);
3764 dbgcKdCtxPktRecvReset(pThis);
3765 }
3766 /* else: Ignore and continue. */
3767 break;
3768 }
3769 case KDRECVSTATE_PACKET_HDR_SECOND_BYTE:
3770 {
3771 /*
3772 * If the first and second byte differ there might be a single breakin
3773 * packet byte received and this is actually the start of a new packet.
3774 */
3775 if (pThis->PktHdr.ab[0] != pThis->PktHdr.ab[1])
3776 {
3777 if (pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
3778 {
3779 /* Halt the VM and rearrange the packet receiving state machine. */
3780 LogFlow(("DbgKd: Halting VM!\n"));
3781
3782 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
3783 pThis->PktHdr.ab[0] = pThis->PktHdr.ab[1]; /* Overwrite the first byte with the new start. */
3784 pThis->pbRecv = &pThis->PktHdr.ab[1];
3785 pThis->cbRecvLeft = sizeof(pThis->PktHdr.ab[1]);
3786 }
3787 else
3788 rc = VERR_NET_PROTOCOL_ERROR; /* Refuse talking to the remote end any further. */
3789 }
3790 else
3791 {
3792 /* Normal packet receive continues with the rest of the header. */
3793 pThis->pbRecv = &pThis->PktHdr.ab[2];
3794 pThis->cbRecvLeft = sizeof(pThis->PktHdr.Fields) - 2;
3795 pThis->enmState = KDRECVSTATE_PACKET_HDR;
3796 }
3797 break;
3798 }
3799 case KDRECVSTATE_PACKET_HDR:
3800 {
3801 if ( dbgcKdPktHdrValidate(&pThis->PktHdr.Fields)
3802 && pThis->PktHdr.Fields.cbBody <= sizeof(pThis->abBody))
3803 {
3804 /* Start receiving the body. */
3805 if (pThis->PktHdr.Fields.cbBody)
3806 {
3807 pThis->pbRecv = &pThis->abBody[0];
3808 pThis->cbRecvLeft = pThis->PktHdr.Fields.cbBody;
3809 pThis->enmState = KDRECVSTATE_PACKET_BODY;
3810 }
3811 else /* No body means no trailer byte it looks like. */
3812 rc = dbgcKdCtxPktProcess(pThis);
3813 }
3814 else
3815 rc = VERR_NET_PROTOCOL_ERROR;
3816 break;
3817 }
3818 case KDRECVSTATE_PACKET_BODY:
3819 {
3820 pThis->enmState = KDRECVSTATE_PACKET_TRAILER;
3821 pThis->bTrailer = 0;
3822 pThis->pbRecv = &pThis->bTrailer;
3823 pThis->cbRecvLeft = sizeof(pThis->bTrailer);
3824 break;
3825 }
3826 case KDRECVSTATE_PACKET_TRAILER:
3827 {
3828 if (pThis->bTrailer == KD_PACKET_TRAILING_BYTE)
3829 rc = dbgcKdCtxPktProcess(pThis);
3830 else
3831 rc = VERR_NET_PROTOCOL_ERROR;
3832 break;
3833 }
3834 default:
3835 AssertMsgFailed(("Invalid receive state %d\n", pThis->enmState));
3836 }
3837
3838 return rc;
3839}
3840
3841
3842/**
3843 * Receive data and processes complete packets.
3844 *
3845 * @returns Status code.
3846 * @param pThis The KD context.
3847 */
3848static int dbgcKdCtxRecv(PKDCTX pThis)
3849{
3850 int rc = VINF_SUCCESS;
3851
3852 LogFlowFunc(("pThis=%p{.cbRecvLeft=%zu}\n", pThis, pThis->cbRecvLeft));
3853
3854 if (pThis->cbRecvLeft)
3855 {
3856 size_t cbRead = 0;
3857 rc = pThis->Dbgc.pIo->pfnRead(pThis->Dbgc.pIo, pThis->pbRecv, pThis->cbRecvLeft, &cbRead);
3858 if (RT_SUCCESS(rc))
3859 {
3860 pThis->tsRecvLast = RTTimeMilliTS();
3861 pThis->cbRecvLeft -= cbRead;
3862 pThis->pbRecv += cbRead;
3863 if (!pThis->cbRecvLeft)
3864 rc = dbgcKdCtxRecvDataProcess(pThis);
3865 }
3866 }
3867
3868 LogFlowFunc(("returns rc=%Rrc\n", rc));
3869 return rc;
3870}
3871
3872
3873/**
3874 * Processes debugger events.
3875 *
3876 * @returns VBox status code.
3877 * @param pThis The KD context data.
3878 * @param pEvent Pointer to event data.
3879 */
3880static int dbgcKdCtxProcessEvent(PKDCTX pThis, PCDBGFEVENT pEvent)
3881{
3882 /*
3883 * Process the event.
3884 */
3885 PDBGC pDbgc = &pThis->Dbgc;
3886 pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
3887 pThis->Dbgc.iArg = 0;
3888 int rc = VINF_SUCCESS;
3889 VMCPUID idCpuOld = pDbgc->idCpu;
3890 pDbgc->idCpu = pEvent->idCpu;
3891 switch (pEvent->enmType)
3892 {
3893 /*
3894 * The first part is events we have initiated with commands.
3895 */
3896 case DBGFEVENT_HALT_DONE:
3897 {
3898 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3899 break;
3900 }
3901
3902 /*
3903 * The second part is events which can occur at any time.
3904 */
3905 case DBGFEVENT_FATAL_ERROR:
3906 {
3907 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
3908 dbgcGetEventCtx(pEvent->enmCtx));
3909 if (RT_SUCCESS(rc))
3910 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3911 break;
3912 }
3913
3914 case DBGFEVENT_BREAKPOINT:
3915 case DBGFEVENT_BREAKPOINT_IO:
3916 case DBGFEVENT_BREAKPOINT_MMIO:
3917 case DBGFEVENT_BREAKPOINT_HYPER:
3918 {
3919 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.hBp);
3920 switch (rc)
3921 {
3922 case VERR_DBGC_BP_NOT_FOUND:
3923 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
3924 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
3925 break;
3926
3927 case VINF_DBGC_BP_NO_COMMAND:
3928 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
3929 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
3930 break;
3931
3932 case VINF_BUFFER_OVERFLOW:
3933 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
3934 pEvent->u.Bp.hBp, dbgcGetEventCtx(pEvent->enmCtx));
3935 break;
3936
3937 default:
3938 break;
3939 }
3940 if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pUVM, VMCPUID_ALL))
3941 {
3942 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3943
3944 /* Set the resume flag to ignore the breakpoint when resuming execution. */
3945 if ( RT_SUCCESS(rc)
3946 && pEvent->enmType == DBGFEVENT_BREAKPOINT)
3947 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r eflags.rf = 1");
3948 }
3949
3950 /* Figure out the breakpoint and set the triggered flag for emulation of DR6. */
3951 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
3952 {
3953 if (pThis->aHwBp[i].hDbgfBp == pEvent->u.Bp.hBp)
3954 {
3955 pThis->aHwBp[i].fTriggered = true;
3956 break;
3957 }
3958 }
3959
3960 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3961 break;
3962 }
3963
3964 case DBGFEVENT_STEPPED:
3965 case DBGFEVENT_STEPPED_HYPER:
3966 {
3967 pThis->fSingleStepped = true; /* For emulation of DR6. */
3968 rc = dbgcKdCtxStateChangeSend(pThis, pEvent->enmType);
3969 break;
3970 }
3971
3972 case DBGFEVENT_ASSERTION_HYPER:
3973 {
3974 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3975 "\ndbgf event: Hypervisor Assertion! (%s)\n"
3976 "%s"
3977 "%s"
3978 "\n",
3979 dbgcGetEventCtx(pEvent->enmCtx),
3980 pEvent->u.Assert.pszMsg1,
3981 pEvent->u.Assert.pszMsg2);
3982 if (RT_SUCCESS(rc))
3983 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
3984 break;
3985 }
3986
3987 case DBGFEVENT_DEV_STOP:
3988 {
3989 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
3990 "\n"
3991 "dbgf event: DBGFSTOP (%s)\n"
3992 "File: %s\n"
3993 "Line: %d\n"
3994 "Function: %s\n",
3995 dbgcGetEventCtx(pEvent->enmCtx),
3996 pEvent->u.Src.pszFile,
3997 pEvent->u.Src.uLine,
3998 pEvent->u.Src.pszFunction);
3999 if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
4000 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
4001 "Message: %s\n",
4002 pEvent->u.Src.pszMessage);
4003 if (RT_SUCCESS(rc))
4004 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
4005 break;
4006 }
4007
4008
4009 case DBGFEVENT_INVALID_COMMAND:
4010 {
4011 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
4012 break;
4013 }
4014
4015 case DBGFEVENT_POWERING_OFF:
4016 {
4017 pThis->Dbgc.fReady = false;
4018 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, false);
4019 rc = VERR_GENERAL_FAILURE;
4020 break;
4021 }
4022
4023 default:
4024 {
4025 /*
4026 * Probably a generic event. Look it up to find its name.
4027 */
4028 PCDBGCSXEVT pEvtDesc = dbgcEventLookup(pEvent->enmType);
4029 if (pEvtDesc)
4030 {
4031 if (pEvtDesc->enmKind == kDbgcSxEventKind_Interrupt)
4032 {
4033 Assert(pEvtDesc->pszDesc);
4034 Assert(pEvent->u.Generic.cArgs == 1);
4035 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s no %#llx! (%s)\n",
4036 pEvtDesc->pszDesc, pEvent->u.Generic.auArgs[0], pEvtDesc->pszName);
4037 }
4038 else if (pEvtDesc->fFlags & DBGCSXEVT_F_BUGCHECK)
4039 {
4040 Assert(pEvent->u.Generic.cArgs >= 5);
4041 char szDetails[512];
4042 DBGFR3FormatBugCheck(pDbgc->pUVM, szDetails, sizeof(szDetails), pEvent->u.Generic.auArgs[0],
4043 pEvent->u.Generic.auArgs[1], pEvent->u.Generic.auArgs[2],
4044 pEvent->u.Generic.auArgs[3], pEvent->u.Generic.auArgs[4]);
4045 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s %s%s!\n%s", pEvtDesc->pszName,
4046 pEvtDesc->pszDesc ? "- " : "", pEvtDesc->pszDesc ? pEvtDesc->pszDesc : "",
4047 szDetails);
4048 }
4049 else if ( (pEvtDesc->fFlags & DBGCSXEVT_F_TAKE_ARG)
4050 || pEvent->u.Generic.cArgs > 1
4051 || ( pEvent->u.Generic.cArgs == 1
4052 && pEvent->u.Generic.auArgs[0] != 0))
4053 {
4054 if (pEvtDesc->pszDesc)
4055 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!",
4056 pEvtDesc->pszName, pEvtDesc->pszDesc);
4057 else
4058 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!", pEvtDesc->pszName);
4059 if (pEvent->u.Generic.cArgs <= 1)
4060 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " arg=%#llx\n", pEvent->u.Generic.auArgs[0]);
4061 else
4062 {
4063 for (uint32_t i = 0; i < pEvent->u.Generic.cArgs; i++)
4064 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " args[%u]=%#llx", i, pEvent->u.Generic.auArgs[i]);
4065 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
4066 }
4067 }
4068 else
4069 {
4070 if (pEvtDesc->pszDesc)
4071 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s - %s!\n",
4072 pEvtDesc->pszName, pEvtDesc->pszDesc);
4073 else
4074 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: %s!\n", pEvtDesc->pszName);
4075 }
4076 }
4077 else
4078 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
4079 break;
4080 }
4081 }
4082
4083 pDbgc->idCpu = idCpuOld;
4084 return rc;
4085}
4086
4087
4088/**
4089 * Handle a receive timeout.
4090 *
4091 * @returns VBox status code.
4092 * @param pThis Pointer to the KD context.
4093 */
4094static int dbgcKdCtxRecvTimeout(PKDCTX pThis)
4095{
4096 int rc = VINF_SUCCESS;
4097
4098 LogFlowFunc(("pThis=%p\n", pThis));
4099
4100 /*
4101 * If a single breakin packet byte was received but the header is otherwise incomplete
4102 * the VM is halted and a state change will be sent in the event processing loop.
4103 */
4104 if ( pThis->enmState == KDRECVSTATE_PACKET_HDR_SECOND_BYTE
4105 && pThis->PktHdr.ab[0] == KD_PACKET_HDR_SIGNATURE_BREAKIN_BYTE)
4106 {
4107 LogFlow(("DbgKd: Halting VM!\n"));
4108 rc = DBGFR3Halt(pThis->Dbgc.pUVM, VMCPUID_ALL);
4109 }
4110 else /* Send a reset packet */ /** @todo Figure out the semantics in this case exactly. */
4111 rc = dbgcKdCtxPktSendReset(pThis);
4112
4113 dbgcKdCtxPktRecvReset(pThis);
4114
4115 LogFlowFunc(("rc=%Rrc\n", rc));
4116 return rc;
4117}
4118
4119
4120/**
4121 * @copydoc DBGC::pfnOutput
4122 */
4123static DECLCALLBACK(int) dbgcKdOutput(void *pvUser, const char *pachChars, size_t cbChars)
4124{
4125 PKDCTX pThis = (PKDCTX)pvUser;
4126
4127 return dbgcKdCtxDebugIoStrSend(pThis, pThis->Dbgc.idCpu, pachChars, cbChars);
4128}
4129
4130
4131/**
4132 * Run the debugger console.
4133 *
4134 * @returns VBox status code.
4135 * @param pThis Pointer to the KD context.
4136 */
4137int dbgcKdRun(PKDCTX pThis)
4138{
4139 /*
4140 * We're ready for commands now.
4141 */
4142 pThis->Dbgc.fReady = true;
4143 pThis->Dbgc.pIo->pfnSetReady(pThis->Dbgc.pIo, true);
4144
4145 /*
4146 * Main Debugger Loop.
4147 *
4148 * This loop will either block on waiting for input or on waiting on
4149 * debug events. If we're forwarding the log we cannot wait for long
4150 * before we must flush the log.
4151 */
4152 int rc;
4153 for (;;)
4154 {
4155 rc = VERR_SEM_OUT_OF_TURN;
4156 if (pThis->Dbgc.pUVM)
4157 rc = DBGFR3QueryWaitable(pThis->Dbgc.pUVM);
4158
4159 if (RT_SUCCESS(rc))
4160 {
4161 /*
4162 * Wait for a debug event.
4163 */
4164 DBGFEVENT Evt;
4165 rc = DBGFR3EventWait(pThis->Dbgc.pUVM, 32, &Evt);
4166 if (RT_SUCCESS(rc))
4167 {
4168 rc = dbgcKdCtxProcessEvent(pThis, &Evt);
4169 if (RT_FAILURE(rc))
4170 break;
4171 }
4172 else if (rc != VERR_TIMEOUT)
4173 break;
4174
4175 /*
4176 * Check for input.
4177 */
4178 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 0))
4179 {
4180 rc = dbgcKdCtxRecv(pThis);
4181 if (RT_FAILURE(rc))
4182 break;
4183 }
4184 }
4185 else if (rc == VERR_SEM_OUT_OF_TURN)
4186 {
4187 /*
4188 * Wait for input.
4189 */
4190 if (pThis->Dbgc.pIo->pfnInput(pThis->Dbgc.pIo, 1000))
4191 {
4192 rc = dbgcKdCtxRecv(pThis);
4193 if (RT_FAILURE(rc))
4194 break;
4195 }
4196 else if ( pThis->msRecvTimeout != RT_INDEFINITE_WAIT
4197 && (RTTimeMilliTS() - pThis->tsRecvLast >= pThis->msRecvTimeout))
4198 rc = dbgcKdCtxRecvTimeout(pThis);
4199 }
4200 else
4201 break;
4202 }
4203
4204 return rc;
4205}
4206
4207
4208/**
4209 * Creates a KD context instance with the given backend.
4210 *
4211 * @returns VBox status code.
4212 * @param ppKdCtx Where to store the pointer to the KD stub context instance on success.
4213 * @param pIo Pointer to the I/O callback table.
4214 * @param fFlags Flags controlling the behavior.
4215 */
4216static int dbgcKdCtxCreate(PPKDCTX ppKdCtx, PCDBGCIO pIo, unsigned fFlags)
4217{
4218 /*
4219 * Validate input.
4220 */
4221 AssertPtrReturn(pIo, VERR_INVALID_POINTER);
4222 AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
4223
4224 /*
4225 * Allocate and initialize.
4226 */
4227 PKDCTX pThis = (PKDCTX)RTMemAllocZ(sizeof(*pThis));
4228 if (!pThis)
4229 return VERR_NO_MEMORY;
4230
4231 dbgcInitCmdHlp(&pThis->Dbgc);
4232 /*
4233 * This is compied from the native debug console (will be used for monitor commands)
4234 * in DBGCConsole.cpp. Try to keep both functions in sync.
4235 */
4236 pThis->Dbgc.pIo = pIo;
4237 pThis->Dbgc.pfnOutput = dbgcKdOutput;
4238 pThis->Dbgc.pvOutputUser = pThis;
4239 pThis->Dbgc.pVM = NULL;
4240 pThis->Dbgc.pUVM = NULL;
4241 pThis->Dbgc.idCpu = 0;
4242 pThis->Dbgc.hDbgAs = DBGF_AS_GLOBAL;
4243 pThis->Dbgc.pszEmulation = "CodeView/WinDbg";
4244 pThis->Dbgc.paEmulationCmds = &g_aCmdsCodeView[0];
4245 pThis->Dbgc.cEmulationCmds = g_cCmdsCodeView;
4246 pThis->Dbgc.paEmulationFuncs = &g_aFuncsCodeView[0];
4247 pThis->Dbgc.cEmulationFuncs = g_cFuncsCodeView;
4248 //pThis->Dbgc.fLog = false;
4249 pThis->Dbgc.fRegTerse = true;
4250 pThis->Dbgc.fStepTraceRegs = true;
4251 //pThis->Dbgc.cPagingHierarchyDumps = 0;
4252 //pThis->Dbgc.DisasmPos = {0};
4253 //pThis->Dbgc.SourcePos = {0};
4254 //pThis->Dbgc.DumpPos = {0};
4255 pThis->Dbgc.pLastPos = &pThis->Dbgc.DisasmPos;
4256 //pThis->Dbgc.cbDumpElement = 0;
4257 //pThis->Dbgc.cVars = 0;
4258 //pThis->Dbgc.paVars = NULL;
4259 //pThis->Dbgc.pPlugInHead = NULL;
4260 //pThis->Dbgc.pFirstBp = NULL;
4261 //pThis->Dbgc.abSearch = {0};
4262 //pThis->Dbgc.cbSearch = 0;
4263 pThis->Dbgc.cbSearchUnit = 1;
4264 pThis->Dbgc.cMaxSearchHits = 1;
4265 //pThis->Dbgc.SearchAddr = {0};
4266 //pThis->Dbgc.cbSearchRange = 0;
4267
4268 //pThis->Dbgc.uInputZero = 0;
4269 //pThis->Dbgc.iRead = 0;
4270 //pThis->Dbgc.iWrite = 0;
4271 //pThis->Dbgc.cInputLines = 0;
4272 //pThis->Dbgc.fInputOverflow = false;
4273 pThis->Dbgc.fReady = true;
4274 pThis->Dbgc.pszScratch = &pThis->Dbgc.achScratch[0];
4275 //pThis->Dbgc.iArg = 0;
4276 //pThis->Dbgc.rcOutput = 0;
4277 //pThis->Dbgc.rcCmd = 0;
4278
4279 //pThis->Dbgc.pszHistoryFile = NULL;
4280 //pThis->Dbgc.pszGlobalInitScript = NULL;
4281 //pThis->Dbgc.pszLocalInitScript = NULL;
4282
4283 dbgcEvalInit();
4284
4285 pThis->fBreakinRecv = false;
4286 pThis->fInVBoxDbg = false;
4287 pThis->idPktNext = KD_PACKET_HDR_ID_INITIAL;
4288 pThis->pIfWinNt = NULL;
4289 pThis->f32Bit = false;
4290 dbgcKdCtxPktRecvReset(pThis);
4291
4292 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aHwBp); i++)
4293 {
4294 PKDCTXHWBP pBp = &pThis->aHwBp[i];
4295 pBp->hDbgfBp = NIL_DBGFBP;
4296 }
4297
4298 dbgcKdCtxHwBpReset(pThis);
4299
4300 *ppKdCtx = pThis;
4301 return VINF_SUCCESS;
4302}
4303
4304
4305/**
4306 * Destroys the given KD context.
4307 *
4308 * @returns nothing.
4309 * @param pThis The KD context to destroy.
4310 */
4311static void dbgcKdCtxDestroy(PKDCTX pThis)
4312{
4313 AssertPtr(pThis);
4314
4315 pThis->pIfWinNt = NULL;
4316
4317 /* Detach from the VM. */
4318 if (pThis->Dbgc.pUVM)
4319 DBGFR3Detach(pThis->Dbgc.pUVM);
4320
4321 /* Free config strings. */
4322 RTStrFree(pThis->Dbgc.pszGlobalInitScript);
4323 pThis->Dbgc.pszGlobalInitScript = NULL;
4324 RTStrFree(pThis->Dbgc.pszLocalInitScript);
4325 pThis->Dbgc.pszLocalInitScript = NULL;
4326 RTStrFree(pThis->Dbgc.pszHistoryFile);
4327 pThis->Dbgc.pszHistoryFile = NULL;
4328
4329 /* Finally, free the instance memory. */
4330 RTMemFree(pThis);
4331}
4332
4333
4334DECL_HIDDEN_CALLBACK(int) dbgcKdStubRunloop(PUVM pUVM, PCDBGCIO pIo, unsigned fFlags)
4335{
4336 /*
4337 * Validate input.
4338 */
4339 AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
4340 PVM pVM = NULL;
4341 if (pUVM)
4342 {
4343 pVM = VMR3GetVM(pUVM);
4344 AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
4345 }
4346
4347 /*
4348 * Allocate and initialize instance data
4349 */
4350 PKDCTX pThis;
4351 int rc = dbgcKdCtxCreate(&pThis, pIo, fFlags);
4352 if (RT_FAILURE(rc))
4353 return rc;
4354 if (!HMR3IsEnabled(pUVM) && !NEMR3IsEnabled(pUVM))
4355 pThis->Dbgc.hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;
4356
4357 /*
4358 * Attach to the specified VM.
4359 */
4360 if (RT_SUCCESS(rc) && pUVM)
4361 {
4362 rc = DBGFR3Attach(pUVM);
4363 if (RT_SUCCESS(rc))
4364 {
4365 pThis->Dbgc.pVM = pVM;
4366 pThis->Dbgc.pUVM = pUVM;
4367 pThis->Dbgc.idCpu = 0;
4368 }
4369 else
4370 rc = pThis->Dbgc.CmdHlp.pfnVBoxError(&pThis->Dbgc.CmdHlp, rc, "When trying to attach to VM %p\n", pThis->Dbgc.pVM);
4371 }
4372
4373 /*
4374 * Load plugins.
4375 */
4376 if (RT_SUCCESS(rc))
4377 {
4378 if (pVM)
4379 DBGFR3PlugInLoadAll(pThis->Dbgc.pUVM);
4380 dbgcEventInit(&pThis->Dbgc);
4381
4382 /*
4383 * Run the debugger main loop.
4384 */
4385 rc = dbgcKdRun(pThis);
4386 dbgcEventTerm(&pThis->Dbgc);
4387 }
4388
4389 /*
4390 * Cleanup console debugger session.
4391 */
4392 dbgcKdCtxDestroy(pThis);
4393 return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
4394}
4395
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