/**
 * 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);
}
Example #2
0
/**
 * 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;
}
Example #3
0
/**
 * 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;
}
Example #4
0
/**
 * 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);
}