VirtualBox

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

Last change on this file since 72287 was 69111, checked in by vboxsync, 7 years ago

(C) year

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