VirtualBox

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

Last change on this file since 52474 was 52474, checked in by vboxsync, 11 years ago

Devices/Misc/VirtualKD: fix code breakage due to padding

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