VirtualBox

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

Last change on this file since 61497 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/* $Id: VirtualKD.cpp 57358 2015-08-14 15:16:38Z 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-2015 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_VIRTUALKD
26#include <VBox/vmm/pdmdev.h>
27#include <iprt/assert.h>
28#include <iprt/path.h>
29
30#include "VBoxDD.h"
31
32
33/*********************************************************************************************************************************
34* Defined Constants And Macros *
35*********************************************************************************************************************************/
36
37#define IKDClient_InterfaceVersion 3
38
39
40/*********************************************************************************************************************************
41* Structures and Typedefs *
42*********************************************************************************************************************************/
43
44typedef struct VKDREQUESTHDR
45{
46 unsigned cbData;
47 unsigned cbReplyMax;
48} VKDREQUESTHDR;
49
50#pragma pack(1)
51typedef struct VKDREPLYHDR
52{
53 unsigned cbData;
54 char chOne;
55 char chSpace;
56} VKDREPLYHDR;
57#pragma pack()
58AssertCompileSize(VKDREPLYHDR, 6);
59
60class IKDClient
61{
62public:
63 virtual unsigned OnRequest(const char *pRequestIncludingRpcHeader, unsigned RequestSizeWithRpcHeader, char **ppReply)=0;
64 virtual ~IKDClient() {}
65};
66
67typedef IKDClient *(*PFNCreateVBoxKDClientEx)(unsigned version);
68
69typedef struct VIRTUALKD
70{
71 bool fOpenChannelDetected;
72 bool fChannelDetectSuccessful;
73 RTLDRMOD hLib;
74 IKDClient *pKDClient;
75 char abCmdBody[262144];
76} VIRTUALKD;
77
78
79/*********************************************************************************************************************************
80* Internal Functions *
81*********************************************************************************************************************************/
82
83static DECLCALLBACK(int) vkdPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
84{
85 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
86
87 if (pThis->fOpenChannelDetected)
88 {
89 *pu32 = RT_MAKE_U32_FROM_U8('V', 'B', 'O', 'X'); /* 'XOBV', checked in VMWRPC.H */
90 pThis->fOpenChannelDetected = false;
91 pThis->fChannelDetectSuccessful = true;
92 }
93 else
94 *pu32 = -1;
95
96 return VINF_SUCCESS;
97}
98
99static DECLCALLBACK(int) vkdPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
100{
101 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
102
103 if (Port == 0x5659)
104 {
105 VKDREQUESTHDR RequestHeader = {0, };
106 int rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, &RequestHeader, sizeof(RequestHeader));
107 if (!RT_SUCCESS(rc) || !RequestHeader.cbData)
108 return VINF_SUCCESS;
109 rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)(u32 + sizeof(RequestHeader)), pThis->abCmdBody, RequestHeader.cbData);
110 if (!RT_SUCCESS(rc))
111 return VINF_SUCCESS;
112
113 char *pReply = NULL;
114 unsigned cbReply;
115 cbReply = pThis->pKDClient->OnRequest(pThis->abCmdBody,
116 RequestHeader.cbData,
117 &pReply);
118
119 if (!pReply)
120 cbReply = 0;
121
122 VKDREPLYHDR ReplyHeader;
123 ReplyHeader.cbData = cbReply + 2;
124 ReplyHeader.chOne = '1';
125 ReplyHeader.chSpace = ' ';
126 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)u32, &ReplyHeader, sizeof(ReplyHeader));
127 if (!RT_SUCCESS(rc))
128 return VINF_SUCCESS;
129 if (cbReply)
130 {
131 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)(u32 + sizeof(ReplyHeader)), pReply, cbReply);
132 if (!RT_SUCCESS(rc))
133 return VINF_SUCCESS;
134 }
135 }
136 else if (Port == 0x5658)
137 {
138 if (u32 == 0x564D5868)
139 pThis->fOpenChannelDetected = true;
140 else
141 pThis->fOpenChannelDetected = false;
142 }
143
144 return VINF_SUCCESS;
145}
146
147
148/**
149 * @interface_method_impl{PDMDEVREG,pfnConstruct}
150 */
151static DECLCALLBACK(int) vkdConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
152{
153 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
154
155 pThis->fOpenChannelDetected = false;
156 pThis->fChannelDetectSuccessful = false;
157 pThis->hLib = NIL_RTLDRMOD;
158 pThis->pKDClient = NULL;
159
160 if (!CFGMR3AreValuesValid(pCfg,
161 "Path\0"))
162 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
163
164 /* This device is a bit unusual, after this point it will not fail to be
165 * constructed, but there will be a warning and it will not work. */
166
167 char szPath[RTPATH_MAX] = "";
168 CFGMR3QueryString(pCfg, "Path", szPath, sizeof(szPath));
169
170 RTPathAppend(szPath, sizeof(szPath),
171#if HC_ARCH_BITS == 64
172 "kdclient64.dll"
173#else
174 "kdclient.dll"
175#endif
176 );
177 int rc = RTLdrLoad(szPath, &pThis->hLib);
178 if (RT_FAILURE(rc))
179 {
180 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_LOAD",
181 N_("Failed to load VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
182 return VINF_SUCCESS;
183 }
184
185 PFNCreateVBoxKDClientEx pfnInit;
186 rc = RTLdrGetSymbol(pThis->hLib, "CreateVBoxKDClientEx", (void **)&pfnInit);
187 if (RT_FAILURE(rc))
188 {
189 RTLdrClose(pThis->hLib);
190 pThis->hLib = NIL_RTLDRMOD;
191 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_SYMBOL",
192 N_("Failed to find entry point for VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
193 return VINF_SUCCESS;
194 }
195
196 pThis->pKDClient = pfnInit(IKDClient_InterfaceVersion);
197 if (!pThis->pKDClient)
198 {
199 RTLdrClose(pThis->hLib);
200 pThis->hLib = NIL_RTLDRMOD;
201 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_INIT",
202 N_("Failed to initialize VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
203 return VINF_SUCCESS;
204 }
205
206 PDMDevHlpIOPortRegister(pDevIns, 0x5658, 2, NULL, vkdPortWrite, vkdPortRead, NULL, NULL, "VirtualKD");
207
208 return VINF_SUCCESS;
209}
210
211/**
212 * @interface_method_impl{PDMDEVREG,pfnDestruct}
213 */
214static DECLCALLBACK(int) vkdDestruct(PPDMDEVINS pDevIns)
215{
216 VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
217
218 delete pThis->pKDClient;
219 if (pThis->hLib != NIL_RTLDRMOD)
220 RTLdrClose(pThis->hLib);
221
222 return VINF_SUCCESS;
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};
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