VirtualBox

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

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

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.6 KB
Line 
1/* $Id: DBGFOS.cpp 62478 2016-07-22 18:29:06Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Guest OS Diggers.
4 */
5
6/*
7 * Copyright (C) 2008-2016 Oracle Corporation
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
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGF
23#include <VBox/vmm/dbgf.h>
24#include <VBox/vmm/mm.h>
25#include "DBGFInternal.h"
26#include <VBox/vmm/uvm.h>
27#include <VBox/err.h>
28#include <VBox/log.h>
29
30#include <iprt/assert.h>
31#include <iprt/thread.h>
32#include <iprt/param.h>
33
34
35/*********************************************************************************************************************************
36* Defined Constants And Macros *
37*********************************************************************************************************************************/
38
39#define DBGF_OS_READ_LOCK(pUVM) \
40 do { int rcLock = RTCritSectRwEnterShared(&pUVM->dbgf.s.CritSect); AssertRC(rcLock); } while (0)
41#define DBGF_OS_READ_UNLOCK(pUVM) \
42 do { int rcLock = RTCritSectRwLeaveShared(&pUVM->dbgf.s.CritSect); AssertRC(rcLock); } while (0)
43
44#define DBGF_OS_WRITE_LOCK(pUVM) \
45 do { int rcLock = RTCritSectRwEnterExcl(&pUVM->dbgf.s.CritSect); AssertRC(rcLock); } while (0)
46#define DBGF_OS_WRITE_UNLOCK(pUVM) \
47 do { int rcLock = RTCritSectRwLeaveExcl(&pUVM->dbgf.s.CritSect); AssertRC(rcLock); } while (0)
48
49
50/*********************************************************************************************************************************
51* Structures and Typedefs *
52*********************************************************************************************************************************/
53/**
54 * EMT interface wrappers.
55 *
56 * The diggers expects to be called on an EMT. To avoid the debugger+Main having
57 *
58 * Since the user (debugger/Main) shouldn't be calling directly into the digger code, but rather
59 */
60typedef struct DBGFOSEMTWRAPPER
61{
62 /** Pointer to the next list entry. */
63 struct DBGFOSEMTWRAPPER *pNext;
64 /** The interface type. */
65 DBGFOSINTERFACE enmIf;
66 /** The digger interface pointer. */
67 union
68 {
69 /** Generic void pointer. */
70 void *pv;
71 /** DBGFOSINTERFACE_DMESG.*/
72 PDBGFOSIDMESG pDmesg;
73 } uDigger;
74 /** The user mode VM handle. */
75 PUVM pUVM;
76 /** The wrapper interface union (consult enmIf). */
77 union
78 {
79 /** DBGFOSINTERFACE_DMESG.*/
80 DBGFOSIDMESG Dmesg;
81 } uWrapper;
82} DBGFOSEMTWRAPPER;
83/** Pointer to an EMT interface wrapper. */
84typedef DBGFOSEMTWRAPPER *PDBGFOSEMTWRAPPER;
85
86
87/**
88 * Internal init routine called by DBGFR3Init().
89 *
90 * @returns VBox status code.
91 * @param pUVM The user mode VM handle.
92 */
93int dbgfR3OSInit(PUVM pUVM)
94{
95 return VINF_SUCCESS;
96}
97
98
99/**
100 * Internal cleanup routine called by DBGFR3Term().
101 *
102 * @param pUVM The user mode VM handle.
103 */
104void dbgfR3OSTerm(PUVM pUVM)
105{
106 DBGF_OS_WRITE_LOCK(pUVM);
107
108 /*
109 * Terminate the current one.
110 */
111 if (pUVM->dbgf.s.pCurOS)
112 {
113 pUVM->dbgf.s.pCurOS->pReg->pfnTerm(pUVM, pUVM->dbgf.s.pCurOS->abData);
114 pUVM->dbgf.s.pCurOS = NULL;
115 }
116
117 /*
118 * Destroy all the instances.
119 */
120 while (pUVM->dbgf.s.pOSHead)
121 {
122 PDBGFOS pOS = pUVM->dbgf.s.pOSHead;
123 pUVM->dbgf.s.pOSHead = pOS->pNext;
124 if (pOS->pReg->pfnDestruct)
125 pOS->pReg->pfnDestruct(pUVM, pOS->abData);
126
127 PDBGFOSEMTWRAPPER pFree = pOS->pWrapperHead;
128 while ((pFree = pOS->pWrapperHead) != NULL)
129 {
130 pOS->pWrapperHead = pFree->pNext;
131 pFree->pNext = NULL;
132 MMR3HeapFree(pFree);
133 }
134
135 MMR3HeapFree(pOS);
136 }
137
138 DBGF_OS_WRITE_UNLOCK(pUVM);
139}
140
141
142/**
143 * EMT worker function for DBGFR3OSRegister.
144 *
145 * @returns VBox status code.
146 * @param pUVM The user mode VM handle.
147 * @param pReg The registration structure.
148 */
149static DECLCALLBACK(int) dbgfR3OSRegister(PUVM pUVM, PDBGFOSREG pReg)
150{
151 /* more validations. */
152 DBGF_OS_READ_LOCK(pUVM);
153 PDBGFOS pOS;
154 for (pOS = pUVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext)
155 if (!strcmp(pOS->pReg->szName, pReg->szName))
156 {
157 DBGF_OS_READ_UNLOCK(pUVM);
158 Log(("dbgfR3OSRegister: %s -> VERR_ALREADY_LOADED\n", pReg->szName));
159 return VERR_ALREADY_LOADED;
160 }
161 DBGF_OS_READ_UNLOCK(pUVM);
162
163 /*
164 * Allocate a new structure, call the constructor and link it into the list.
165 */
166 pOS = (PDBGFOS)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_OS, RT_OFFSETOF(DBGFOS, abData[pReg->cbData]));
167 AssertReturn(pOS, VERR_NO_MEMORY);
168 pOS->pReg = pReg;
169
170 int rc = pOS->pReg->pfnConstruct(pUVM, pOS->abData);
171 if (RT_SUCCESS(rc))
172 {
173 DBGF_OS_WRITE_LOCK(pUVM);
174 pOS->pNext = pUVM->dbgf.s.pOSHead;
175 pUVM->dbgf.s.pOSHead = pOS;
176 DBGF_OS_WRITE_UNLOCK(pUVM);
177 }
178 else
179 {
180 if (pOS->pReg->pfnDestruct)
181 pOS->pReg->pfnDestruct(pUVM, pOS->abData);
182 MMR3HeapFree(pOS);
183 }
184
185 return VINF_SUCCESS;
186}
187
188
189/**
190 * Registers a guest OS digger.
191 *
192 * This will instantiate an instance of the digger and add it
193 * to the list for us in the next call to DBGFR3OSDetect().
194 *
195 * @returns VBox status code.
196 * @param pUVM The user mode VM handle.
197 * @param pReg The registration structure.
198 * @thread Any.
199 */
200VMMR3DECL(int) DBGFR3OSRegister(PUVM pUVM, PCDBGFOSREG pReg)
201{
202 /*
203 * Validate intput.
204 */
205 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
206
207 AssertPtrReturn(pReg, VERR_INVALID_POINTER);
208 AssertReturn(pReg->u32Magic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
209 AssertReturn(pReg->u32EndMagic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
210 AssertReturn(!pReg->fFlags, VERR_INVALID_PARAMETER);
211 AssertReturn(pReg->cbData < _2G, VERR_INVALID_PARAMETER);
212 AssertReturn(pReg->szName[0], VERR_INVALID_NAME);
213 AssertReturn(RTStrEnd(&pReg->szName[0], sizeof(pReg->szName)), VERR_INVALID_NAME);
214 AssertPtrReturn(pReg->pfnConstruct, VERR_INVALID_POINTER);
215 AssertPtrNullReturn(pReg->pfnDestruct, VERR_INVALID_POINTER);
216 AssertPtrReturn(pReg->pfnProbe, VERR_INVALID_POINTER);
217 AssertPtrReturn(pReg->pfnInit, VERR_INVALID_POINTER);
218 AssertPtrReturn(pReg->pfnRefresh, VERR_INVALID_POINTER);
219 AssertPtrReturn(pReg->pfnTerm, VERR_INVALID_POINTER);
220 AssertPtrReturn(pReg->pfnQueryVersion, VERR_INVALID_POINTER);
221 AssertPtrReturn(pReg->pfnQueryInterface, VERR_INVALID_POINTER);
222
223 /*
224 * Pass it on to EMT(0).
225 */
226 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSRegister, 2, pUVM, pReg);
227}
228
229
230/**
231 * EMT worker function for DBGFR3OSDeregister.
232 *
233 * @returns VBox status code.
234 * @param pUVM The user mode VM handle.
235 * @param pReg The registration structure.
236 */
237static DECLCALLBACK(int) dbgfR3OSDeregister(PUVM pUVM, PDBGFOSREG pReg)
238{
239 /*
240 * Unlink it.
241 */
242 bool fWasCurOS = false;
243 PDBGFOS pOSPrev = NULL;
244 PDBGFOS pOS;
245 DBGF_OS_WRITE_LOCK(pUVM);
246 for (pOS = pUVM->dbgf.s.pOSHead; pOS; pOSPrev = pOS, pOS = pOS->pNext)
247 if (pOS->pReg == pReg)
248 {
249 if (pOSPrev)
250 pOSPrev->pNext = pOS->pNext;
251 else
252 pUVM->dbgf.s.pOSHead = pOS->pNext;
253 if (pUVM->dbgf.s.pCurOS == pOS)
254 {
255 pUVM->dbgf.s.pCurOS = NULL;
256 fWasCurOS = true;
257 }
258 break;
259 }
260 DBGF_OS_WRITE_UNLOCK(pUVM);
261 if (!pOS)
262 {
263 Log(("DBGFR3OSDeregister: %s -> VERR_NOT_FOUND\n", pReg->szName));
264 return VERR_NOT_FOUND;
265 }
266
267 /*
268 * Terminate it if it was the current OS, then invoke the
269 * destructor and clean up.
270 */
271 if (fWasCurOS)
272 pOS->pReg->pfnTerm(pUVM, pOS->abData);
273 if (pOS->pReg->pfnDestruct)
274 pOS->pReg->pfnDestruct(pUVM, pOS->abData);
275
276 PDBGFOSEMTWRAPPER pFree = pOS->pWrapperHead;
277 while ((pFree = pOS->pWrapperHead) != NULL)
278 {
279 pOS->pWrapperHead = pFree->pNext;
280 pFree->pNext = NULL;
281 MMR3HeapFree(pFree);
282 }
283
284 MMR3HeapFree(pOS);
285
286 return VINF_SUCCESS;
287}
288
289
290/**
291 * Deregisters a guest OS digger previously registered by DBGFR3OSRegister.
292 *
293 * @returns VBox status code.
294 *
295 * @param pUVM The user mode VM handle.
296 * @param pReg The registration structure.
297 * @thread Any.
298 */
299VMMR3DECL(int) DBGFR3OSDeregister(PUVM pUVM, PCDBGFOSREG pReg)
300{
301 /*
302 * Validate input.
303 */
304 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
305 AssertPtrReturn(pReg, VERR_INVALID_POINTER);
306 AssertReturn(pReg->u32Magic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
307 AssertReturn(pReg->u32EndMagic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC);
308 AssertReturn(RTStrEnd(&pReg->szName[0], sizeof(pReg->szName)), VERR_INVALID_NAME);
309
310 DBGF_OS_READ_LOCK(pUVM);
311 PDBGFOS pOS;
312 for (pOS = pUVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext)
313 if (pOS->pReg == pReg)
314 break;
315 DBGF_OS_READ_UNLOCK(pUVM);
316
317 if (!pOS)
318 {
319 Log(("DBGFR3OSDeregister: %s -> VERR_NOT_FOUND\n", pReg->szName));
320 return VERR_NOT_FOUND;
321 }
322
323 /*
324 * Pass it on to EMT(0).
325 */
326 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSDeregister, 2, pUVM, pReg);
327}
328
329
330/**
331 * EMT worker function for DBGFR3OSDetect.
332 *
333 * @returns VBox status code.
334 * @retval VINF_SUCCESS if successfully detected.
335 * @retval VINF_DBGF_OS_NOT_DETCTED if we cannot figure it out.
336 *
337 * @param pUVM The user mode VM handle.
338 * @param pszName Where to store the OS name. Empty string if not detected.
339 * @param cchName Size of the buffer.
340 */
341static DECLCALLBACK(int) dbgfR3OSDetect(PUVM pUVM, char *pszName, size_t cchName)
342{
343 /*
344 * Cycle thru the detection routines.
345 */
346 DBGF_OS_WRITE_LOCK(pUVM);
347
348 PDBGFOS const pOldOS = pUVM->dbgf.s.pCurOS;
349 pUVM->dbgf.s.pCurOS = NULL;
350
351 for (PDBGFOS pNewOS = pUVM->dbgf.s.pOSHead; pNewOS; pNewOS = pNewOS->pNext)
352 if (pNewOS->pReg->pfnProbe(pUVM, pNewOS->abData))
353 {
354 int rc;
355 pUVM->dbgf.s.pCurOS = pNewOS;
356 if (pOldOS == pNewOS)
357 rc = pNewOS->pReg->pfnRefresh(pUVM, pNewOS->abData);
358 else
359 {
360 if (pOldOS)
361 pOldOS->pReg->pfnTerm(pUVM, pNewOS->abData);
362 rc = pNewOS->pReg->pfnInit(pUVM, pNewOS->abData);
363 }
364 if (pszName && cchName)
365 strncat(pszName, pNewOS->pReg->szName, cchName);
366
367 DBGF_OS_WRITE_UNLOCK(pUVM);
368 return rc;
369 }
370
371 /* not found */
372 if (pOldOS)
373 pOldOS->pReg->pfnTerm(pUVM, pOldOS->abData);
374
375 DBGF_OS_WRITE_UNLOCK(pUVM);
376 return VINF_DBGF_OS_NOT_DETCTED;
377}
378
379
380/**
381 * Detects the guest OS and try dig out symbols and useful stuff.
382 *
383 * When called the 2nd time, symbols will be updated that if the OS
384 * is the same.
385 *
386 * @returns VBox status code.
387 * @retval VINF_SUCCESS if successfully detected.
388 * @retval VINF_DBGF_OS_NOT_DETCTED if we cannot figure it out.
389 *
390 * @param pUVM The user mode VM handle.
391 * @param pszName Where to store the OS name. Empty string if not detected.
392 * @param cchName Size of the buffer.
393 * @thread Any.
394 */
395VMMR3DECL(int) DBGFR3OSDetect(PUVM pUVM, char *pszName, size_t cchName)
396{
397 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
398 if (pszName && cchName)
399 *pszName = '\0';
400 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
401
402 /*
403 * Pass it on to EMT(0).
404 */
405 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSDetect, 3, pUVM, pszName, cchName);
406}
407
408
409/**
410 * EMT worker function for DBGFR3OSQueryNameAndVersion
411 *
412 * @returns VBox status code.
413 * @param pUVM The user mode VM handle.
414 * @param pszName Where to store the OS name. Optional.
415 * @param cchName The size of the name buffer.
416 * @param pszVersion Where to store the version string. Optional.
417 * @param cchVersion The size of the version buffer.
418 */
419static DECLCALLBACK(int) dbgfR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
420{
421 /*
422 * Any known OS?
423 */
424 DBGF_OS_READ_LOCK(pUVM);
425
426 if (pUVM->dbgf.s.pCurOS)
427 {
428 int rc = VINF_SUCCESS;
429 if (pszName && cchName)
430 {
431 size_t cch = strlen(pUVM->dbgf.s.pCurOS->pReg->szName);
432 if (cchName > cch)
433 memcpy(pszName, pUVM->dbgf.s.pCurOS->pReg->szName, cch + 1);
434 else
435 {
436 memcpy(pszName, pUVM->dbgf.s.pCurOS->pReg->szName, cchName - 1);
437 pszName[cchName - 1] = '\0';
438 rc = VINF_BUFFER_OVERFLOW;
439 }
440 }
441
442 if (pszVersion && cchVersion)
443 {
444 int rc2 = pUVM->dbgf.s.pCurOS->pReg->pfnQueryVersion(pUVM, pUVM->dbgf.s.pCurOS->abData, pszVersion, cchVersion);
445 if (RT_FAILURE(rc2) || rc == VINF_SUCCESS)
446 rc = rc2;
447 }
448
449 DBGF_OS_READ_UNLOCK(pUVM);
450 return rc;
451 }
452
453 DBGF_OS_READ_UNLOCK(pUVM);
454 return VERR_DBGF_OS_NOT_DETCTED;
455}
456
457
458/**
459 * Queries the name and/or version string for the guest OS.
460 *
461 * It goes without saying that this querying is done using the current
462 * guest OS digger and not additions or user configuration.
463 *
464 * @returns VBox status code.
465 * @param pUVM The user mode VM handle.
466 * @param pszName Where to store the OS name. Optional.
467 * @param cchName The size of the name buffer.
468 * @param pszVersion Where to store the version string. Optional.
469 * @param cchVersion The size of the version buffer.
470 * @thread Any.
471 */
472VMMR3DECL(int) DBGFR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion)
473{
474 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
475 AssertPtrNullReturn(pszName, VERR_INVALID_POINTER);
476 AssertPtrNullReturn(pszVersion, VERR_INVALID_POINTER);
477
478 /*
479 * Initialize the output up front.
480 */
481 if (pszName && cchName)
482 *pszName = '\0';
483 if (pszVersion && cchVersion)
484 *pszVersion = '\0';
485
486 /*
487 * Pass it on to EMT(0).
488 */
489 return VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/,
490 (PFNRT)dbgfR3OSQueryNameAndVersion, 5, pUVM, pszName, cchName, pszVersion, cchVersion);
491}
492
493
494/**
495 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog, Generic EMT wrapper.}
496 */
497static DECLCALLBACK(int) dbgfR3OSEmtIDmesg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages,
498 char *pszBuf, size_t cbBuf, size_t *pcbActual)
499{
500 PDBGFOSEMTWRAPPER pWrapper = RT_FROM_MEMBER(pThis, DBGFOSEMTWRAPPER, uWrapper.Dmesg);
501 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
502 AssertReturn(pUVM == pWrapper->pUVM, VERR_INVALID_VM_HANDLE);
503 AssertReturn(!fFlags, VERR_INVALID_FLAGS);
504 AssertReturn(cMessages > 0, VERR_INVALID_PARAMETER);
505 if (cbBuf)
506 AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
507 AssertPtrNullReturn(pcbActual, VERR_INVALID_POINTER);
508
509 return VMR3ReqPriorityCallWaitU(pWrapper->pUVM, 0 /*idDstCpu*/,
510 (PFNRT)pWrapper->uDigger.pDmesg->pfnQueryKernelLog, 7,
511 pWrapper->uDigger.pDmesg, pUVM, fFlags, cMessages, pszBuf, cbBuf, pcbActual);
512
513}
514
515
516/**
517 * EMT worker for DBGFR3OSQueryInterface.
518 *
519 * @param pUVM The user mode VM handle.
520 * @param enmIf The interface identifier.
521 * @param ppvIf Where to store the interface pointer on success.
522 */
523static DECLCALLBACK(void) dbgfR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf, void **ppvIf)
524{
525 AssertPtrReturnVoid(ppvIf);
526 *ppvIf = NULL;
527 AssertReturnVoid(enmIf > DBGFOSINTERFACE_INVALID && enmIf < DBGFOSINTERFACE_END);
528 UVM_ASSERT_VALID_EXT_RETURN_VOID(pUVM);
529
530 /*
531 * Forward the query to the current OS.
532 */
533 DBGF_OS_READ_LOCK(pUVM);
534 PDBGFOS pOS = pUVM->dbgf.s.pCurOS;
535 if (pOS)
536 {
537 void *pvDiggerIf;
538 pvDiggerIf = pOS->pReg->pfnQueryInterface(pUVM, pUVM->dbgf.s.pCurOS->abData, enmIf);
539 if (pvDiggerIf)
540 {
541 /*
542 * Do we have an EMT wrapper for this interface already?
543 *
544 * We ASSUME the interfaces are static and not dynamically allocated
545 * for each QueryInterface call.
546 */
547 PDBGFOSEMTWRAPPER pWrapper = pOS->pWrapperHead;
548 while ( pWrapper != NULL
549 && ( pWrapper->uDigger.pv != pvDiggerIf
550 && pWrapper->enmIf != enmIf) )
551 pWrapper = pWrapper->pNext;
552 if (pWrapper)
553 {
554 *ppvIf = &pWrapper->uWrapper;
555 DBGF_OS_READ_UNLOCK(pUVM);
556 return;
557 }
558 DBGF_OS_READ_UNLOCK(pUVM);
559
560 /*
561 * Create a wrapper.
562 */
563 int rc = MMR3HeapAllocExU(pUVM, MM_TAG_DBGF_OS, sizeof(*pWrapper), (void **)&pWrapper);
564 if (RT_FAILURE(rc))
565 return;
566 pWrapper->uDigger.pv = pvDiggerIf;
567 pWrapper->pUVM = pUVM;
568 pWrapper->enmIf = enmIf;
569 switch (enmIf)
570 {
571 case DBGFOSINTERFACE_DMESG:
572 pWrapper->uWrapper.Dmesg.u32Magic = DBGFOSIDMESG_MAGIC;
573 pWrapper->uWrapper.Dmesg.pfnQueryKernelLog = dbgfR3OSEmtIDmesg_QueryKernelLog;
574 pWrapper->uWrapper.Dmesg.u32EndMagic = DBGFOSIDMESG_MAGIC;
575 break;
576 default:
577 AssertFailed();
578 MMR3HeapFree(pWrapper);
579 return;
580 }
581
582 DBGF_OS_WRITE_LOCK(pUVM);
583 if (pUVM->dbgf.s.pCurOS == pOS)
584 {
585 pWrapper->pNext = pOS->pWrapperHead;
586 pOS->pWrapperHead = pWrapper;
587 *ppvIf = &pWrapper->uWrapper;
588 DBGF_OS_WRITE_UNLOCK(pUVM);
589 }
590 else
591 {
592 DBGF_OS_WRITE_UNLOCK(pUVM);
593 MMR3HeapFree(pWrapper);
594 }
595 return;
596 }
597 }
598 DBGF_OS_READ_UNLOCK(pUVM);
599}
600
601
602/**
603 * Query an optional digger interface.
604 *
605 * @returns Pointer to the digger interface on success, NULL if the interfaces isn't
606 * available or no active guest OS digger.
607 * @param pUVM The user mode VM handle.
608 * @param enmIf The interface identifier.
609 * @thread Any.
610 */
611VMMR3DECL(void *) DBGFR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf)
612{
613 AssertMsgReturn(enmIf > DBGFOSINTERFACE_INVALID && enmIf < DBGFOSINTERFACE_END, ("%d\n", enmIf), NULL);
614
615 /*
616 * Pass it on to an EMT.
617 */
618 void *pvIf = NULL;
619 VMR3ReqPriorityCallVoidWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3OSQueryInterface, 3, pUVM, enmIf, &pvIf);
620 return pvIf;
621}
622
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