VirtualBox

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

Last change on this file since 11964 was 8800, checked in by vboxsync, 17 years ago

Started digging into the solaris guest kernel. Added DBGFR3MemRead.

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