VirtualBox

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

Last change on this file since 74168 was 73460, checked in by vboxsync, 6 years ago

IPRT,DBGF,Diggers: Moved DBGFRETURNTYPE and the unwind state structure to IPRT (dbg.h) in prep for debug module interface and more. Added stack unwind assist callback for the OS diggers so they can identify special stack frames and supply more info via the sure-register-value array and frame flags. Identify and decode NT/AMD64 trap frames.

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