VirtualBox

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

Last change on this file since 80191 was 80191, checked in by vboxsync, 5 years ago

VMM/r3: Refactored VMCPU enumeration in preparation that aCpus will be replaced with a pointer array. Removed two raw-mode offset members from the CPUM and CPUMCPU sub-structures. bugref:9217 bugref:9517

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