VirtualBox

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

Last change on this file since 956 was 23, checked in by vboxsync, 18 years ago

string.h & stdio.h + header cleanups.

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