VirtualBox

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

Last change on this file since 67973 was 67973, checked in by vboxsync, 8 years ago

bugref:8877: VirtualKD: fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/* $Id: VirtualKD.cpp 67973 2017-07-14 13:47:20Z 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-2016 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.215389.xyz. 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 size_t 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;
121 cbReply = pThis->pKDClient->OnRequest(pThis->abCmdBody, cbData, &pReply);
122
123 if (!pReply)
124 cbReply = 0;
125
126 VKDREPLYHDR ReplyHeader;
127 ReplyHeader.cbData = cbReply + 2;
128 ReplyHeader.chOne = '1';
129 ReplyHeader.chSpace = ' ';
130 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)u32, &ReplyHeader, sizeof(ReplyHeader));
131 if (!RT_SUCCESS(rc))
132 return VINF_SUCCESS;
133 if (cbReply)
134 {
135 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)(u32 + sizeof(ReplyHeader)), pReply, cbReply);
136 if (!RT_SUCCESS(rc))
137 return VINF_SUCCESS;
138 }
139 }
140 else if (Port == 0x5658)
141 {
142 if (u32 == 0x564D5868)
143 pThis->fOpenChannelDetected = true;
144 else
145 pThis->fOpenChannelDetected = false;
146 }
147
148 return VINF_SUCCESS;
149}
150
151
152/**
153 * @interface_method_impl{PDMDEVREG,pfnDestruct}
154 */
155static DECLCALLBACK(int) vkdDestruct(PPDMDEVINS pDevIns)
156{
157 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
158 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
159
160 delete pThis->pKDClient;
161 if (pThis->hLib != NIL_RTLDRMOD)
162 RTLdrClose(pThis->hLib);
163
164 return VINF_SUCCESS;
165}
166
167
168/**
169 * @interface_method_impl{PDMDEVREG,pfnConstruct}
170 */
171static DECLCALLBACK(int) vkdConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
172{
173 RT_NOREF(iInstance);
174 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
175 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
176
177 pThis->fOpenChannelDetected = false;
178 pThis->fChannelDetectSuccessful = false;
179 pThis->hLib = NIL_RTLDRMOD;
180 pThis->pKDClient = NULL;
181
182 if (!CFGMR3AreValuesValid(pCfg,
183 "Path\0"))
184 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
185
186 /* This device is a bit unusual, after this point it will not fail to be
187 * constructed, but there will be a warning and it will not work. */
188
189 char szPath[RTPATH_MAX] = "";
190 CFGMR3QueryString(pCfg, "Path", szPath, sizeof(szPath));
191
192 RTPathAppend(szPath, sizeof(szPath), HC_ARCH_BITS == 64 ? "kdclient64.dll" : "kdclient.dll");
193 int rc = RTLdrLoad(szPath, &pThis->hLib);
194 if (RT_FAILURE(rc))
195 {
196 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_LOAD",
197 N_("Failed to load VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
198 return VINF_SUCCESS;
199 }
200
201 PFNCreateVBoxKDClientEx pfnInit;
202 rc = RTLdrGetSymbol(pThis->hLib, "CreateVBoxKDClientEx", (void **)&pfnInit);
203 if (RT_FAILURE(rc))
204 {
205 RTLdrClose(pThis->hLib);
206 pThis->hLib = NIL_RTLDRMOD;
207 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_SYMBOL",
208 N_("Failed to find entry point for VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
209 return VINF_SUCCESS;
210 }
211
212 pThis->pKDClient = pfnInit(IKDClient_InterfaceVersion);
213 if (!pThis->pKDClient)
214 {
215 RTLdrClose(pThis->hLib);
216 pThis->hLib = NIL_RTLDRMOD;
217 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_INIT",
218 N_("Failed to initialize VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
219 return VINF_SUCCESS;
220 }
221
222 PDMDevHlpIOPortRegister(pDevIns, 0x5658, 2, NULL, vkdPortWrite, vkdPortRead, NULL, NULL, "VirtualKD");
223
224 return VINF_SUCCESS;
225}
226
227
228/**
229 * The device registration structure.
230 */
231const PDMDEVREG g_DeviceVirtualKD =
232{
233 /* u32Version */
234 PDM_DEVREG_VERSION,
235 /* szName */
236 "VirtualKD",
237 /* szRCMod */
238 "",
239 /* szR0Mod */
240 "",
241 /* pszDescription */
242 "Provides fast debugging interface when debugging Windows kernel",
243 /* fFlags */
244 PDM_DEVREG_FLAGS_DEFAULT_BITS,
245 /* fClass */
246 PDM_DEVREG_CLASS_MISC,
247 /* cMaxInstances */
248 1,
249 /* cbInstance */
250 sizeof(VIRTUALKD),
251 /* pfnConstruct */
252 vkdConstruct,
253 /* pfnDestruct */
254 vkdDestruct,
255 /* pfnRelocate */
256 NULL,
257 /* pfnIOCtl */
258 NULL,
259 /* pfnPowerOn */
260 NULL,
261 /* pfnReset */
262 NULL,
263 /* pfnSuspend */
264 NULL,
265 /* pfnResume */
266 NULL,
267 /* pfnAttach */
268 NULL,
269 /* pfnDetach */
270 NULL,
271 /* pfnQueryInterface */
272 NULL,
273 /* pfnInitComplete */
274 NULL,
275 /* pfnPowerOff */
276 NULL,
277 /* pfnSoftReset */
278 NULL,
279 /* u32VersionEnd */
280 PDM_DEVREG_VERSION
281};
282
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette