VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/DBGFInfo.cpp@ 38838

最後變更 在這個檔案從38838是 38838,由 vboxsync 提交於 14 年 前

VMM,++: Try fix the async reset, suspend and power-off problems in PDM wrt conflicting VMM requests. Split them into priority requests and normal requests. The priority requests can safely be processed when PDM is doing async state change waits, the normal ones cannot. (The problem I bumped into was a unmap-chunk request from PGM being processed during PDMR3Reset, causing a recursive VMMR3EmtRendezvous deadlock.)

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 31.4 KB
 
1/* $Id: DBGFInfo.cpp 38838 2011-09-23 11:21:55Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Info.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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_INFO
23#include <VBox/vmm/dbgf.h>
24
25#include <VBox/vmm/mm.h>
26#include "DBGFInternal.h"
27#include <VBox/vmm/vm.h>
28#include <VBox/err.h>
29#include <VBox/log.h>
30
31#include <iprt/assert.h>
32#include <iprt/ctype.h>
33#include <iprt/semaphore.h>
34#include <iprt/stream.h>
35#include <iprt/string.h>
36#include <iprt/thread.h>
37
38
39/*******************************************************************************
40* Internal Functions *
41*******************************************************************************/
42static DECLCALLBACK(void) dbgfR3InfoLog_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...);
43static DECLCALLBACK(void) dbgfR3InfoLog_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args);
44static DECLCALLBACK(void) dbgfR3InfoLogRel_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...);
45static DECLCALLBACK(void) dbgfR3InfoLogRel_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args);
46static DECLCALLBACK(void) dbgfR3InfoStdErr_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...);
47static DECLCALLBACK(void) dbgfR3InfoStdErr_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args);
48static DECLCALLBACK(void) dbgfR3InfoHelp(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
49
50
51/*******************************************************************************
52* Global Variables *
53*******************************************************************************/
54/** Logger output. */
55static const DBGFINFOHLP g_dbgfR3InfoLogHlp =
56{
57 dbgfR3InfoLog_Printf,
58 dbgfR3InfoLog_PrintfV
59};
60
61/** Release logger output. */
62static const DBGFINFOHLP g_dbgfR3InfoLogRelHlp =
63{
64 dbgfR3InfoLogRel_Printf,
65 dbgfR3InfoLogRel_PrintfV
66};
67
68/** Standard error output. */
69static const DBGFINFOHLP g_dbgfR3InfoStdErrHlp =
70{
71 dbgfR3InfoStdErr_Printf,
72 dbgfR3InfoStdErr_PrintfV
73};
74
75
76/**
77 * Initialize the info handlers.
78 *
79 * @returns VBox status code.
80 * @param pVM VM handle.
81 */
82int dbgfR3InfoInit(PVM pVM)
83{
84 /*
85 * Make sure we already didn't initialized in the lazy manner.
86 */
87 if (RTCritSectIsInitialized(&pVM->dbgf.s.InfoCritSect))
88 return VINF_SUCCESS;
89
90 /*
91 * Initialize the crit sect.
92 */
93 int rc = RTCritSectInit(&pVM->dbgf.s.InfoCritSect);
94 AssertRCReturn(rc, rc);
95
96 /*
97 * Register the 'info help' item.
98 */
99 rc = DBGFR3InfoRegisterInternal(pVM, "help", "List of info items.", dbgfR3InfoHelp);
100 AssertRCReturn(rc, rc);
101
102 return VINF_SUCCESS;
103}
104
105
106/**
107 * Terminate the info handlers.
108 *
109 * @returns VBox status code.
110 * @param pVM VM handle.
111 */
112int dbgfR3InfoTerm(PVM pVM)
113{
114 /*
115 * Delete the crit sect.
116 */
117 int rc = RTCritSectDelete(&pVM->dbgf.s.InfoCritSect);
118 AssertRC(rc);
119 return rc;
120}
121
122
123/** Logger output.
124 * @copydoc DBGFINFOHLP::pfnPrintf */
125static DECLCALLBACK(void) dbgfR3InfoLog_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
126{
127 va_list args;
128 va_start(args, pszFormat);
129 RTLogPrintfV(pszFormat, args);
130 va_end(args);
131}
132
133/** Logger output.
134 * @copydoc DBGFINFOHLP::pfnPrintfV */
135static DECLCALLBACK(void) dbgfR3InfoLog_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
136{
137 RTLogPrintfV(pszFormat, args);
138}
139
140
141/**
142 * Gets the logger info helper.
143 * The returned info helper will unconditionally write all output to the log.
144 *
145 * @returns Pointer to the logger info helper.
146 */
147VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogHlp(void)
148{
149 return &g_dbgfR3InfoLogHlp;
150}
151
152
153/** Release logger output.
154 * @copydoc DBGFINFOHLP::pfnPrintf */
155static DECLCALLBACK(void) dbgfR3InfoLogRel_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
156{
157 va_list args;
158 va_start(args, pszFormat);
159 RTLogRelPrintfV(pszFormat, args);
160 va_end(args);
161}
162
163/** Release logger output.
164 * @copydoc DBGFINFOHLP::pfnPrintfV */
165static DECLCALLBACK(void) dbgfR3InfoLogRel_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
166{
167 RTLogRelPrintfV(pszFormat, args);
168}
169
170
171/** Standard error output.
172 * @copydoc DBGFINFOHLP::pfnPrintf */
173static DECLCALLBACK(void) dbgfR3InfoStdErr_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
174{
175 va_list args;
176 va_start(args, pszFormat);
177 RTStrmPrintfV(g_pStdErr, pszFormat, args);
178 va_end(args);
179}
180
181/** Standard error output.
182 * @copydoc DBGFINFOHLP::pfnPrintfV */
183static DECLCALLBACK(void) dbgfR3InfoStdErr_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
184{
185 RTStrmPrintfV(g_pStdErr, pszFormat, args);
186}
187
188
189/**
190 * Gets the release logger info helper.
191 * The returned info helper will unconditionally write all output to the release log.
192 *
193 * @returns Pointer to the release logger info helper.
194 */
195VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogRelHlp(void)
196{
197 return &g_dbgfR3InfoLogRelHlp;
198}
199
200
201/**
202 * Handle registration worker.
203 * This allocates the structure, initializes the common fields and inserts into the list.
204 * Upon successful return the we're inside the crit sect and the caller must leave it.
205 *
206 * @returns VBox status code.
207 * @param pVM VM handle.
208 * @param pszName The identifier of the info.
209 * @param pszDesc The description of the info and any arguments the handler may take.
210 * @param fFlags The flags.
211 * @param ppInfo Where to store the created
212 */
213static int dbgfR3InfoRegister(PVM pVM, const char *pszName, const char *pszDesc, uint32_t fFlags, PDBGFINFO *ppInfo)
214{
215 /*
216 * Validate.
217 */
218 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
219 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
220 AssertPtrReturn(pszDesc, VERR_INVALID_POINTER);
221 AssertMsgReturn(!(fFlags & ~(DBGFINFO_FLAGS_RUN_ON_EMT)), ("fFlags=%#x\n", fFlags), VERR_INVALID_PARAMETER);
222
223 /*
224 * Allocate and initialize.
225 */
226 int rc;
227 size_t cchName = strlen(pszName) + 1;
228 PDBGFINFO pInfo = (PDBGFINFO)MMR3HeapAlloc(pVM, MM_TAG_DBGF_INFO, RT_OFFSETOF(DBGFINFO, szName[cchName]));
229 if (pInfo)
230 {
231 pInfo->enmType = DBGFINFOTYPE_INVALID;
232 pInfo->fFlags = fFlags;
233 pInfo->pszDesc = pszDesc;
234 pInfo->cchName = cchName - 1;
235 memcpy(pInfo->szName, pszName, cchName);
236
237 /* lazy init */
238 rc = VINF_SUCCESS;
239 if (!RTCritSectIsInitialized(&pVM->dbgf.s.InfoCritSect))
240 rc = dbgfR3InfoInit(pVM);
241 if (RT_SUCCESS(rc))
242 {
243 /*
244 * Insert in alphabetical order.
245 */
246 rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
247 AssertRC(rc);
248 PDBGFINFO pPrev = NULL;
249 PDBGFINFO pCur;
250 for (pCur = pVM->dbgf.s.pInfoFirst; pCur; pPrev = pCur, pCur = pCur->pNext)
251 if (strcmp(pszName, pCur->szName) < 0)
252 break;
253 pInfo->pNext = pCur;
254 if (pPrev)
255 pPrev->pNext = pInfo;
256 else
257 pVM->dbgf.s.pInfoFirst = pInfo;
258
259 *ppInfo = pInfo;
260 return VINF_SUCCESS;
261 }
262 MMR3HeapFree(pInfo);
263 }
264 else
265 rc = VERR_NO_MEMORY;
266 return rc;
267}
268
269
270/**
271 * Register a info handler owned by a device.
272 *
273 * @returns VBox status code.
274 * @param pVM VM handle.
275 * @param pszName The identifier of the info.
276 * @param pszDesc The description of the info and any arguments the handler may take.
277 * @param pfnHandler The handler function to be called to display the info.
278 * @param pDevIns The device instance owning the info.
279 */
280VMMR3DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns)
281{
282 LogFlow(("DBGFR3InfoRegisterDevice: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pDevIns=%p\n",
283 pszName, pszName, pszDesc, pszDesc, pfnHandler, pDevIns));
284
285 /*
286 * Validate the specific stuff.
287 */
288 if (!pfnHandler)
289 {
290 AssertMsgFailed(("No handler\n"));
291 return VERR_INVALID_PARAMETER;
292 }
293 if (!pDevIns)
294 {
295 AssertMsgFailed(("No pDevIns\n"));
296 return VERR_INVALID_PARAMETER;
297 }
298
299 /*
300 * Register
301 */
302 PDBGFINFO pInfo;
303 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, 0, &pInfo);
304 if (RT_SUCCESS(rc))
305 {
306 pInfo->enmType = DBGFINFOTYPE_DEV;
307 pInfo->u.Dev.pfnHandler = pfnHandler;
308 pInfo->u.Dev.pDevIns = pDevIns;
309 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
310 }
311
312 return rc;
313}
314
315
316/**
317 * Register a info handler owned by a driver.
318 *
319 * @returns VBox status code.
320 * @param pVM VM handle.
321 * @param pszName The identifier of the info.
322 * @param pszDesc The description of the info and any arguments the handler may take.
323 * @param pfnHandler The handler function to be called to display the info.
324 * @param pDrvIns The driver instance owning the info.
325 */
326VMMR3DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns)
327{
328 LogFlow(("DBGFR3InfoRegisterDriver: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pDrvIns=%p\n",
329 pszName, pszName, pszDesc, pszDesc, pfnHandler, pDrvIns));
330
331 /*
332 * Validate the specific stuff.
333 */
334 if (!pfnHandler)
335 {
336 AssertMsgFailed(("No handler\n"));
337 return VERR_INVALID_PARAMETER;
338 }
339 if (!pDrvIns)
340 {
341 AssertMsgFailed(("No pDrvIns\n"));
342 return VERR_INVALID_PARAMETER;
343 }
344
345 /*
346 * Register
347 */
348 PDBGFINFO pInfo;
349 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, 0, &pInfo);
350 if (RT_SUCCESS(rc))
351 {
352 pInfo->enmType = DBGFINFOTYPE_DRV;
353 pInfo->u.Drv.pfnHandler = pfnHandler;
354 pInfo->u.Drv.pDrvIns = pDrvIns;
355 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
356 }
357
358 return rc;
359}
360
361
362/**
363 * Register a info handler owned by an internal component.
364 *
365 * @returns VBox status code.
366 * @param pVM VM handle.
367 * @param pszName The identifier of the info.
368 * @param pszDesc The description of the info and any arguments the handler may take.
369 * @param pfnHandler The handler function to be called to display the info.
370 */
371VMMR3DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler)
372{
373 return DBGFR3InfoRegisterInternalEx(pVM, pszName, pszDesc, pfnHandler, 0);
374}
375
376
377/**
378 * Register a info handler owned by an internal component.
379 *
380 * @returns VBox status code.
381 * @param pVM VM handle.
382 * @param pszName The identifier of the info.
383 * @param pszDesc The description of the info and any arguments the handler may take.
384 * @param pfnHandler The handler function to be called to display the info.
385 * @param fFlags Flags, see the DBGFINFO_FLAGS_*.
386 */
387VMMR3DECL(int) DBGFR3InfoRegisterInternalEx(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler, uint32_t fFlags)
388{
389 LogFlow(("DBGFR3InfoRegisterInternal: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p fFlags=%x\n",
390 pszName, pszName, pszDesc, pszDesc, pfnHandler, fFlags));
391
392 /*
393 * Validate the specific stuff.
394 */
395 if (!pfnHandler)
396 {
397 AssertMsgFailed(("No handler\n"));
398 return VERR_INVALID_PARAMETER;
399 }
400
401 /*
402 * Register
403 */
404 PDBGFINFO pInfo;
405 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, fFlags, &pInfo);
406 if (RT_SUCCESS(rc))
407 {
408 pInfo->enmType = DBGFINFOTYPE_INT;
409 pInfo->u.Int.pfnHandler = pfnHandler;
410 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
411 }
412
413 return rc;
414}
415
416
417/**
418 * Register a info handler owned by an external component.
419 *
420 * @returns VBox status code.
421 * @param pVM VM handle.
422 * @param pszName The identifier of the info.
423 * @param pszDesc The description of the info and any arguments the handler may take.
424 * @param pfnHandler The handler function to be called to display the info.
425 * @param pvUser User argument to be passed to the handler.
426 */
427VMMR3DECL(int) DBGFR3InfoRegisterExternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser)
428{
429 LogFlow(("DBGFR3InfoRegisterExternal: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pvUser=%p\n",
430 pszName, pszName, pszDesc, pszDesc, pfnHandler, pvUser));
431
432 /*
433 * Validate the specific stuff.
434 */
435 if (!pfnHandler)
436 {
437 AssertMsgFailed(("No handler\n"));
438 return VERR_INVALID_PARAMETER;
439 }
440
441 /*
442 * Register
443 */
444 PDBGFINFO pInfo;
445 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, 0, &pInfo);
446 if (RT_SUCCESS(rc))
447 {
448 pInfo->enmType = DBGFINFOTYPE_EXT;
449 pInfo->u.Ext.pfnHandler = pfnHandler;
450 pInfo->u.Ext.pvUser = pvUser;
451 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
452 }
453
454 return rc;
455}
456
457
458/**
459 * Deregister one(/all) info handler(s) owned by a device.
460 *
461 * @returns VBox status code.
462 * @param pVM VM Handle.
463 * @param pDevIns Device instance.
464 * @param pszName The identifier of the info. If NULL all owned by the device.
465 */
466VMMR3DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName)
467{
468 LogFlow(("DBGFR3InfoDeregisterDevice: pDevIns=%p pszName=%p:{%s}\n", pDevIns, pszName, pszName));
469
470 /*
471 * Validate input.
472 */
473 if (!pDevIns)
474 {
475 AssertMsgFailed(("!pDevIns\n"));
476 return VERR_INVALID_PARAMETER;
477 }
478 size_t cchName = pszName ? strlen(pszName) : 0;
479
480 /*
481 * Enumerate the info handlers and free the requested entries.
482 */
483 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
484 AssertRC(rc);
485 rc = VERR_FILE_NOT_FOUND;
486 PDBGFINFO pPrev = NULL;
487 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
488 if (pszName)
489 {
490 /*
491 * Free a specific one.
492 */
493 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
494 if ( pInfo->enmType == DBGFINFOTYPE_DEV
495 && pInfo->u.Dev.pDevIns == pDevIns
496 && pInfo->cchName == cchName
497 && !strcmp(pInfo->szName, pszName))
498 {
499 if (pPrev)
500 pPrev->pNext = pInfo->pNext;
501 else
502 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
503 MMR3HeapFree(pInfo);
504 rc = VINF_SUCCESS;
505 break;
506 }
507 }
508 else
509 {
510 /*
511 * Free all owned by the driver.
512 */
513 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
514 if ( pInfo->enmType == DBGFINFOTYPE_DEV
515 && pInfo->u.Dev.pDevIns == pDevIns)
516 {
517 if (pPrev)
518 pPrev->pNext = pInfo->pNext;
519 else
520 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
521 MMR3HeapFree(pInfo);
522 pInfo = pPrev;
523 }
524 rc = VINF_SUCCESS;
525 }
526 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
527 AssertRC(rc2);
528 AssertRC(rc);
529 LogFlow(("DBGFR3InfoDeregisterDevice: returns %Rrc\n", rc));
530 return rc;
531}
532
533/**
534 * Deregister one(/all) info handler(s) owned by a driver.
535 *
536 * @returns VBox status code.
537 * @param pVM VM Handle.
538 * @param pDrvIns Driver instance.
539 * @param pszName The identifier of the info. If NULL all owned by the driver.
540 */
541VMMR3DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName)
542{
543 LogFlow(("DBGFR3InfoDeregisterDriver: pDrvIns=%p pszName=%p:{%s}\n", pDrvIns, pszName, pszName));
544
545 /*
546 * Validate input.
547 */
548 if (!pDrvIns)
549 {
550 AssertMsgFailed(("!pDrvIns\n"));
551 return VERR_INVALID_PARAMETER;
552 }
553 size_t cchName = pszName ? strlen(pszName) : 0;
554
555 /*
556 * Enumerate the info handlers and free the requested entries.
557 */
558 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
559 AssertRC(rc);
560 rc = VERR_FILE_NOT_FOUND;
561 PDBGFINFO pPrev = NULL;
562 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
563 if (pszName)
564 {
565 /*
566 * Free a specific one.
567 */
568 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
569 if ( pInfo->enmType == DBGFINFOTYPE_DRV
570 && pInfo->u.Drv.pDrvIns == pDrvIns
571 && pInfo->cchName == cchName
572 && !strcmp(pInfo->szName, pszName))
573 {
574 if (pPrev)
575 pPrev->pNext = pInfo->pNext;
576 else
577 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
578 MMR3HeapFree(pInfo);
579 rc = VINF_SUCCESS;
580 break;
581 }
582 }
583 else
584 {
585 /*
586 * Free all owned by the driver.
587 */
588 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
589 if ( pInfo->enmType == DBGFINFOTYPE_DRV
590 && pInfo->u.Drv.pDrvIns == pDrvIns)
591 {
592 if (pPrev)
593 pPrev->pNext = pInfo->pNext;
594 else
595 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
596 MMR3HeapFree(pInfo);
597 pInfo = pPrev;
598 }
599 rc = VINF_SUCCESS;
600 }
601 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
602 AssertRC(rc2);
603 AssertRC(rc);
604 LogFlow(("DBGFR3InfoDeregisterDriver: returns %Rrc\n", rc));
605 return rc;
606}
607
608
609/**
610 * Internal deregistration helper.
611 *
612 * @returns VBox status code.
613 * @param pVM VM Handle.
614 * @param pszName The identifier of the info.
615 * @param enmType The info owner type.
616 */
617static int dbgfR3InfoDeregister(PVM pVM, const char *pszName, DBGFINFOTYPE enmType)
618{
619 /*
620 * Validate input.
621 */
622 if (!pszName)
623 {
624 AssertMsgFailed(("!pszName\n"));
625 return VERR_INVALID_PARAMETER;
626 }
627
628 /*
629 * Find the info handler.
630 */
631 size_t cchName = strlen(pszName);
632 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
633 AssertRC(rc);
634 rc = VERR_FILE_NOT_FOUND;
635 PDBGFINFO pPrev = NULL;
636 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
637 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
638 if ( pInfo->cchName == cchName
639 && !strcmp(pInfo->szName, pszName)
640 && pInfo->enmType == enmType)
641 {
642 if (pPrev)
643 pPrev->pNext = pInfo->pNext;
644 else
645 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
646 MMR3HeapFree(pInfo);
647 rc = VINF_SUCCESS;
648 break;
649 }
650 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
651 AssertRC(rc2);
652 AssertRC(rc);
653 LogFlow(("dbgfR3InfoDeregister: returns %Rrc\n", rc));
654 return rc;
655}
656
657
658/**
659 * Deregister a info handler owned by an internal component.
660 *
661 * @returns VBox status code.
662 * @param pVM VM Handle.
663 * @param pszName The identifier of the info. If NULL all owned by the device.
664 */
665VMMR3DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName)
666{
667 LogFlow(("DBGFR3InfoDeregisterInternal: pszName=%p:{%s}\n", pszName, pszName));
668 return dbgfR3InfoDeregister(pVM, pszName, DBGFINFOTYPE_INT);
669}
670
671
672/**
673 * Deregister a info handler owned by an external component.
674 *
675 * @returns VBox status code.
676 * @param pVM VM Handle.
677 * @param pszName The identifier of the info. If NULL all owned by the device.
678 */
679VMMR3DECL(int) DBGFR3InfoDeregisterExternal(PVM pVM, const char *pszName)
680{
681 LogFlow(("DBGFR3InfoDeregisterExternal: pszName=%p:{%s}\n", pszName, pszName));
682 return dbgfR3InfoDeregister(pVM, pszName, DBGFINFOTYPE_EXT);
683}
684
685
686/**
687 * Worker for DBGFR3Info and DBGFR3InfoEx.
688 *
689 * @returns VBox status code.
690 * @param pVM The VM handle.
691 * @param idCpu Which CPU to run EMT bound handlers on.
692 * VMCPUID_ANY or a valid CPU ID.
693 * @param pszName What to dump.
694 * @param pszArgs Arguments, optional.
695 * @param pHlp Output helper, optional.
696 */
697static DECLCALLBACK(int) dbgfR3Info(PVM pVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp)
698{
699 /*
700 * Validate input.
701 */
702 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
703 if (pHlp)
704 {
705 if ( !pHlp->pfnPrintf
706 || !pHlp->pfnPrintfV)
707 {
708 AssertMsgFailed(("A pHlp member is missing!\n"));
709 return VERR_INVALID_PARAMETER;
710 }
711 }
712 else
713 pHlp = &g_dbgfR3InfoLogHlp;
714
715 /*
716 * Find the info handler.
717 */
718 size_t cchName = strlen(pszName);
719 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
720 AssertRC(rc);
721 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
722 for (; pInfo; pInfo = pInfo->pNext)
723 if ( pInfo->cchName == cchName
724 && !memcmp(pInfo->szName, pszName, cchName))
725 break;
726 if (pInfo)
727 {
728 /*
729 * Found it.
730 * Make a copy of it on the stack so we can leave the crit sect.
731 * Switch on the type and invoke the handler.
732 */
733 DBGFINFO Info = *pInfo;
734 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
735 AssertRC(rc);
736 rc = VINF_SUCCESS;
737 switch (Info.enmType)
738 {
739 case DBGFINFOTYPE_DEV:
740 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
741 rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Dev.pfnHandler, 3, Info.u.Dev.pDevIns, pHlp, pszArgs);
742 else
743 Info.u.Dev.pfnHandler(Info.u.Dev.pDevIns, pHlp, pszArgs);
744 break;
745
746 case DBGFINFOTYPE_DRV:
747 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
748 rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Drv.pfnHandler, 3, Info.u.Drv.pDrvIns, pHlp, pszArgs);
749 else
750 Info.u.Drv.pfnHandler(Info.u.Drv.pDrvIns, pHlp, pszArgs);
751 break;
752
753 case DBGFINFOTYPE_INT:
754 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
755 rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Int.pfnHandler, 3, pVM, pHlp, pszArgs);
756 else
757 Info.u.Int.pfnHandler(pVM, pHlp, pszArgs);
758 break;
759
760 case DBGFINFOTYPE_EXT:
761 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
762 rc = VMR3ReqCallVoidWait(pVM, idCpu, (PFNRT)Info.u.Ext.pfnHandler, 3, Info.u.Ext.pvUser, pHlp, pszArgs);
763 else
764 Info.u.Ext.pfnHandler(Info.u.Ext.pvUser, pHlp, pszArgs);
765 break;
766
767 default:
768 AssertMsgFailed(("Invalid info type enmType=%d\n", Info.enmType));
769 rc = VERR_INTERNAL_ERROR;
770 break;
771 }
772 }
773 else
774 {
775 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
776 AssertRC(rc);
777 rc = VERR_FILE_NOT_FOUND;
778 }
779 return rc;
780}
781
782/**
783 * Display a piece of info writing to the supplied handler.
784 *
785 * @returns VBox status code.
786 * @param pVM VM handle.
787 * @param pszName The identifier of the info to display.
788 * @param pszArgs Arguments to the info handler.
789 * @param pHlp The output helper functions. If NULL the logger will be used.
790 */
791VMMR3DECL(int) DBGFR3Info(PVM pVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp)
792{
793 return dbgfR3Info(pVM, VMCPUID_ANY, pszName, pszArgs, pHlp);
794}
795
796
797/**
798 * Display a piece of info writing to the supplied handler.
799 *
800 * @returns VBox status code.
801 * @param pVM VM handle.
802 * @param idCpu The CPU to exectue the request on. Pass NIL_VMCPUID
803 * to not involve any EMT.
804 * @param pszName The identifier of the info to display.
805 * @param pszArgs Arguments to the info handler.
806 * @param pHlp The output helper functions. If NULL the logger will be used.
807 */
808VMMR3DECL(int) DBGFR3InfoEx(PVM pVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp)
809{
810 if (idCpu == NIL_VMCPUID)
811 return dbgfR3Info(pVM, VMCPUID_ANY, pszName, pszArgs, pHlp);
812 return VMR3ReqPriorityCallWait(pVM, idCpu,
813 (PFNRT)dbgfR3Info, 5, pVM, idCpu, pszName, pszArgs, pHlp);
814}
815
816
817/**
818 * Wrapper for DBGFR3Info that outputs to the release log.
819 *
820 * @returns See DBGFR3Info.
821 * @param pVM The VM handle.
822 * @param pszName See DBGFR3Info.
823 * @param pszArgs See DBGFR3Info.
824 */
825VMMR3DECL(int) DBGFR3InfoLogRel(PVM pVM, const char *pszName, const char *pszArgs)
826{
827 return DBGFR3Info(pVM, pszName, pszArgs, &g_dbgfR3InfoLogRelHlp);
828}
829
830
831/**
832 * Wrapper for DBGFR3Info that outputs to standard error.
833 *
834 * @returns See DBGFR3Info.
835 * @param pVM The VM handle.
836 * @param pszName See DBGFR3Info.
837 * @param pszArgs See DBGFR3Info.
838 */
839VMMR3DECL(int) DBGFR3InfoStdErr(PVM pVM, const char *pszName, const char *pszArgs)
840{
841 return DBGFR3Info(pVM, pszName, pszArgs, &g_dbgfR3InfoStdErrHlp);
842}
843
844
845/**
846 * Display several info items.
847 *
848 * This is intended used by the fatal error dump only.
849 *
850 * @returns
851 * @param pVM The VM handle.
852 * @param pszIncludePat Simple string pattern of info items to include.
853 * @param pszExcludePat Simple string pattern of info items to exclude.
854 * @param pszSepFmt Item separator format string. The item name will be
855 * given as parameter.
856 * @param pHlp The output helper functions. If NULL the logger
857 * will be used.
858 *
859 * @threads EMT
860 */
861VMMR3DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat, const char *pszSepFmt,
862 PCDBGFINFOHLP pHlp)
863{
864 /*
865 * Validate input.
866 */
867 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
868 AssertPtrReturn(pszIncludePat, VERR_INVALID_POINTER);
869 AssertPtrReturn(pszExcludePat, VERR_INVALID_POINTER);
870 if (pHlp)
871 {
872 AssertPtrReturn(pHlp->pfnPrintf, VERR_INVALID_POINTER);
873 AssertPtrReturn(pHlp->pfnPrintfV, VERR_INVALID_POINTER);
874 }
875 else
876 pHlp = &g_dbgfR3InfoLogHlp;
877
878 size_t const cchIncludePat = strlen(pszIncludePat);
879 size_t const cchExcludePat = strlen(pszExcludePat);
880 const char *pszArgs = "";
881
882 /*
883 * Enumerate the info handlers and call the ones matching.
884 * Note! We won't leave the critical section here...
885 */
886 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
887 AssertRC(rc);
888 rc = VWRN_NOT_FOUND;
889 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext)
890 {
891 if ( RTStrSimplePatternMultiMatch(pszIncludePat, cchIncludePat, pInfo->szName, pInfo->cchName, NULL)
892 && !RTStrSimplePatternMultiMatch(pszExcludePat, cchExcludePat, pInfo->szName, pInfo->cchName, NULL))
893 {
894 pHlp->pfnPrintf(pHlp, pszSepFmt, pInfo->szName);
895 rc = VINF_SUCCESS;
896 switch (pInfo->enmType)
897 {
898 case DBGFINFOTYPE_DEV:
899 if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
900 rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Dev.pfnHandler, 3, pInfo->u.Dev.pDevIns, pHlp, pszArgs);
901 else
902 pInfo->u.Dev.pfnHandler(pInfo->u.Dev.pDevIns, pHlp, pszArgs);
903 break;
904
905 case DBGFINFOTYPE_DRV:
906 if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
907 rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Drv.pfnHandler, 3, pInfo->u.Drv.pDrvIns, pHlp, pszArgs);
908 else
909 pInfo->u.Drv.pfnHandler(pInfo->u.Drv.pDrvIns, pHlp, pszArgs);
910 break;
911
912 case DBGFINFOTYPE_INT:
913 if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
914 rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Int.pfnHandler, 3, pVM, pHlp, pszArgs);
915 else
916 pInfo->u.Int.pfnHandler(pVM, pHlp, pszArgs);
917 break;
918
919 case DBGFINFOTYPE_EXT:
920 if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
921 rc = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)pInfo->u.Ext.pfnHandler, 3, pInfo->u.Ext.pvUser, pHlp, pszArgs);
922 else
923 pInfo->u.Ext.pfnHandler(pInfo->u.Ext.pvUser, pHlp, pszArgs);
924 break;
925
926 default:
927 AssertMsgFailed(("Invalid info type enmType=%d\n", pInfo->enmType));
928 rc = VERR_INTERNAL_ERROR;
929 break;
930 }
931 }
932 }
933 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
934 AssertRC(rc2);
935
936 return rc;
937}
938
939
940/**
941 * Enumerate all the register info handlers.
942 *
943 * @returns VBox status code.
944 * @param pVM VM handle.
945 * @param pfnCallback Pointer to callback function.
946 * @param pvUser User argument to pass to the callback.
947 */
948VMMR3DECL(int) DBGFR3InfoEnum(PVM pVM, PFNDBGFINFOENUM pfnCallback, void *pvUser)
949{
950 LogFlow(("DBGFR3InfoLog: pfnCallback=%p pvUser=%p\n", pfnCallback, pvUser));
951
952 /*
953 * Validate input.
954 */
955 if (!pfnCallback)
956 {
957 AssertMsgFailed(("!pfnCallback\n"));
958 return VERR_INVALID_PARAMETER;
959 }
960
961 /*
962 * Enter and enumerate.
963 */
964 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
965 AssertRC(rc);
966
967 rc = VINF_SUCCESS;
968 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; RT_SUCCESS(rc) && pInfo; pInfo = pInfo->pNext)
969 rc = pfnCallback(pVM, pInfo->szName, pInfo->pszDesc, pvUser);
970
971 /*
972 * Leave and exit.
973 */
974 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
975 AssertRC(rc2);
976
977 LogFlow(("DBGFR3InfoLog: returns %Rrc\n", rc));
978 return rc;
979}
980
981
982/**
983 * Info handler, internal version.
984 *
985 * @param pVM The VM handle.
986 * @param pHlp Callback functions for doing output.
987 * @param pszArgs Argument string. Optional and specific to the handler.
988 */
989static DECLCALLBACK(void) dbgfR3InfoHelp(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
990{
991 LogFlow(("dbgfR3InfoHelp: pszArgs=%s\n", pszArgs));
992
993 /*
994 * Enter and enumerate.
995 */
996 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
997 AssertRC(rc);
998
999 if (pszArgs && *pszArgs)
1000 {
1001 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext)
1002 {
1003 const char *psz = strstr(pszArgs, pInfo->szName);
1004 if ( psz
1005 && ( psz == pszArgs
1006 || RT_C_IS_SPACE(psz[-1]))
1007 && ( !psz[pInfo->cchName]
1008 || RT_C_IS_SPACE(psz[pInfo->cchName])))
1009 pHlp->pfnPrintf(pHlp, "%-16s %s\n",
1010 pInfo->szName, pInfo->pszDesc);
1011 }
1012 }
1013 else
1014 {
1015 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext)
1016 pHlp->pfnPrintf(pHlp, "%-16s %s\n",
1017 pInfo->szName, pInfo->pszDesc);
1018 }
1019
1020 /*
1021 * Leave and exit.
1022 */
1023 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
1024 AssertRC(rc);
1025}
1026
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette