VirtualBox

source: vbox/trunk/src/VBox/VMM/DBGFOS.cpp@ 13782

Last change on this file since 13782 was 13782, checked in by vboxsync, 16 years ago

More SMP groundwork.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.1 KB
Line 
1/* $Id: DBGFOS.cpp 13782 2008-11-04 12:16:30Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Guest OS Diggers.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DBGF
27#include <VBox/dbgf.h>
28#include <VBox/mm.h>
29#include "DBGFInternal.h"
30#include <VBox/vm.h>
31#include <VBox/err.h>
32
33#include <VBox/log.h>
34#include <iprt/thread.h>
35#include <iprt/assert.h>
36
37
38
39/**
40 * EMT worker function for DBGFR3OSRegister.
41 *
42 * @returns VBox status code.
43 * @param pVM Pointer to the shared VM structure.
44 * @param pReg The registration structure.
45 */
46static DECLCALLBACK(int) dbgfR3OSRegister(PVM pVM, PDBGFOSREG pReg)
47{
48 /* more validations. */
49 PDBGFOS pOS;
50 for (pOS = pVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext)
51 if (!strcmp(pOS->pReg->szName, pReg->szName))
52 {
53 Log(("dbgfR3OSRegister: %s -> VERR_ALREADY_LOADED\n", pReg->szName));
54 return VERR_ALREADY_LOADED;
55 }
56
57 /*
58 * Allocate a new structure, call the constructor and link it into the list.
59 */
60 pOS = (PDBGFOS)MMR3HeapAllocZ(pVM, MM_TAG_DBGF_OS, RT_OFFSETOF(DBGFOS, abData[pReg->cbData]));
61 AssertReturn(pOS, VERR_NO_MEMORY);
62 pOS->pReg = pReg;
63
64 int rc = pOS->pReg->pfnConstruct(pVM, pOS->abData);
65 if (RT_SUCCESS(rc))
66 {
67 pOS->pNext = pVM->dbgf.s.pOSHead;
68 pVM->dbgf.s.pOSHead = pOS;
69 }
70 else
71 {
72 if (pOS->pReg->pfnDestruct)
73 pOS->pReg->pfnDestruct(pVM, pOS->abData);
74 MMR3HeapFree(pOS);
75 }
76
77 return VINF_SUCCESS;
78}
79
80
81/**
82 * Registers a guest OS digger.
83 *
84 * This will instantiate an instance of the digger and add it
85 * to the list for us in the next call to DBGFR3OSDetect().
86 *
87 * @returns VBox status code.
88 * @param pVM Pointer to the shared VM structure.
89 * @param pReg The registration structure.
90 * @thread Any.
91 */
92VMMR3DECL(int) DBGFR3OSRegister(PVM pVM, PCDBGFOSREG pReg)
93{
94 /*
95 * Validate intput.
96 */
97 AssertPtrReturn(pReg, VERR_INVALID_POINTER);
98 AssertReturn(pReg->u32Magic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
99 AssertReturn(pReg->u32EndMagic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
100 AssertReturn(!pReg->fFlags, VERR_INVALID_PARAMETER);
101 AssertReturn(pReg->cbData < _2G, VERR_INVALID_PARAMETER);
102 AssertReturn(pReg->szName[0], VERR_INVALID_NAME);
103 AssertReturn(memchr(&pReg->szName[0], '\0', sizeof(pReg->szName)), VERR_INVALID_NAME);
104 AssertPtrReturn(pReg->pfnConstruct, VERR_INVALID_POINTER);
105 AssertPtrNullReturn(pReg->pfnDestruct, VERR_INVALID_POINTER);
106 AssertPtrReturn(pReg->pfnProbe, VERR_INVALID_POINTER);
107 AssertPtrReturn(pReg->pfnInit, VERR_INVALID_POINTER);
108 AssertPtrReturn(pReg->pfnRefresh, VERR_INVALID_POINTER);
109 AssertPtrReturn(pReg->pfnTerm, VERR_INVALID_POINTER);
110 AssertPtrReturn(pReg->pfnQueryVersion, VERR_INVALID_POINTER);
111 AssertPtrReturn(pReg->pfnQueryInterface, VERR_INVALID_POINTER);
112
113 /*
114 * Pass it on to the EMT.
115 */
116 PVMREQ pReq;
117 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3OSRegister, 2, pVM, pReg);
118 if (RT_SUCCESS(rc))
119 rc = pReq->iStatus;
120 VMR3ReqFree(pReq);
121
122 return rc;
123}
124
125
126/**
127 * Internal cleanup routine called by DBGFR3Term().
128 *
129 * @param pVM Pointer to the shared VM structure.
130 */
131void dbgfR3OSTerm(PVM pVM)
132{
133 /*
134 * Terminate the current one.
135 */
136 if (pVM->dbgf.s.pCurOS)
137 {
138 pVM->dbgf.s.pCurOS->pReg->pfnTerm(pVM, pVM->dbgf.s.pCurOS->abData);
139 pVM->dbgf.s.pCurOS = NULL;
140 }
141
142 /*
143 * Destroy all the instances.
144 */
145 while (pVM->dbgf.s.pOSHead)
146 {
147 PDBGFOS pOS = pVM->dbgf.s.pOSHead;
148 pVM->dbgf.s.pOSHead = pOS->pNext;
149 if (pOS->pReg->pfnDestruct)
150 pOS->pReg->pfnDestruct(pVM, pOS->abData);
151 MMR3HeapFree(pOS);
152 }
153}
154
155
156/**
157 * EMT worker function for DBGFR3OSDetect.
158 *
159 * @returns VBox status code.
160 * @retval VINF_SUCCESS if successfully detected.
161 * @retval VINF_DBGF_OS_NOT_DETCTED if we cannot figure it out.
162 *
163 * @param pVM Pointer to the shared VM structure.
164 * @param pszName Where to store the OS name. Empty string if not detected.
165 * @param cchName Size of the buffer.
166 */
167static DECLCALLBACK(int) dbgfR3OSDetect(PVM pVM, char *pszName, size_t cchName)
168{
169 /*
170 * Cycle thru the detection routines.
171 */
172 PDBGFOS const pOldOS = pVM->dbgf.s.pCurOS;
173 pVM->dbgf.s.pCurOS = NULL;
174
175 for (PDBGFOS pNewOS = pVM->dbgf.s.pOSHead; pNewOS; pNewOS = pNewOS->pNext)
176 if (pNewOS->pReg->pfnProbe(pVM, pNewOS->abData))
177 {
178 int rc;
179 pVM->dbgf.s.pCurOS = pNewOS;
180 if (pOldOS == pNewOS)
181 rc = pNewOS->pReg->pfnRefresh(pVM, pNewOS->abData);
182 else
183 {
184 if (pOldOS)
185 pOldOS->pReg->pfnTerm(pVM, pNewOS->abData);
186 rc = pNewOS->pReg->pfnInit(pVM, pNewOS->abData);
187 }
188 if (pszName && cchName)
189 strncat(pszName, pNewOS->pReg->szName, cchName);
190 return rc;
191 }
192
193 /* not found */
194 if (pOldOS)
195 pOldOS->pReg->pfnTerm(pVM, pOldOS->abData);
196 return VINF_DBGF_OS_NOT_DETCTED;
197}
198
199
200/**
201 * Detectes the guest OS and try dig out symbols and useful stuff.
202 *
203 * When called the 2nd time, symbols will be updated that if the OS
204 * is the same.
205 *
206 * @returns VBox status code.
207 * @retval VINF_SUCCESS if successfully detected.
208 * @retval VINF_DBGF_OS_NOT_DETCTED if we cannot figure it out.
209 *
210 * @param pVM Pointer to the shared VM structure.
211 * @param pszName Where to store the OS name. Empty string if not detected.
212 * @param cchName Size of the buffer.
213 * @thread Any.
214 */
215VMMR3DECL(int) DBGFR3OSDetect(PVM pVM, char *pszName, size_t cchName)
216{
217 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
218 if (pszName && cchName)
219 *pszName = '\0';
220
221 /*
222 * Pass it on to the EMT.
223 */
224 PVMREQ pReq;
225 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3OSDetect, 3, pVM, pszName, cchName);
226 if (RT_SUCCESS(rc))
227 rc = pReq->iStatus;
228 VMR3ReqFree(pReq);
229
230 return rc;
231}
232
233
234/**
235 * EMT worker function for DBGFR3OSQueryNameAndVersion
236 *
237 * @returns VBox status code.
238 * @param pVM Pointer to the shared VM structure.
239 * @param pszName Where to store the OS name. Optional.
240 * @param cchName The size of the name buffer.
241 * @param pszVersion Where to store the version string. Optional.
242 * @param cchVersion The size of the version buffer.
243 */
244static DECLCALLBACK(int) dbgfR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
245{
246 /*
247 * Any known OS?
248 */
249 if (pVM->dbgf.s.pCurOS)
250 {
251 int rc = VINF_SUCCESS;
252 if (pszName && cchName)
253 {
254 size_t cch = strlen(pVM->dbgf.s.pCurOS->pReg->szName);
255 if (cchName > cch)
256 memcpy(pszName, pVM->dbgf.s.pCurOS->pReg->szName, cch + 1);
257 else
258 {
259 memcpy(pszName, pVM->dbgf.s.pCurOS->pReg->szName, cchName - 1);
260 pszName[cchName - 1] = '\0';
261 rc = VINF_BUFFER_OVERFLOW;
262 }
263 }
264
265 if (pszVersion && cchVersion)
266 {
267 int rc2 = pVM->dbgf.s.pCurOS->pReg->pfnQueryVersion(pVM, pVM->dbgf.s.pCurOS->abData, pszVersion, cchVersion);
268 if (RT_FAILURE(rc2) || rc == VINF_SUCCESS)
269 rc = rc2;
270 }
271 return rc;
272 }
273
274 return VERR_DBGF_OS_NOT_DETCTED;
275}
276
277
278/**
279 * Queries the name and/or version string for the guest OS.
280 *
281 * It goes without saying that this querying is done using the current
282 * guest OS digger and not additions or user configuration.
283 *
284 * @returns VBox status code.
285 * @param pVM Pointer to the shared VM structure.
286 * @param pszName Where to store the OS name. Optional.
287 * @param cchName The size of the name buffer.
288 * @param pszVersion Where to store the version string. Optional.
289 * @param cchVersion The size of the version buffer.
290 * @thread Any.
291 */
292VMMR3DECL(int) DBGFR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
293{
294 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
295 AssertPtrNullReturn(pszVersion, VERR_INVALID_POINTER);
296
297 /*
298 * Initialize the output up front.
299 */
300 if (pszName && cchName)
301 *pszName = '\0';
302 if (pszVersion && cchVersion)
303 *pszVersion = '\0';
304
305 /*
306 * Pass it on to the EMT.
307 */
308 PVMREQ pReq;
309 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3OSQueryNameAndVersion,
310 5, pVM, pszName, cchName, pszVersion, cchVersion);
311 if (RT_SUCCESS(rc))
312 rc = pReq->iStatus;
313 VMR3ReqFree(pReq);
314
315 return rc;
316}
317
318
319/**
320 * EMT worker for DBGFR3OSQueryInterface.
321 *
322 * @param pVM Pointer to the shared VM structure.
323 * @param enmIf The interface identifier.
324 * @param ppvIf Where to store the interface pointer on success.
325 */
326static DECLCALLBACK(void) dbgfR3OSQueryInterface(PVM pVM, DBGFOSINTERFACE enmIf, void **ppvIf)
327{
328 if (pVM->dbgf.s.pCurOS)
329 {
330 *ppvIf = pVM->dbgf.s.pCurOS->pReg->pfnQueryInterface(pVM, pVM->dbgf.s.pCurOS->abData, enmIf);
331 if (*ppvIf)
332 {
333 /** @todo Create EMT wrapper for the returned interface once we've defined one...
334 * Just keep a list of wrapper together with the OS instance. */
335 }
336 }
337 else
338 *ppvIf = NULL;
339}
340
341
342/**
343 * Query an optional digger interface.
344 *
345 * @returns Pointer to the digger interface on success, NULL if the interfaces isn't
346 * available or no active guest OS digger.
347 * @param pVM Pointer to the shared VM structure.
348 * @param enmIf The interface identifier.
349 * @thread Any.
350 */
351VMMR3DECL(void *) DBGFR3OSQueryInterface(PVM pVM, DBGFOSINTERFACE enmIf)
352{
353 AssertMsgReturn(enmIf > DBGFOSINTERFACE_INVALID && enmIf < DBGFOSINTERFACE_END, ("%d\n", enmIf), NULL);
354
355 /*
356 * Pass it on to the EMT.
357 */
358 void *pvIf = NULL;
359 PVMREQ pReq;
360 VMR3ReqCallVoidU(pVM->pUVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)dbgfR3OSQueryInterface, 3, pVM, enmIf, &pvIf);
361 VMR3ReqFree(pReq);
362
363 return pvIf;
364}
365
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