VirtualBox

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

Last change on this file since 13476 was 12989, checked in by vboxsync, 16 years ago

VMM + VBox/cdefs.h: consolidated all the XYZ*DECLS of the VMM into VMM*DECL. Removed dead DECL and IN_XYZ* macros.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.0 KB
Line 
1/* $Id: DBGFInfo.cpp 12989 2008-10-06 02:15:39Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Info.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
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 */
140VMMR3DECL(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 */
170VMMR3DECL(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 fFlags The flags.
186 * @param ppInfo Where to store the created
187 */
188static int dbgfR3InfoRegister(PVM pVM, const char *pszName, const char *pszDesc, uint32_t fFlags, PDBGFINFO *ppInfo)
189{
190 /*
191 * Validate.
192 */
193 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
194 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
195 AssertPtrReturn(pszDesc, VERR_INVALID_POINTER);
196 AssertMsgReturn(!(fFlags & ~(DBGFINFO_FLAGS_RUN_ON_EMT)), ("fFlags=%#x\n", fFlags), VERR_INVALID_PARAMETER);
197
198 /*
199 * Allocate and initialize.
200 */
201 int rc;
202 size_t cchName = strlen(pszName) + 1;
203 PDBGFINFO pInfo = (PDBGFINFO)MMR3HeapAlloc(pVM, MM_TAG_DBGF_INFO, RT_OFFSETOF(DBGFINFO, szName[cchName]));
204 if (pInfo)
205 {
206 pInfo->enmType = DBGFINFOTYPE_INVALID;
207 pInfo->fFlags = fFlags;
208 pInfo->pszDesc = pszDesc;
209 pInfo->cchName = cchName - 1;
210 memcpy(pInfo->szName, pszName, cchName);
211
212 /* lazy init */
213 rc = VINF_SUCCESS;
214 if (!RTCritSectIsInitialized(&pVM->dbgf.s.InfoCritSect))
215 rc = dbgfR3InfoInit(pVM);
216 if (VBOX_SUCCESS(rc))
217 {
218 /*
219 * Insert in alphabetical order.
220 */
221 rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
222 AssertRC(rc);
223 PDBGFINFO pPrev = NULL;
224 PDBGFINFO pCur;
225 for (pCur = pVM->dbgf.s.pInfoFirst; pCur; pPrev = pCur, pCur = pCur->pNext)
226 if (strcmp(pszName, pCur->szName) < 0)
227 break;
228 pInfo->pNext = pCur;
229 if (pPrev)
230 pPrev->pNext = pInfo;
231 else
232 pVM->dbgf.s.pInfoFirst = pInfo;
233
234 *ppInfo = pInfo;
235 return VINF_SUCCESS;
236 }
237 MMR3HeapFree(pInfo);
238 }
239 else
240 rc = VERR_NO_MEMORY;
241 return rc;
242}
243
244
245/**
246 * Register a info handler owned by a device.
247 *
248 * @returns VBox status code.
249 * @param pVM VM handle.
250 * @param pszName The identifier of the info.
251 * @param pszDesc The description of the info and any arguments the handler may take.
252 * @param pfnHandler The handler function to be called to display the info.
253 * @param pDevIns The device instance owning the info.
254 */
255VMMR3DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns)
256{
257 LogFlow(("DBGFR3InfoRegisterDevice: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pDevIns=%p\n",
258 pszName, pszName, pszDesc, pszDesc, pfnHandler, pDevIns));
259
260 /*
261 * Validate the specific stuff.
262 */
263 if (!pfnHandler)
264 {
265 AssertMsgFailed(("No handler\n"));
266 return VERR_INVALID_PARAMETER;
267 }
268 if (!pDevIns)
269 {
270 AssertMsgFailed(("No pDevIns\n"));
271 return VERR_INVALID_PARAMETER;
272 }
273
274 /*
275 * Register
276 */
277 PDBGFINFO pInfo;
278 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, 0, &pInfo);
279 if (VBOX_SUCCESS(rc))
280 {
281 pInfo->enmType = DBGFINFOTYPE_DEV;
282 pInfo->u.Dev.pfnHandler = pfnHandler;
283 pInfo->u.Dev.pDevIns = pDevIns;
284 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
285 }
286
287 return rc;
288}
289
290
291/**
292 * Register a info handler owned by a driver.
293 *
294 * @returns VBox status code.
295 * @param pVM VM handle.
296 * @param pszName The identifier of the info.
297 * @param pszDesc The description of the info and any arguments the handler may take.
298 * @param pfnHandler The handler function to be called to display the info.
299 * @param pDrvIns The driver instance owning the info.
300 */
301VMMR3DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns)
302{
303 LogFlow(("DBGFR3InfoRegisterDriver: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pDrvIns=%p\n",
304 pszName, pszName, pszDesc, pszDesc, pfnHandler, pDrvIns));
305
306 /*
307 * Validate the specific stuff.
308 */
309 if (!pfnHandler)
310 {
311 AssertMsgFailed(("No handler\n"));
312 return VERR_INVALID_PARAMETER;
313 }
314 if (!pDrvIns)
315 {
316 AssertMsgFailed(("No pDrvIns\n"));
317 return VERR_INVALID_PARAMETER;
318 }
319
320 /*
321 * Register
322 */
323 PDBGFINFO pInfo;
324 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, 0, &pInfo);
325 if (VBOX_SUCCESS(rc))
326 {
327 pInfo->enmType = DBGFINFOTYPE_DRV;
328 pInfo->u.Drv.pfnHandler = pfnHandler;
329 pInfo->u.Drv.pDrvIns = pDrvIns;
330 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
331 }
332
333 return rc;
334}
335
336
337/**
338 * Register a info handler owned by an internal component.
339 *
340 * @returns VBox status code.
341 * @param pVM VM handle.
342 * @param pszName The identifier of the info.
343 * @param pszDesc The description of the info and any arguments the handler may take.
344 * @param pfnHandler The handler function to be called to display the info.
345 */
346VMMR3DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler)
347{
348 return DBGFR3InfoRegisterInternalEx(pVM, pszName, pszDesc, pfnHandler, 0);
349}
350
351
352/**
353 * Register a info handler owned by an internal component.
354 *
355 * @returns VBox status code.
356 * @param pVM VM handle.
357 * @param pszName The identifier of the info.
358 * @param pszDesc The description of the info and any arguments the handler may take.
359 * @param pfnHandler The handler function to be called to display the info.
360 * @param fFlags Flags, see the DBGFINFO_FLAGS_*.
361 */
362VMMR3DECL(int) DBGFR3InfoRegisterInternalEx(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler, uint32_t fFlags)
363{
364 LogFlow(("DBGFR3InfoRegisterInternal: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p fFlags=%x\n",
365 pszName, pszName, pszDesc, pszDesc, pfnHandler, fFlags));
366
367 /*
368 * Validate the specific stuff.
369 */
370 if (!pfnHandler)
371 {
372 AssertMsgFailed(("No handler\n"));
373 return VERR_INVALID_PARAMETER;
374 }
375
376 /*
377 * Register
378 */
379 PDBGFINFO pInfo;
380 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, fFlags, &pInfo);
381 if (VBOX_SUCCESS(rc))
382 {
383 pInfo->enmType = DBGFINFOTYPE_INT;
384 pInfo->u.Int.pfnHandler = pfnHandler;
385 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
386 }
387
388 return rc;
389}
390
391
392/**
393 * Register a info handler owned by an external component.
394 *
395 * @returns VBox status code.
396 * @param pVM VM handle.
397 * @param pszName The identifier of the info.
398 * @param pszDesc The description of the info and any arguments the handler may take.
399 * @param pfnHandler The handler function to be called to display the info.
400 * @param pvUser User argument to be passed to the handler.
401 */
402VMMR3DECL(int) DBGFR3InfoRegisterExternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser)
403{
404 LogFlow(("DBGFR3InfoRegisterExternal: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p pvUser=%p\n",
405 pszName, pszName, pszDesc, pszDesc, pfnHandler, pvUser));
406
407 /*
408 * Validate the specific stuff.
409 */
410 if (!pfnHandler)
411 {
412 AssertMsgFailed(("No handler\n"));
413 return VERR_INVALID_PARAMETER;
414 }
415
416 /*
417 * Register
418 */
419 PDBGFINFO pInfo;
420 int rc = dbgfR3InfoRegister(pVM, pszName, pszDesc, 0, &pInfo);
421 if (VBOX_SUCCESS(rc))
422 {
423 pInfo->enmType = DBGFINFOTYPE_EXT;
424 pInfo->u.Ext.pfnHandler = pfnHandler;
425 pInfo->u.Ext.pvUser = pvUser;
426 RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
427 }
428
429 return rc;
430}
431
432
433/**
434 * Deregister one(/all) info handler(s) owned by a device.
435 *
436 * @returns VBox status code.
437 * @param pVM VM Handle.
438 * @param pDevIns Device instance.
439 * @param pszName The identifier of the info. If NULL all owned by the device.
440 */
441VMMR3DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName)
442{
443 LogFlow(("DBGFR3InfoDeregisterDevice: pDevIns=%p pszName=%p:{%s}\n", pDevIns, pszName, pszName));
444
445 /*
446 * Validate input.
447 */
448 if (!pDevIns)
449 {
450 AssertMsgFailed(("!pDevIns\n"));
451 return VERR_INVALID_PARAMETER;
452 }
453 size_t cchName = pszName ? strlen(pszName) : 0;
454
455 /*
456 * Enumerate the info handlers and free the requested entries.
457 */
458 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
459 AssertRC(rc);
460 rc = VERR_FILE_NOT_FOUND;
461 PDBGFINFO pPrev = NULL;
462 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
463 if (pszName)
464 {
465 /*
466 * Free a specific one.
467 */
468 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
469 if ( pInfo->enmType == DBGFINFOTYPE_DEV
470 && pInfo->u.Dev.pDevIns == pDevIns
471 && pInfo->cchName == cchName
472 && !strcmp(pInfo->szName, pszName))
473 {
474 if (pPrev)
475 pPrev->pNext = pInfo->pNext;
476 else
477 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
478 MMR3HeapFree(pInfo);
479 rc = VINF_SUCCESS;
480 break;
481 }
482 }
483 else
484 {
485 /*
486 * Free all owned by the driver.
487 */
488 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
489 if ( pInfo->enmType == DBGFINFOTYPE_DEV
490 && pInfo->u.Dev.pDevIns == pDevIns)
491 {
492 if (pPrev)
493 pPrev->pNext = pInfo->pNext;
494 else
495 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
496 MMR3HeapFree(pInfo);
497 pInfo = pPrev;
498 }
499 rc = VINF_SUCCESS;
500 }
501 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
502 AssertRC(rc2);
503 AssertRC(rc);
504 LogFlow(("DBGFR3InfoDeregisterDevice: returns %Vrc\n", rc));
505 return rc;
506}
507
508/**
509 * Deregister one(/all) info handler(s) owned by a driver.
510 *
511 * @returns VBox status code.
512 * @param pVM VM Handle.
513 * @param pDrvIns Driver instance.
514 * @param pszName The identifier of the info. If NULL all owned by the driver.
515 */
516VMMR3DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName)
517{
518 LogFlow(("DBGFR3InfoDeregisterDriver: pDrvIns=%p pszName=%p:{%s}\n", pDrvIns, pszName, pszName));
519
520 /*
521 * Validate input.
522 */
523 if (!pDrvIns)
524 {
525 AssertMsgFailed(("!pDrvIns\n"));
526 return VERR_INVALID_PARAMETER;
527 }
528 size_t cchName = pszName ? strlen(pszName) : 0;
529
530 /*
531 * Enumerate the info handlers and free the requested entries.
532 */
533 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
534 AssertRC(rc);
535 rc = VERR_FILE_NOT_FOUND;
536 PDBGFINFO pPrev = NULL;
537 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
538 if (pszName)
539 {
540 /*
541 * Free a specific one.
542 */
543 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
544 if ( pInfo->enmType == DBGFINFOTYPE_DRV
545 && pInfo->u.Drv.pDrvIns == pDrvIns
546 && pInfo->cchName == cchName
547 && !strcmp(pInfo->szName, pszName))
548 {
549 if (pPrev)
550 pPrev->pNext = pInfo->pNext;
551 else
552 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
553 MMR3HeapFree(pInfo);
554 rc = VINF_SUCCESS;
555 break;
556 }
557 }
558 else
559 {
560 /*
561 * Free all owned by the driver.
562 */
563 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
564 if ( pInfo->enmType == DBGFINFOTYPE_DRV
565 && pInfo->u.Drv.pDrvIns == pDrvIns)
566 {
567 if (pPrev)
568 pPrev->pNext = pInfo->pNext;
569 else
570 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
571 MMR3HeapFree(pInfo);
572 pInfo = pPrev;
573 }
574 rc = VINF_SUCCESS;
575 }
576 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
577 AssertRC(rc2);
578 AssertRC(rc);
579 LogFlow(("DBGFR3InfoDeregisterDriver: returns %Vrc\n", rc));
580 return rc;
581}
582
583
584/**
585 * Internal deregistration helper.
586 *
587 * @returns VBox status code.
588 * @param pVM VM Handle.
589 * @param pszName The identifier of the info.
590 * @param enmType The info owner type.
591 */
592static int dbgfR3InfoDeregister(PVM pVM, const char *pszName, DBGFINFOTYPE enmType)
593{
594 /*
595 * Validate input.
596 */
597 if (!pszName)
598 {
599 AssertMsgFailed(("!pszName\n"));
600 return VERR_INVALID_PARAMETER;
601 }
602
603 /*
604 * Find the info handler.
605 */
606 size_t cchName = strlen(pszName);
607 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
608 AssertRC(rc);
609 rc = VERR_FILE_NOT_FOUND;
610 PDBGFINFO pPrev = NULL;
611 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
612 for (; pInfo; pPrev = pInfo, pInfo = pInfo->pNext)
613 if ( pInfo->cchName == cchName
614 && !strcmp(pInfo->szName, pszName)
615 && pInfo->enmType == enmType)
616 {
617 if (pPrev)
618 pPrev->pNext = pInfo->pNext;
619 else
620 pVM->dbgf.s.pInfoFirst = pInfo->pNext;
621 MMR3HeapFree(pInfo);
622 rc = VINF_SUCCESS;
623 break;
624 }
625 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
626 AssertRC(rc2);
627 AssertRC(rc);
628 LogFlow(("dbgfR3InfoDeregister: returns %Vrc\n", rc));
629 return rc;
630}
631
632
633/**
634 * Deregister a info handler owned by an internal component.
635 *
636 * @returns VBox status code.
637 * @param pVM VM Handle.
638 * @param pszName The identifier of the info. If NULL all owned by the device.
639 */
640VMMR3DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName)
641{
642 LogFlow(("DBGFR3InfoDeregisterInternal: pszName=%p:{%s}\n", pszName, pszName));
643 return dbgfR3InfoDeregister(pVM, pszName, DBGFINFOTYPE_INT);
644}
645
646
647/**
648 * Deregister a info handler owned by an external component.
649 *
650 * @returns VBox status code.
651 * @param pVM VM Handle.
652 * @param pszName The identifier of the info. If NULL all owned by the device.
653 */
654VMMR3DECL(int) DBGFR3InfoDeregisterExternal(PVM pVM, const char *pszName)
655{
656 LogFlow(("DBGFR3InfoDeregisterExternal: pszName=%p:{%s}\n", pszName, pszName));
657 return dbgfR3InfoDeregister(pVM, pszName, DBGFINFOTYPE_EXT);
658}
659
660
661/**
662 * Display a piece of info writing to the supplied handler.
663 *
664 * @returns VBox status code.
665 * @param pVM VM handle.
666 * @param pszName The identifier of the info to display.
667 * @param pszArgs Arguments to the info handler.
668 * @param pHlp The output helper functions. If NULL the logger will be used.
669 */
670VMMR3DECL(int) DBGFR3Info(PVM pVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp)
671{
672 /*
673 * Validate input.
674 */
675 if (!pszName)
676 {
677 AssertMsgFailed(("!pszName\n"));
678 return VERR_INVALID_PARAMETER;
679 }
680 if (pHlp)
681 {
682 if ( !pHlp->pfnPrintf
683 || !pHlp->pfnPrintfV)
684 {
685 AssertMsgFailed(("A pHlp member is missing!\n"));
686 return VERR_INVALID_PARAMETER;
687 }
688 }
689 else
690 pHlp = &g_dbgfR3InfoLogHlp;
691
692 /*
693 * Find the info handler.
694 */
695 size_t cchName = strlen(pszName);
696 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
697 AssertRC(rc);
698 PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst;
699 for (; pInfo; pInfo = pInfo->pNext)
700 if ( pInfo->cchName == cchName
701 && !memcmp(pInfo->szName, pszName, cchName))
702 break;
703 if (pInfo)
704 {
705 /*
706 * Found it.
707 * Make a copy of it on the stack so we can leave the crit sect.
708 * Switch on the type and invoke the handler.
709 */
710 DBGFINFO Info = *pInfo;
711 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
712 AssertRC(rc);
713 rc = VINF_SUCCESS;
714 PVMREQ pReq = NULL;
715 switch (Info.enmType)
716 {
717 case DBGFINFOTYPE_DEV:
718 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
719 rc = VMR3ReqCallVoid(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)Info.u.Dev.pfnHandler, 3, Info.u.Dev.pDevIns, pHlp, pszArgs);
720 else
721 Info.u.Dev.pfnHandler(Info.u.Dev.pDevIns, pHlp, pszArgs);
722 break;
723
724 case DBGFINFOTYPE_DRV:
725 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
726 rc = VMR3ReqCallVoid(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)Info.u.Drv.pfnHandler, 3, Info.u.Drv.pDrvIns, pHlp, pszArgs);
727 else
728 Info.u.Drv.pfnHandler(Info.u.Drv.pDrvIns, pHlp, pszArgs);
729 break;
730
731 case DBGFINFOTYPE_INT:
732 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
733 rc = VMR3ReqCallVoid(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)Info.u.Int.pfnHandler, 3, pVM, pHlp, pszArgs);
734 else
735 Info.u.Int.pfnHandler(pVM, pHlp, pszArgs);
736 break;
737
738 case DBGFINFOTYPE_EXT:
739 if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT)
740 rc = VMR3ReqCallVoid(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)Info.u.Ext.pfnHandler, 3, Info.u.Ext.pvUser, pHlp, pszArgs);
741 else
742 Info.u.Ext.pfnHandler(Info.u.Ext.pvUser, pHlp, pszArgs);
743 break;
744
745 default:
746 AssertMsgFailed(("Invalid info type enmType=%d\n", Info.enmType));
747 rc = VERR_INTERNAL_ERROR;
748 break;
749 }
750 VMR3ReqFree(pReq);
751 }
752 else
753 {
754 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
755 AssertRC(rc);
756 rc = VERR_FILE_NOT_FOUND;
757 }
758 return rc;
759}
760
761
762/**
763 * Enumerate all the register info handlers.
764 *
765 * @returns VBox status code.
766 * @param pVM VM handle.
767 * @param pfnCallback Pointer to callback function.
768 * @param pvUser User argument to pass to the callback.
769 */
770VMMR3DECL(int) DBGFR3InfoEnum(PVM pVM, PFNDBGFINFOENUM pfnCallback, void *pvUser)
771{
772 LogFlow(("DBGFR3InfoLog: pfnCallback=%p pvUser=%p\n", pfnCallback, pvUser));
773
774 /*
775 * Validate input.
776 */
777 if (!pfnCallback)
778 {
779 AssertMsgFailed(("!pfnCallback\n"));
780 return VERR_INVALID_PARAMETER;
781 }
782
783 /*
784 * Enter and enumerate.
785 */
786 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
787 AssertRC(rc);
788
789 rc = VINF_SUCCESS;
790 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; VBOX_SUCCESS(rc) && pInfo; pInfo = pInfo->pNext)
791 rc = pfnCallback(pVM, pInfo->szName, pInfo->pszDesc, pvUser);
792
793 /*
794 * Leave and exit.
795 */
796 int rc2 = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
797 AssertRC(rc2);
798
799 LogFlow(("DBGFR3InfoLog: returns %Vrc\n", rc));
800 return rc;
801}
802
803
804/**
805 * Info handler, internal version.
806 *
807 * @param pVM The VM handle.
808 * @param pHlp Callback functions for doing output.
809 * @param pszArgs Argument string. Optional and specific to the handler.
810 */
811static DECLCALLBACK(void) dbgfR3InfoHelp(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
812{
813 LogFlow(("dbgfR3InfoHelp: pszArgs=%s\n", pszArgs));
814
815 /*
816 * Enter and enumerate.
817 */
818 int rc = RTCritSectEnter(&pVM->dbgf.s.InfoCritSect);
819 AssertRC(rc);
820
821 if (pszArgs && *pszArgs)
822 {
823 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext)
824 {
825 const char *psz = strstr(pszArgs, pInfo->szName);
826 if ( psz
827 && ( psz == pszArgs
828 || isspace(psz[-1]))
829 && ( !psz[pInfo->cchName]
830 || isspace(psz[pInfo->cchName])))
831 pHlp->pfnPrintf(pHlp, "%-16s %s\n",
832 pInfo->szName, pInfo->pszDesc);
833 }
834 }
835 else
836 {
837 for (PDBGFINFO pInfo = pVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext)
838 pHlp->pfnPrintf(pHlp, "%-16s %s\n",
839 pInfo->szName, pInfo->pszDesc);
840 }
841
842 /*
843 * Leave and exit.
844 */
845 rc = RTCritSectLeave(&pVM->dbgf.s.InfoCritSect);
846 AssertRC(rc);
847}
848
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