VirtualBox

source: vbox/trunk/src/VBox/Devices/Misc/VirtualKD.cpp@ 76553

Last change on this file since 76553 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/* $Id: VirtualKD.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VirtualKD - Device stub/loader for fast Windows kernel-mode debugging.
4 *
5 * Contributed by: Ivan Shcherbakov
6 * Heavily modified after the contribution.
7 */
8
9/*
10 * Copyright (C) 2010-2019 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 */
20
21
22/*********************************************************************************************************************************
23* Header Files *
24*********************************************************************************************************************************/
25#define LOG_GROUP LOG_GROUP_DEV // LOG_GROUP_DEV_VIRTUALKD
26#include <VBox/vmm/pdmdev.h>
27#include <VBox/log.h>
28#include <iprt/assert.h>
29#include <iprt/path.h>
30
31#include "VBoxDD.h"
32
33
34/*********************************************************************************************************************************
35* Defined Constants And Macros *
36*********************************************************************************************************************************/
37
38#define IKDClient_InterfaceVersion 3
39
40
41/*********************************************************************************************************************************
42* Structures and Typedefs *
43*********************************************************************************************************************************/
44
45typedef struct VKDREQUESTHDR
46{
47 unsigned cbData;
48 unsigned cbReplyMax;
49} VKDREQUESTHDR;
50
51#pragma pack(1)
52typedef struct VKDREPLYHDR
53{
54 unsigned cbData;
55 char chOne;
56 char chSpace;
57} VKDREPLYHDR;
58#pragma pack()
59AssertCompileSize(VKDREPLYHDR, 6);
60
61class IKDClient
62{
63public:
64 virtual unsigned OnRequest(const char *pRequestIncludingRpcHeader, unsigned RequestSizeWithRpcHeader, char **ppReply)=0;
65 virtual ~IKDClient() {}
66};
67
68typedef IKDClient *(*PFNCreateVBoxKDClientEx)(unsigned version);
69
70typedef struct VIRTUALKD
71{
72 bool fOpenChannelDetected;
73 bool fChannelDetectSuccessful;
74 RTLDRMOD hLib;
75 IKDClient *pKDClient;
76 char abCmdBody[_256K];
77} VIRTUALKD;
78
79
80/*********************************************************************************************************************************
81* Internal Functions *
82*********************************************************************************************************************************/
83
84static DECLCALLBACK(int) vkdPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
85{
86 RT_NOREF(pvUser, Port, cb);
87 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
88
89 if (pThis->fOpenChannelDetected)
90 {
91 *pu32 = RT_MAKE_U32_FROM_U8('V', 'B', 'O', 'X'); /* 'XOBV', checked in VMWRPC.H */
92 pThis->fOpenChannelDetected = false;
93 pThis->fChannelDetectSuccessful = true;
94 }
95 else
96 *pu32 = UINT32_MAX;
97
98 return VINF_SUCCESS;
99}
100
101static DECLCALLBACK(int) vkdPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
102{
103 RT_NOREF(pvUser, cb);
104 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
105
106 if (Port == 0x5659)
107 {
108 VKDREQUESTHDR RequestHeader = {0, };
109 int rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, &RequestHeader, sizeof(RequestHeader));
110 if ( !RT_SUCCESS(rc)
111 || !RequestHeader.cbData)
112 return VINF_SUCCESS;
113
114 unsigned cbData = RT_MIN(RequestHeader.cbData, sizeof(pThis->abCmdBody));
115 rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)(u32 + sizeof(RequestHeader)), pThis->abCmdBody, cbData);
116 if (!RT_SUCCESS(rc))
117 return VINF_SUCCESS;
118
119 char *pReply = NULL;
120 unsigned cbReply = pThis->pKDClient->OnRequest(pThis->abCmdBody, cbData, &pReply);
121
122 if (!pReply)
123 cbReply = 0;
124
125 VKDREPLYHDR ReplyHeader;
126 ReplyHeader.cbData = cbReply + 2;
127 ReplyHeader.chOne = '1';
128 ReplyHeader.chSpace = ' ';
129 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)u32, &ReplyHeader, sizeof(ReplyHeader));
130 if (!RT_SUCCESS(rc))
131 return VINF_SUCCESS;
132 if (cbReply)
133 {
134 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)(u32 + sizeof(ReplyHeader)), pReply, cbReply);
135 if (!RT_SUCCESS(rc))
136 return VINF_SUCCESS;
137 }
138 }
139 else if (Port == 0x5658)
140 {
141 if (u32 == 0x564D5868)
142 pThis->fOpenChannelDetected = true;
143 else
144 pThis->fOpenChannelDetected = false;
145 }
146
147 return VINF_SUCCESS;
148}
149
150
151/**
152 * @interface_method_impl{PDMDEVREG,pfnDestruct}
153 */
154static DECLCALLBACK(int) vkdDestruct(PPDMDEVINS pDevIns)
155{
156 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
157 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
158
159 delete pThis->pKDClient;
160 if (pThis->hLib != NIL_RTLDRMOD)
161 RTLdrClose(pThis->hLib);
162
163 return VINF_SUCCESS;
164}
165
166
167/**
168 * @interface_method_impl{PDMDEVREG,pfnConstruct}
169 */
170static DECLCALLBACK(int) vkdConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
171{
172 RT_NOREF(iInstance);
173 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
174 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
175
176 pThis->fOpenChannelDetected = false;
177 pThis->fChannelDetectSuccessful = false;
178 pThis->hLib = NIL_RTLDRMOD;
179 pThis->pKDClient = NULL;
180
181 if (!CFGMR3AreValuesValid(pCfg,
182 "Path\0"))
183 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
184
185 /* This device is a bit unusual, after this point it will not fail to be
186 * constructed, but there will be a warning and it will not work. */
187
188 char szPath[RTPATH_MAX] = "";
189 CFGMR3QueryString(pCfg, "Path", szPath, sizeof(szPath));
190
191 RTPathAppend(szPath, sizeof(szPath), HC_ARCH_BITS == 64 ? "kdclient64.dll" : "kdclient.dll");
192 int rc = RTLdrLoad(szPath, &pThis->hLib);
193 if (RT_FAILURE(rc))
194 {
195 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_LOAD",
196 N_("Failed to load VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
197 return VINF_SUCCESS;
198 }
199
200 PFNCreateVBoxKDClientEx pfnInit;
201 rc = RTLdrGetSymbol(pThis->hLib, "CreateVBoxKDClientEx", (void **)&pfnInit);
202 if (RT_FAILURE(rc))
203 {
204 RTLdrClose(pThis->hLib);
205 pThis->hLib = NIL_RTLDRMOD;
206 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_SYMBOL",
207 N_("Failed to find entry point for VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
208 return VINF_SUCCESS;
209 }
210
211 pThis->pKDClient = pfnInit(IKDClient_InterfaceVersion);
212 if (!pThis->pKDClient)
213 {
214 RTLdrClose(pThis->hLib);
215 pThis->hLib = NIL_RTLDRMOD;
216 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_INIT",
217 N_("Failed to initialize VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
218 return VINF_SUCCESS;
219 }
220
221 return PDMDevHlpIOPortRegister(pDevIns, 0x5658, 2, NULL, vkdPortWrite, vkdPortRead, NULL, NULL, "VirtualKD");
222}
223
224
225/**
226 * The device registration structure.
227 */
228const PDMDEVREG g_DeviceVirtualKD =
229{
230 /* u32Version */
231 PDM_DEVREG_VERSION,
232 /* szName */
233 "VirtualKD",
234 /* szRCMod */
235 "",
236 /* szR0Mod */
237 "",
238 /* pszDescription */
239 "Provides fast debugging interface when debugging Windows kernel",
240 /* fFlags */
241 PDM_DEVREG_FLAGS_DEFAULT_BITS,
242 /* fClass */
243 PDM_DEVREG_CLASS_MISC,
244 /* cMaxInstances */
245 1,
246 /* cbInstance */
247 sizeof(VIRTUALKD),
248 /* pfnConstruct */
249 vkdConstruct,
250 /* pfnDestruct */
251 vkdDestruct,
252 /* pfnRelocate */
253 NULL,
254 /* pfnIOCtl */
255 NULL,
256 /* pfnPowerOn */
257 NULL,
258 /* pfnReset */
259 NULL,
260 /* pfnSuspend */
261 NULL,
262 /* pfnResume */
263 NULL,
264 /* pfnAttach */
265 NULL,
266 /* pfnDetach */
267 NULL,
268 /* pfnQueryInterface */
269 NULL,
270 /* pfnInitComplete */
271 NULL,
272 /* pfnPowerOff */
273 NULL,
274 /* pfnSoftReset */
275 NULL,
276 /* u32VersionEnd */
277 PDM_DEVREG_VERSION
278};
279
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