VirtualBox

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

Last change on this file since 7805 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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