/** * Deregisters a guest OS digger previously registered by DBGFR3OSRegister. * * @returns VBox status code. * * @param pVM Pointer to the shared VM structure. * @param pReg The registration structure. * @thread Any. */ VMMR3DECL(int) DBGFR3OSDeregister(PVM pVM, PCDBGFOSREG pReg) { /* * Validate input. */ VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); AssertPtrReturn(pReg, VERR_INVALID_POINTER); AssertReturn(pReg->u32Magic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC); AssertReturn(pReg->u32EndMagic == DBGFOSREG_MAGIC, VERR_INVALID_MAGIC); AssertReturn(RTStrEnd(&pReg->szName[0], sizeof(pReg->szName)), VERR_INVALID_NAME); DBGF_OS_READ_LOCK(pVM); PDBGFOS pOS; for (pOS = pVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext) if (pOS->pReg == pReg) break; DBGF_OS_READ_LOCK(pVM); if (!pOS) { Log(("DBGFR3OSDeregister: %s -> VERR_NOT_FOUND\n", pReg->szName)); return VERR_NOT_FOUND; } /* * Pass it on to EMT(0). */ return VMR3ReqPriorityCallWait(pVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSDeregister, 2, pVM, pReg); }
/** * EMT worker function for DBGFR3OSRegister. * * @returns VBox status code. * @param pUVM The user mode VM handle. * @param pReg The registration structure. */ static DECLCALLBACK(int) dbgfR3OSRegister(PUVM pUVM, PDBGFOSREG pReg) { /* more validations. */ DBGF_OS_READ_LOCK(pUVM); PDBGFOS pOS; for (pOS = pUVM->dbgf.s.pOSHead; pOS; pOS = pOS->pNext) if (!strcmp(pOS->pReg->szName, pReg->szName)) { DBGF_OS_READ_UNLOCK(pUVM); Log(("dbgfR3OSRegister: %s -> VERR_ALREADY_LOADED\n", pReg->szName)); return VERR_ALREADY_LOADED; } DBGF_OS_READ_UNLOCK(pUVM); /* * Allocate a new structure, call the constructor and link it into the list. */ pOS = (PDBGFOS)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_OS, RT_OFFSETOF(DBGFOS, abData[pReg->cbData])); AssertReturn(pOS, VERR_NO_MEMORY); pOS->pReg = pReg; int rc = pOS->pReg->pfnConstruct(pUVM, pOS->abData); if (RT_SUCCESS(rc)) { DBGF_OS_WRITE_LOCK(pUVM); pOS->pNext = pUVM->dbgf.s.pOSHead; pUVM->dbgf.s.pOSHead = pOS; DBGF_OS_WRITE_UNLOCK(pUVM); } else { if (pOS->pReg->pfnDestruct) pOS->pReg->pfnDestruct(pUVM, pOS->abData); MMR3HeapFree(pOS); } return VINF_SUCCESS; }
/** * EMT worker function for DBGFR3OSQueryNameAndVersion * * @returns VBox status code. * @param pUVM The user mode VM handle. * @param pszName Where to store the OS name. Optional. * @param cchName The size of the name buffer. * @param pszVersion Where to store the version string. Optional. * @param cchVersion The size of the version buffer. */ static DECLCALLBACK(int) dbgfR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion) { /* * Any known OS? */ DBGF_OS_READ_LOCK(pUVM); if (pUVM->dbgf.s.pCurOS) { int rc = VINF_SUCCESS; if (pszName && cchName) { size_t cch = strlen(pUVM->dbgf.s.pCurOS->pReg->szName); if (cchName > cch) memcpy(pszName, pUVM->dbgf.s.pCurOS->pReg->szName, cch + 1); else { memcpy(pszName, pUVM->dbgf.s.pCurOS->pReg->szName, cchName - 1); pszName[cchName - 1] = '\0'; rc = VINF_BUFFER_OVERFLOW; } } if (pszVersion && cchVersion) { int rc2 = pUVM->dbgf.s.pCurOS->pReg->pfnQueryVersion(pUVM, pUVM->dbgf.s.pCurOS->abData, pszVersion, cchVersion); if (RT_FAILURE(rc2) || rc == VINF_SUCCESS) rc = rc2; } DBGF_OS_READ_UNLOCK(pUVM); return rc; } DBGF_OS_READ_UNLOCK(pUVM); return VERR_DBGF_OS_NOT_DETCTED; }
/** * EMT worker for DBGFR3OSQueryInterface. * * @param pUVM The user mode VM handle. * @param enmIf The interface identifier. * @param ppvIf Where to store the interface pointer on success. */ static DECLCALLBACK(void) dbgfR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf, void **ppvIf) { AssertPtrReturnVoid(ppvIf); *ppvIf = NULL; AssertReturnVoid(enmIf > DBGFOSINTERFACE_INVALID && enmIf < DBGFOSINTERFACE_END); UVM_ASSERT_VALID_EXT_RETURN_VOID(pUVM); /* * Forward the query to the current OS. */ DBGF_OS_READ_LOCK(pUVM); PDBGFOS pOS = pUVM->dbgf.s.pCurOS; if (pOS) { void *pvDiggerIf; pvDiggerIf = pOS->pReg->pfnQueryInterface(pUVM, pUVM->dbgf.s.pCurOS->abData, enmIf); if (pvDiggerIf) { /* * Do we have an EMT wrapper for this interface already? * * We ASSUME the interfaces are static and not dynamically allocated * for each QueryInterface call. */ PDBGFOSEMTWRAPPER pWrapper = pOS->pWrapperHead; while ( pWrapper != NULL && ( pWrapper->uDigger.pv != pvDiggerIf && pWrapper->enmIf != enmIf) ) pWrapper = pWrapper->pNext; if (pWrapper) { *ppvIf = &pWrapper->uWrapper; DBGF_OS_READ_UNLOCK(pUVM); return; } DBGF_OS_READ_UNLOCK(pUVM); /* * Create a wrapper. */ int rc = MMR3HeapAllocExU(pUVM, MM_TAG_DBGF_OS, sizeof(*pWrapper), (void **)&pWrapper); if (RT_FAILURE(rc)) return; pWrapper->uDigger.pv = pvDiggerIf; pWrapper->pUVM = pUVM; pWrapper->enmIf = enmIf; switch (enmIf) { case DBGFOSINTERFACE_DMESG: pWrapper->uWrapper.Dmesg.u32Magic = DBGFOSIDMESG_MAGIC; pWrapper->uWrapper.Dmesg.pfnQueryKernelLog = dbgfR3OSEmtIDmesg_QueryKernelLog; pWrapper->uWrapper.Dmesg.u32EndMagic = DBGFOSIDMESG_MAGIC; break; default: AssertFailed(); MMR3HeapFree(pWrapper); return; } DBGF_OS_WRITE_LOCK(pUVM); if (pUVM->dbgf.s.pCurOS == pOS) { pWrapper->pNext = pOS->pWrapperHead; pOS->pWrapperHead = pWrapper; *ppvIf = &pWrapper->uWrapper; DBGF_OS_WRITE_UNLOCK(pUVM); } else { DBGF_OS_WRITE_UNLOCK(pUVM); MMR3HeapFree(pWrapper); } return; } } DBGF_OS_READ_UNLOCK(pUVM); }