VirtualBox

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

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

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 23.3 KB
 
1/** @file
2 *
3 * VMM DBGF - Debugger Facility, Info.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DBGF_INFO
27#include <VBox/dbgf.h>
28#include <VBox/mm.h>
29#include "DBGFInternal.h"
30#include <VBox/vm.h>
31
32#include <VBox/log.h>
33#include <iprt/semaphore.h>
34#include <iprt/thread.h>
35#include <iprt/assert.h>
36#include <VBox/err.h>
37
38#include <string.h>
39#include <ctype.h>
40
41
42/*******************************************************************************
43* Internal Functions *
44*******************************************************************************/
45static DECLCALLBACK(void) dbgfR3InfoLog_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...);
46static DECLCALLBACK(void) dbgfR3InfoLog_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args);
47static DECLCALLBACK(void) dbgfR3InfoLogRel_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...);
48static DECLCALLBACK(void) dbgfR3InfoLogRel_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args);
49static DECLCALLBACK(void) dbgfR3InfoHelp(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
50
51
52/*******************************************************************************
53* Global Variables *
54*******************************************************************************/
55/** Logger output. */
56static const DBGFINFOHLP g_dbgfR3InfoLogHlp =
57{
58 dbgfR3InfoLog_Printf,
59 dbgfR3InfoLog_PrintfV
60};
61
62/** Release logger output. */
63static const DBGFINFOHLP g_dbgfR3InfoLogRelHlp =
64{
65 dbgfR3InfoLogRel_Printf,
66 dbgfR3InfoLogRel_PrintfV
67};
68
69
70/**
71 * Initialize the info handlers.
72 *
73 * @returns VBox status code.
74 * @param pVM VM handle.
75 */
76int dbgfR3InfoInit(PVM pVM)
77{
78 /*
79 * Make sure we already didn't initialized in the lazy manner.
80 */
81 if (RTCritSectIsInitialized(&pVM->dbgf.s.InfoCritSect))
82 return VINF_SUCCESS;
83
84 /*
85 * Initialize the crit sect.
86 */
87 int rc = RTCritSectInit(&pVM->dbgf.s.InfoCritSect);
88 AssertRCReturn(rc, rc);
89
90 /*
91 * Register the 'info help' item.
92 */
93 rc = DBGFR3InfoRegisterInternal(pVM, "help", "List of info items.", dbgfR3InfoHelp);
94 AssertRCReturn(rc, rc);
95
96 return VINF_SUCCESS;
97}
98
99
100/**
101 * Terminate the info handlers.
102 *
103 * @returns VBox status code.
104 * @param pVM VM handle.
105 */
106int dbgfR3InfoTerm(PVM pVM)
107{
108 /*
109 * Delete the crit sect.
110 */
111 int rc = RTCritSectDelete(&pVM->dbgf.s.InfoCritSect);
112 AssertRC(rc);
113 return rc;
114}
115
116
117/** Logger output.
118 * @copydoc DBGFINFOHLP::pfnPrintf */
119static DECLCALLBACK(void) dbgfR3InfoLog_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
120{
121 va_list args;
122 va_start(args, pszFormat);
123 RTLogPrintfV(pszFormat, args);
124 va_end(args);
125}
126
127/** Logger output.
128 * @copydoc DBGFINFOHLP::pfnPrintfV */
129static DECLCALLBACK(void) dbgfR3InfoLog_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
130{
131 RTLogPrintfV(pszFormat, args);
132}
133
134
135/**
136 * Gets the logger info helper.
137 * The returned info helper will unconditionally write all output to the log.
138 *
139 * @returns Pointer to the logger info helper.
140 */
141DBGFR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogHlp(void)
142{
143 return &g_dbgfR3InfoLogHlp;
144}
145
146
147/** Release logger output.
148 * @copydoc DBGFINFOHLP::pfnPrintf */
149static DECLCALLBACK(void) dbgfR3InfoLogRel_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
150{
151 va_list args;
152 va_start(args, pszFormat);
153 RTLogRelPrintfV(pszFormat, args);
154 va_end(args);
155}
156
157/** Release logger output.
158 * @copydoc DBGFINFOHLP::pfnPrintfV */
159static DECLCALLBACK(void) dbgfR3InfoLogRel_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
160{
161 RTLogRelPrintfV(pszFormat, args);
162}
163
164
165/**
166 * Gets the release logger info helper.
167 * The returned info helper will unconditionally write all output to the release log.
168 *
169 * @returns Pointer to the release logger info helper.
170 */
171DBGFR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogRelHlp(void)
172{
173 return &g_dbgfR3InfoLogRelHlp;
174}
175
176
177/**
178 * Handle registration worker.
179 * This allocates the structure, initalizes the common fields and inserts into the list.
180 * Upon successful return the we're inside the crit sect and the caller must leave it.
181 *
182 * @returns VBox status code.
183 * @param pVM VM handle.
184 * @param pszName The identifier of the info.
185 * @param pszDesc The description of the info and any arguments the handler may take.
186 * @param ppInfo Where to store the created
187 */
188static int dbgfR3InfoRegister(PVM pVM, const char *pszName, const char *pszDesc, PDBGFINFO *ppInfo)
189{
190 /*
191 * Validate.
192 */
193 if (!pszName)
194 {
195 AssertMsgFailed(("!pszName\n"));
196 return VERR_INVALID_PARAMETER;
197 }
198 if (!pszDesc)
199 {
200 AssertMsgFailed(("!pszDesc\n"));
201 return VERR_INVALID_PARAMETER;
202 }
203
204 /*
205 * Allocate and initialize.
206 */
207 int rc;
208 size_t cchName = strlen(pszName) + 1;
209 PDBGFINFO pInfo = (PDBGFINFO)MMR3HeapAlloc(pVM, MM_TAG_DBGF_INFO, RT_OFFSETOF(DBGFINFO, szName[cchName]));
210 if (pInfo)
211 {
212 pInfo->enmType = DBGFINFOTYPE_INVALID;
213 pInfo->pszDesc = pszDesc;
214 pInfo->cchName = cchName - 1;
215 memcpy(pInfo->szName, pszName, cchName);
216
217 /* lazy init */
218 rc = VINF_SUCCESS;
219 if (!RTCritSectIsInitialized(&pVM->dbgf.s.InfoCritSect))
220 rc = dbgfR3InfoInit(pVM);
221 if (VBOX_SUCCESS(rc))
222 {
223 /*
224 * Insert in alphabetical order.
225 */
226 rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
227 AssertRC(rc);
228 PDBGFINFO pPrev = NULL;
229 PDBGFINFO pCur;
230 for (pCur = pVM->dbgf.s.pInfoFirst; pCur; pPrev = pCur, pCur = pCur->pNext)
231 if (strcmp(pszName, pCur->szName) < 0)
232 break;
233 pInfo->pNext = pCur;
234 if (pPrev)
235 pPrev->pNext = pInfo;
236 else
237 pVM->dbgf.s.pInfoFirst = pInfo;
238
239 *ppInfo = pInfo;
240 return VINF_SUCCESS;
241 }
242 MMR3HeapFree(pInfo);
243 }
244 else
245 rc = VERR_NO_MEMORY;
246 return rc;
247}
248
249
250/**
251 * Register a info handler owned by a device.
252 *
253 * @returns VBox status code.
254 * @param pVM VM handle.
255 * @param pszName The identifier of the info.
256 * @param pszDesc The description of the info and any arguments the handler may take.
257 * @param pfnHandler The handler function to be called to display the info.
258 * @param pDevIns The device instance owning the info.
259 */
260DBGFR3DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns)
261{
262 LogFlow(("DBGFR3InfoRegisterDevice: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pDevIns=%p\n",
263 pszName, pszName, pszDesc, pszDesc, pfnHandler, pDevIns));
264
265 /*
266 * Validate the specific stuff.
267 */
268 if (!pfnHandler)
269 {
270 AssertMsgFailed(("No handler\n"));
271 return VERR_INVALID_PARAMETER;
272 }
273 if (!pDevIns)
274 {
275 AssertMsgFailed(("No pDevIns\n"));
276 return VERR_INVALID_PARAMETER;
277 }
278
279 /*
280 * Register
281 */
282 PDBGFINFO pInfo;
283 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, &pInfo);
284 if (VBOX_SUCCESS(rc))
285 {
286 pInfo->enmType = DBGFINFOTYPE_DEV;
287 pInfo->u.Dev.pfnHandler = pfnHandler;
288 pInfo->u.Dev.pDevIns = pDevIns;
289 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
290 }
291
292 return rc;
293}
294
295
296/**
297 * Register a info handler owned by a driver.
298 *
299 * @returns VBox status code.
300 * @param pVM VM handle.
301 * @param pszName The identifier of the info.
302 * @param pszDesc The description of the info and any arguments the handler may take.
303 * @param pfnHandler The handler function to be called to display the info.
304 * @param pDrvIns The driver instance owning the info.
305 */
306DBGFR3DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns)
307{
308 LogFlow(("DBGFR3InfoRegisterDriver: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pDrvIns=%p\n",
309 pszName, pszName, pszDesc, pszDesc, pfnHandler, pDrvIns));
310
311 /*
312 * Validate the specific stuff.
313 */
314 if (!pfnHandler)
315 {
316 AssertMsgFailed(("No handler\n"));
317 return VERR_INVALID_PARAMETER;
318 }
319 if (!pDrvIns)
320 {
321 AssertMsgFailed(("No pDrvIns\n"));
322 return VERR_INVALID_PARAMETER;
323 }
324
325 /*
326 * Register
327 */
328 PDBGFINFO pInfo;
329 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, &pInfo);
330 if (VBOX_SUCCESS(rc))
331 {
332 pInfo->enmType = DBGFINFOTYPE_DRV;
333 pInfo->u.Drv.pfnHandler = pfnHandler;
334 pInfo->u.Drv.pDrvIns = pDrvIns;
335 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
336 }
337
338 return rc;
339}
340
341
342/**
343 * Register a info handler owned by an internal component.
344 *
345 * @returns VBox status code.
346 * @param pVM VM handle.
347 * @param pszName The identifier of the info.
348 * @param pszDesc The description of the info and any arguments the handler may take.
349 * @param pfnHandler The handler function to be called to display the info.
350 */
351DBGFR3DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler)
352{
353 LogFlow(("DBGFR3InfoRegisterInternal: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
354 pszName, pszName, pszDesc, pszDesc, pfnHandler));
355
356 /*
357 * Validate the specific stuff.
358 */
359 if (!pfnHandler)
360 {
361 AssertMsgFailed(("No handler\n"));
362 return VERR_INVALID_PARAMETER;
363 }
364
365 /*
366 * Register
367 */
368 PDBGFINFO pInfo;
369 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, &pInfo);
370 if (VBOX_SUCCESS(rc))
371 {
372 pInfo->enmType = DBGFINFOTYPE_INT;
373 pInfo->u.Int.pfnHandler = pfnHandler;
374 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
375 }
376
377 return rc;
378}
379
380
381
382/**
383 * Register a info handler owned by an external component.
384 *
385 * @returns VBox status code.
386 * @param pVM VM handle.
387 * @param pszName The identifier of the info.
388 * @param pszDesc The description of the info and any arguments the handler may take.
389 * @param pfnHandler The handler function to be called to display the info.
390 * @param pvUser User argument to be passed to the handler.
391 */
392DBGFR3DECL(int) DBGFR3InfoRegisterExternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser)
393{
394 LogFlow(("DBGFR3InfoRegisterExternal: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pvUser=%p\n",
395 pszName, pszName, pszDesc, pszDesc, pfnHandler, pvUser));
396
397 /*
398 * Validate the specific stuff.
399 */
400 if (!pfnHandler)
401 {
402 AssertMsgFailed(("No handler\n"));
403 return VERR_INVALID_PARAMETER;
404 }
405
406 /*
407 * Register
408 */
409 PDBGFINFO pInfo;
410 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, &pInfo);
411 if (VBOX_SUCCESS(rc))
412 {
413 pInfo->enmType = DBGFINFOTYPE_EXT;
414 pInfo->u.Ext.pfnHandler = pfnHandler;
415 pInfo->u.Ext.pvUser = pvUser;
416 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
417 }
418
419 return rc;
420}
421
422
423/**
424 * Deregister one(/all) info handler(s) owned by a device.
425 *
426 * @returns VBox status code.
427 * @param pVM VM Handle.
428 * @param pDevIns Device instance.
429 * @param pszName The identifier of the info. If NULL all owned by the device.
430 */
431DBGFR3DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName)
432{
433 LogFlow(("DBGFR3InfoDeregisterDevice: pDevIns=%p pszName=%p:{%s}\n", pDevIns, pszName, pszName));
434
435 /*
436 * Validate input.
437 */
438 if (!pDevIns)
439 {
440 AssertMsgFailed(("!pDevIns\n"));
441 return VERR_INVALID_PARAMETER;
442 }
443 size_t cchName = pszName ? strlen(pszName) : 0;
444
445 /*
446 * Enumerate the info handlers and free the requested entries.
447 */
448 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
449 AssertRC(rc);
450 rc = VERR_FILE_NOT_FOUND;
451 PDBGFINFO pPrev = NULL;
452 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
453 if (pszName)
454 {
455 /*
456 * Free a specific one.
457 */
458 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
459 if ( pInfo->enmType == DBGFINFOTYPE_DEV
460 && pInfo->u.Dev.pDevIns == pDevIns
461 && pInfo->cchName == cchName
462 && !strcmp(pInfo->szName, pszName))
463 {
464 if (pPrev)
465 pPrev->pNext = pInfo->pNext;
466 else
467 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
468 MMR3HeapFree(pInfo);
469 rc = VINF_SUCCESS;
470 break;
471 }
472 }
473 else
474 {
475 /*
476 * Free all owned by the driver.
477 */
478 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
479 if ( pInfo->enmType == DBGFINFOTYPE_DEV
480 && pInfo->u.Dev.pDevIns == pDevIns)
481 {
482 if (pPrev)
483 pPrev->pNext = pInfo->pNext;
484 else
485 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
486 MMR3HeapFree(pInfo);
487 pInfo = pPrev;
488 }
489 rc = VINF_SUCCESS;
490 }
491 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
492 AssertRC(rc2);
493 AssertRC(rc);
494 LogFlow(("DBGFR3InfoDeregisterDevice: returns %Vrc\n", rc));
495 return rc;
496}
497
498/**
499 * Deregister one(/all) info handler(s) owned by a driver.
500 *
501 * @returns VBox status code.
502 * @param pVM VM Handle.
503 * @param pDrvIns Driver instance.
504 * @param pszName The identifier of the info. If NULL all owned by the driver.
505 */
506DBGFR3DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName)
507{
508 LogFlow(("DBGFR3InfoDeregisterDriver: pDrvIns=%p pszName=%p:{%s}\n", pDrvIns, pszName, pszName));
509
510 /*
511 * Validate input.
512 */
513 if (!pDrvIns)
514 {
515 AssertMsgFailed(("!pDrvIns\n"));
516 return VERR_INVALID_PARAMETER;
517 }
518 size_t cchName = pszName ? strlen(pszName) : 0;
519
520 /*
521 * Enumerate the info handlers and free the requested entries.
522 */
523 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
524 AssertRC(rc);
525 rc = VERR_FILE_NOT_FOUND;
526 PDBGFINFO pPrev = NULL;
527 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
528 if (pszName)
529 {
530 /*
531 * Free a specific one.
532 */
533 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
534 if ( pInfo->enmType == DBGFINFOTYPE_DRV
535 && pInfo->u.Drv.pDrvIns == pDrvIns
536 && pInfo->cchName == cchName
537 && !strcmp(pInfo->szName, pszName))
538 {
539 if (pPrev)
540 pPrev->pNext = pInfo->pNext;
541 else
542 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
543 MMR3HeapFree(pInfo);
544 rc = VINF_SUCCESS;
545 break;
546 }
547 }
548 else
549 {
550 /*
551 * Free all owned by the driver.
552 */
553 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
554 if ( pInfo->enmType == DBGFINFOTYPE_DRV
555 && pInfo->u.Drv.pDrvIns == pDrvIns)
556 {
557 if (pPrev)
558 pPrev->pNext = pInfo->pNext;
559 else
560 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
561 MMR3HeapFree(pInfo);
562 pInfo = pPrev;
563 }
564 rc = VINF_SUCCESS;
565 }
566 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
567 AssertRC(rc2);
568 AssertRC(rc);
569 LogFlow(("DBGFR3InfoDeregisterDriver: returns %Vrc\n", rc));
570 return rc;
571}
572
573
574/**
575 * Internal deregistration helper.
576 *
577 * @returns VBox status code.
578 * @param pVM VM Handle.
579 * @param pszName The identifier of the info.
580 * @param enmType The info owner type.
581 */
582static int dbgfR3InfoDeregister(PVM pVM, const char *pszName, DBGFINFOTYPE enmType)
583{
584 /*
585 * Validate input.
586 */
587 if (!pszName)
588 {
589 AssertMsgFailed(("!pszName\n"));
590 return VERR_INVALID_PARAMETER;
591 }
592
593 /*
594 * Find the info handler.
595 */
596 size_t cchName = strlen(pszName);
597 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
598 AssertRC(rc);
599 rc = VERR_FILE_NOT_FOUND;
600 PDBGFINFO pPrev = NULL;
601 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
602 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
603 if ( pInfo->cchName == cchName
604 && !strcmp(pInfo->szName, pszName)
605 && pInfo->enmType == enmType)
606 {
607 if (pPrev)
608 pPrev->pNext = pInfo->pNext;
609 else
610 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
611 MMR3HeapFree(pInfo);
612 rc = VINF_SUCCESS;
613 break;
614 }
615 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
616 AssertRC(rc2);
617 AssertRC(rc);
618 LogFlow(("dbgfR3InfoDeregister: returns %Vrc\n", rc));
619 return rc;
620}
621
622/**
623 * Deregister a info handler owned by an internal component.
624 *
625 * @returns VBox status code.
626 * @param pVM VM Handle.
627 * @param pszName The identifier of the info. If NULL all owned by the device.
628 */
629DBGFR3DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName)
630{
631 LogFlow(("DBGFR3InfoDeregisterInternal: pszName=%p:{%s}\n", pszName, pszName));
632 return dbgfR3InfoDeregister(pVM, pszName, DBGFINFOTYPE_INT);
633}
634
635
636/**
637 * Deregister a info handler owned by an external component.
638 *
639 * @returns VBox status code.
640 * @param pVM VM Handle.
641 * @param pszName The identifier of the info. If NULL all owned by the device.
642 */
643DBGFR3DECL(int) DBGFR3InfoDeregisterExternal(PVM pVM, const char *pszName)
644{
645 LogFlow(("DBGFR3InfoDeregisterExternal: pszName=%p:{%s}\n", pszName, pszName));
646 return dbgfR3InfoDeregister(pVM, pszName, DBGFINFOTYPE_EXT);
647}
648
649
650/**
651 * Display a piece of info writing to the supplied handler.
652 *
653 * @returns VBox status code.
654 * @param pVM VM handle.
655 * @param pszName The identifier of the info to display.
656 * @param pszArgs Arguments to the info handler.
657 * @param pHlp The output helper functions. If NULL the logger will be used.
658 */
659DBGFR3DECL(int) DBGFR3Info(PVM pVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp)
660{
661 /*
662 * Validate input.
663 */
664 if (!pszName)
665 {
666 AssertMsgFailed(("!pszName\n"));
667 return VERR_INVALID_PARAMETER;
668 }
669 if (pHlp)
670 {
671 if ( !pHlp->pfnPrintf
672 || !pHlp->pfnPrintfV)
673 {
674 AssertMsgFailed(("A pHlp member is missing!\n"));
675 return VERR_INVALID_PARAMETER;
676 }
677 }
678 else
679 pHlp = &g_dbgfR3InfoLogHlp;
680
681 /*
682 * Find the info handler.
683 */
684 size_t cchName = strlen(pszName);
685 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
686 AssertRC(rc);
687 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
688 for (; pInfo; pInfo = pInfo->pNext)
689 if ( pInfo->cchName == cchName
690 && !memcmp(pInfo->szName, pszName, cchName))
691 break;
692 if (pInfo)
693 {
694 /*
695 * Found it.
696 * Make a copy of it on the stack so we can leave the crit sect.
697 * Switch on the type and invoke the handler.
698 */
699 DBGFINFO Info = *pInfo;
700 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
701 AssertRC(rc);
702 rc = VINF_SUCCESS;
703 switch (Info.enmType)
704 {
705 case DBGFINFOTYPE_DEV:
706 Info.u.Dev.pfnHandler(Info.u.Dev.pDevIns, pHlp, pszArgs);
707 break;
708 case DBGFINFOTYPE_DRV:
709 Info.u.Drv.pfnHandler(Info.u.Drv.pDrvIns, pHlp, pszArgs);
710 break;
711 case DBGFINFOTYPE_INT:
712 Info.u.Int.pfnHandler(pVM, pHlp, pszArgs);
713 break;
714 case DBGFINFOTYPE_EXT:
715 Info.u.Ext.pfnHandler(Info.u.Ext.pvUser, pHlp, pszArgs);
716 break;
717 default:
718 AssertMsgFailed(("Invalid info type enmType=%d\n", Info.enmType));
719 rc = VERR_INTERNAL_ERROR;
720 break;
721 }
722 }
723 else
724 {
725 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
726 AssertRC(rc);
727 rc = VERR_FILE_NOT_FOUND;
728 }
729 return rc;
730}
731
732
733/**
734 * Enumerate all the register info handlers.
735 *
736 * @returns VBox status code.
737 * @param pVM VM handle.
738 * @param pfnCallback Pointer to callback function.
739 * @param pvUser User argument to pass to the callback.
740 */
741DBGFR3DECL(int) DBGFR3InfoEnum(PVM pVM, PFNDBGFINFOENUM pfnCallback, void *pvUser)
742{
743 LogFlow(("DBGFR3InfoLog: pfnCallback=%p pvUser=%p\n", pfnCallback, pvUser));
744
745 /*
746 * Validate input.
747 */
748 if (!pfnCallback)
749 {
750 AssertMsgFailed(("!pfnCallback\n"));
751 return VERR_INVALID_PARAMETER;
752 }
753
754 /*
755 * Enter and enumerate.
756 */
757 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
758 AssertRC(rc);
759
760 rc = VINF_SUCCESS;
761 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; VBOX_SUCCESS(rc) && pInfo; pInfo = pInfo->pNext)
762 rc = pfnCallback(pVM, pInfo->szName, pInfo->pszDesc, pvUser);
763
764 /*
765 * Leave and exit.
766 */
767 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
768 AssertRC(rc2);
769
770 LogFlow(("DBGFR3InfoLog: returns %Vrc\n", rc));
771 return rc;
772}
773
774
775/**
776 * Info handler, internal version.
777 *
778 * @param pVM The VM handle.
779 * @param pHlp Callback functions for doing output.
780 * @param pszArgs Argument string. Optional and specific to the handler.
781 */
782static DECLCALLBACK(void) dbgfR3InfoHelp(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
783{
784 LogFlow(("dbgfR3InfoHelp: pszArgs=%s\n", pszArgs));
785
786 /*
787 * Enter and enumerate.
788 */
789 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
790 AssertRC(rc);
791
792 if (pszArgs && *pszArgs)
793 {
794 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext)
795 {
796 const char *psz = strstr(pszArgs, pInfo->szName);
797 if ( psz
798 && ( psz == pszArgs
799 || isspace(psz[-1]))
800 && ( !psz[pInfo->cchName]
801 || isspace(psz[pInfo->cchName])))
802 pHlp->pfnPrintf(pHlp, "%-16s %s\n",
803 pInfo->szName, pInfo->pszDesc);
804 }
805 }
806 else
807 {
808 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext)
809 pHlp->pfnPrintf(pHlp, "%-16s %s\n",
810 pInfo->szName, pInfo->pszDesc);
811 }
812
813 /*
814 * Leave and exit.
815 */
816 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
817 AssertRC(rc);
818}
819
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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