/** * Entry point. */ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) { RT_NOREF1(envp); int rcRet = 0; /* error count. */ RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB); /* * Create empty VM. */ PVM pVM; PUVM pUVM; int rc = VMR3Create(1, NULL, NULL, NULL, NULL, NULL, &pVM, &pUVM); if (RT_SUCCESS(rc)) { /* * Do testing. */ rc = VMR3ReqCallVoidWaitU(pUVM, VMCPUID_ANY, (PFNRT)doit, 1, pVM); AssertRC(rc); STAMR3Dump(pUVM, "*"); /* * Cleanup. */ rc = VMR3PowerOff(pUVM); if (!RT_SUCCESS(rc)) { RTPrintf(TESTCASE ": error: failed to power off vm! rc=%Rrc\n", rc); rcRet++; } rc = VMR3Destroy(pUVM); if (!RT_SUCCESS(rc)) { RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Rrc\n", rc); rcRet++; } VMR3ReleaseUVM(pUVM); } else { RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Rrc\n", rc); rcRet++; } return rcRet; }
/** * Display several info items. * * This is intended used by the fatal error dump only. * * @returns * @param pVM Pointer to the VM. * @param pszIncludePat Simple string pattern of info items to include. * @param pszExcludePat Simple string pattern of info items to exclude. * @param pszSepFmt Item separator format string. The item name will be * given as parameter. * @param pHlp The output helper functions. If NULL the logger * will be used. * * @threads EMT */ VMMR3_INT_DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat, const char *pszSepFmt, PCDBGFINFOHLP pHlp) { /* * Validate input. */ PUVM pUVM = pVM->pUVM; VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); AssertPtrReturn(pszIncludePat, VERR_INVALID_POINTER); AssertPtrReturn(pszExcludePat, VERR_INVALID_POINTER); if (pHlp) { AssertPtrReturn(pHlp->pfnPrintf, VERR_INVALID_POINTER); AssertPtrReturn(pHlp->pfnPrintfV, VERR_INVALID_POINTER); } else pHlp = &g_dbgfR3InfoLogHlp; size_t const cchIncludePat = strlen(pszIncludePat); size_t const cchExcludePat = strlen(pszExcludePat); const char *pszArgs = ""; /* * Enumerate the info handlers and call the ones matching. * Note! We won't leave the critical section here... */ int rc = RTCritSectEnter(&pUVM->dbgf.s.InfoCritSect); AssertRC(rc); rc = VWRN_NOT_FOUND; for (PDBGFINFO pInfo = pUVM->dbgf.s.pInfoFirst; pInfo; pInfo = pInfo->pNext) { if ( RTStrSimplePatternMultiMatch(pszIncludePat, cchIncludePat, pInfo->szName, pInfo->cchName, NULL) && !RTStrSimplePatternMultiMatch(pszExcludePat, cchExcludePat, pInfo->szName, pInfo->cchName, NULL)) { pHlp->pfnPrintf(pHlp, pszSepFmt, pInfo->szName); rc = VINF_SUCCESS; switch (pInfo->enmType) { case DBGFINFOTYPE_DEV: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, VMCPUID_ANY, (PFNRT)pInfo->u.Dev.pfnHandler, 3, pInfo->u.Dev.pDevIns, pHlp, pszArgs); else pInfo->u.Dev.pfnHandler(pInfo->u.Dev.pDevIns, pHlp, pszArgs); break; case DBGFINFOTYPE_DRV: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, VMCPUID_ANY, (PFNRT)pInfo->u.Drv.pfnHandler, 3, pInfo->u.Drv.pDrvIns, pHlp, pszArgs); else pInfo->u.Drv.pfnHandler(pInfo->u.Drv.pDrvIns, pHlp, pszArgs); break; case DBGFINFOTYPE_INT: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, VMCPUID_ANY, (PFNRT)pInfo->u.Int.pfnHandler, 3, pVM, pHlp, pszArgs); else pInfo->u.Int.pfnHandler(pVM, pHlp, pszArgs); break; case DBGFINFOTYPE_EXT: if (pInfo->fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, VMCPUID_ANY, (PFNRT)pInfo->u.Ext.pfnHandler, 3, pInfo->u.Ext.pvUser, pHlp, pszArgs); else pInfo->u.Ext.pfnHandler(pInfo->u.Ext.pvUser, pHlp, pszArgs); break; default: AssertMsgFailedReturn(("Invalid info type enmType=%d\n", pInfo->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); } } } int rc2 = RTCritSectLeave(&pUVM->dbgf.s.InfoCritSect); AssertRC(rc2); return rc; }
/** * Worker for DBGFR3Info and DBGFR3InfoEx. * * @returns VBox status code. * @param pUVM The user mode VM handle. * @param idCpu Which CPU to run EMT bound handlers on. VMCPUID_ANY or * a valid CPU ID. * @param pszName What to dump. * @param pszArgs Arguments, optional. * @param pHlp Output helper, optional. */ static DECLCALLBACK(int) dbgfR3Info(PUVM pUVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp) { /* * Validate input. */ AssertPtrReturn(pszName, VERR_INVALID_POINTER); AssertPtrNullReturn(pszArgs, VERR_INVALID_POINTER); if (pHlp) { AssertPtrReturn(pHlp, VERR_INVALID_PARAMETER); AssertPtrReturn(pHlp->pfnPrintf, VERR_INVALID_PARAMETER); AssertPtrReturn(pHlp->pfnPrintfV, VERR_INVALID_PARAMETER); } else pHlp = &g_dbgfR3InfoLogHlp; /* * Find the info handler. */ size_t cchName = strlen(pszName); int rc = RTCritSectEnter(&pUVM->dbgf.s.InfoCritSect); AssertRC(rc); PDBGFINFO pInfo = pUVM->dbgf.s.pInfoFirst; for (; pInfo; pInfo = pInfo->pNext) if ( pInfo->cchName == cchName && !memcmp(pInfo->szName, pszName, cchName)) break; if (pInfo) { /* * Found it. * Make a copy of it on the stack so we can leave the crit sect. * Switch on the type and invoke the handler. */ DBGFINFO Info = *pInfo; rc = RTCritSectLeave(&pUVM->dbgf.s.InfoCritSect); AssertRC(rc); rc = VINF_SUCCESS; switch (Info.enmType) { case DBGFINFOTYPE_DEV: if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, idCpu, (PFNRT)Info.u.Dev.pfnHandler, 3, Info.u.Dev.pDevIns, pHlp, pszArgs); else Info.u.Dev.pfnHandler(Info.u.Dev.pDevIns, pHlp, pszArgs); break; case DBGFINFOTYPE_DRV: if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, idCpu, (PFNRT)Info.u.Drv.pfnHandler, 3, Info.u.Drv.pDrvIns, pHlp, pszArgs); else Info.u.Drv.pfnHandler(Info.u.Drv.pDrvIns, pHlp, pszArgs); break; case DBGFINFOTYPE_INT: if (RT_VALID_PTR(pUVM->pVM)) { if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, idCpu, (PFNRT)Info.u.Int.pfnHandler, 3, pUVM->pVM, pHlp, pszArgs); else Info.u.Int.pfnHandler(pUVM->pVM, pHlp, pszArgs); } else rc = VERR_INVALID_VM_HANDLE; break; case DBGFINFOTYPE_EXT: if (Info.fFlags & DBGFINFO_FLAGS_RUN_ON_EMT) rc = VMR3ReqCallVoidWaitU(pUVM, idCpu, (PFNRT)Info.u.Ext.pfnHandler, 3, Info.u.Ext.pvUser, pHlp, pszArgs); else Info.u.Ext.pfnHandler(Info.u.Ext.pvUser, pHlp, pszArgs); break; default: AssertMsgFailedReturn(("Invalid info type enmType=%d\n", Info.enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); } } else { rc = RTCritSectLeave(&pUVM->dbgf.s.InfoCritSect); AssertRC(rc); rc = VERR_FILE_NOT_FOUND; } return rc; }