Ejemplo n.º 1
0
/**
 * Registers a guest OS digger.
 *
 * This will instantiate an instance of the digger and add it
 * to the list for us in the next call to DBGFR3OSDetect().
 *
 * @returns VBox status code.
 * @param   pVM     Pointer to the shared VM structure.
 * @param   pReg    The registration structure.
 * @thread  Any.
 */
VMMR3DECL(int) DBGFR3OSRegister(PVM pVM, PCDBGFOSREG pReg)
{
    /*
     * Validate intput.
     */
    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(!pReg->fFlags, VERR_INVALID_PARAMETER);
    AssertReturn(pReg->cbData < _2G, VERR_INVALID_PARAMETER);
    AssertReturn(pReg->szName[0], VERR_INVALID_NAME);
    AssertReturn(RTStrEnd(&pReg->szName[0], sizeof(pReg->szName)), VERR_INVALID_NAME);
    AssertPtrReturn(pReg->pfnConstruct, VERR_INVALID_POINTER);
    AssertPtrNullReturn(pReg->pfnDestruct, VERR_INVALID_POINTER);
    AssertPtrReturn(pReg->pfnProbe, VERR_INVALID_POINTER);
    AssertPtrReturn(pReg->pfnInit, VERR_INVALID_POINTER);
    AssertPtrReturn(pReg->pfnRefresh, VERR_INVALID_POINTER);
    AssertPtrReturn(pReg->pfnTerm, VERR_INVALID_POINTER);
    AssertPtrReturn(pReg->pfnQueryVersion, VERR_INVALID_POINTER);
    AssertPtrReturn(pReg->pfnQueryInterface, VERR_INVALID_POINTER);

    /*
     * Pass it on to EMT(0).
     */
    return VMR3ReqPriorityCallWait(pVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3OSRegister, 2, pVM, pReg);
}
Ejemplo n.º 2
0
/**
 * Query an address space by name.
 *
 * @returns Retained address space handle if found, NIL_RTDBGAS if not.
 *
 * @param   pVM         Pointer to the VM.
 * @param   pszName     The name.
 */
VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName)
{
    /*
     * Validate the input.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS);
    AssertPtrReturn(pszName, NIL_RTDBGAS);
    AssertReturn(*pszName, NIL_RTDBGAS);

    /*
     * Look it up in the string space and retain the result.
     */
    RTDBGAS hDbgAs = NIL_RTDBGAS;
    DBGF_AS_DB_LOCK_READ(pVM);

    PRTSTRSPACECORE pNode = RTStrSpaceGet(&pVM->dbgf.s.AsNameSpace, pszName);
    if (pNode)
    {
        PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, NameCore);
        hDbgAs = (RTDBGAS)pDbNode->HandleCore.Key;
        uint32_t cRefs = RTDbgAsRetain(hDbgAs);
        if (RT_UNLIKELY(cRefs == UINT32_MAX))
            hDbgAs = NIL_RTDBGAS;
    }
    DBGF_AS_DB_UNLOCK_READ(pVM);

    return hDbgAs;
}
Ejemplo n.º 3
0
/**
 * Converts an address to a guest physical address.
 *
 * @returns VBox status code.
 * @retval  VINF_SUCCESS
 * @retval  VERR_INVALID_PARAMETER if the address is invalid.
 * @retval  VERR_INVALID_STATE if the VM is being terminated or if the virtual
 *          CPU handle is invalid.
 * @retval  VERR_NOT_SUPPORTED is the type of address cannot be converted.
 * @retval  VERR_PAGE_NOT_PRESENT
 * @retval  VERR_PAGE_TABLE_NOT_PRESENT
 * @retval  VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
 * @retval  VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
 *
 * @param   pVM             The VM handle.
 * @param   idCpu           The ID of the CPU context to convert virtual
 *                          addresses.
 * @param   pAddress        The address.
 * @param   pGCPhys         Where to return the physical address.
 */
VMMR3DECL(int)  DBGFR3AddrToPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys)
{
    /*
     * Parameter validation.
     */
    AssertPtr(pGCPhys);
    *pGCPhys = NIL_RTGCPHYS;
    AssertPtr(pAddress);
    AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_STATE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_PARAMETER);

    /*
     * Convert by address type.
     */
    int rc;
    if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
        rc = VERR_NOT_SUPPORTED;
    else if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
    {
        *pGCPhys = pAddress->FlatPtr;
        rc = VINF_SUCCESS;
    }
    else
    {
        PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
        if (VMCPU_IS_EMT(pVCpu))
            rc = dbgfR3AddrToPhysOnVCpu(pVCpu, pAddress, pGCPhys);
        else
            rc = VMR3ReqCallWait(pVCpu->pVMR3, pVCpu->idCpu,
                                 (PFNRT)dbgfR3AddrToPhysOnVCpu, 3, pVCpu, pAddress, pGCPhys);
    }
    return rc;
}
Ejemplo n.º 4
0
/**
 * Changes an alias to point to a new address space.
 *
 * Not all the aliases can be changed, currently it's only DBGF_AS_GLOBAL
 * and DBGF_AS_KERNEL.
 *
 * @returns VBox status code.
 * @param   pVM             Pointer to the VM.
 * @param   hAlias          The alias to change.
 * @param   hAliasFor       The address space hAlias should be an alias for.
 *                          This can be an alias. The caller's reference to
 *                          this address space will NOT be consumed.
 */
VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor)
{
    /*
     * Input validation.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertMsgReturn(DBGF_AS_IS_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER);
    AssertMsgReturn(!DBGF_AS_IS_FIXED_ALIAS(hAlias), ("%p\n", hAlias), VERR_INVALID_PARAMETER);
    RTDBGAS hRealAliasFor = DBGFR3AsResolveAndRetain(pVM, hAliasFor);
    if (hRealAliasFor == NIL_RTDBGAS)
        return VERR_INVALID_HANDLE;

    /*
     * Make sure the handle has is already in the database.
     */
    int rc = VERR_NOT_FOUND;
    DBGF_AS_DB_LOCK_WRITE(pVM);
    if (RTAvlPVGet(&pVM->dbgf.s.AsHandleTree, hRealAliasFor))
    {
        /*
         * Update the alias table and release the current address space.
         */
        RTDBGAS hAsOld;
        ASMAtomicXchgHandle(&pVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(hAlias)], hRealAliasFor, &hAsOld);
        uint32_t cRefs = RTDbgAsRelease(hAsOld);
        Assert(cRefs > 0); Assert(cRefs != UINT32_MAX); NOREF(cRefs);
        rc = VINF_SUCCESS;
    }
    DBGF_AS_DB_UNLOCK_WRITE(pVM);

    return rc;
}
Ejemplo n.º 5
0
/**
 * Resolves the address space handle into a real handle if it's an alias,
 * and retains whatever it is.
 *
 * @returns Real address space handle. NIL_RTDBGAS if invalid handle.
 *
 * @param   pVM             Pointer to the VM.
 * @param   hAlias          The possibly address space alias.
 */
VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias)
{
    VM_ASSERT_VALID_EXT_RETURN(pVM, NULL);
    AssertCompileNS(NIL_RTDBGAS == (RTDBGAS)0);

    uint32_t    cRefs;
    uintptr_t   iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias);
    if (iAlias < DBGF_AS_COUNT)
    {
        if (DBGF_AS_IS_FIXED_ALIAS(hAlias))
        {
            /* Perform lazy address space population. */
            if (!pVM->dbgf.s.afAsAliasPopuplated[iAlias])
                dbgfR3AsLazyPopulate(pVM, hAlias);

            /* Won't ever change, no need to grab the lock. */
            hAlias = pVM->dbgf.s.ahAsAliases[iAlias];
            cRefs = RTDbgAsRetain(hAlias);
        }
        else
        {
            /* May change, grab the lock so we can read it safely. */
            DBGF_AS_DB_LOCK_READ(pVM);
            hAlias = pVM->dbgf.s.ahAsAliases[iAlias];
            cRefs = RTDbgAsRetain(hAlias);
            DBGF_AS_DB_UNLOCK_READ(pVM);
        }
    }
    else
        /* Not an alias, just retain it. */
        cRefs = RTDbgAsRetain(hAlias);

    return cRefs != UINT32_MAX ? hAlias : NIL_RTDBGAS;
}
Ejemplo n.º 6
0
/**
 * 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);
}
Ejemplo n.º 7
0
/**
 * Converts an address to a host physical address.
 *
 * @returns VBox status code.
 * @retval  VINF_SUCCESS
 * @retval  VERR_INVALID_PARAMETER if the address is invalid.
 * @retval  VERR_INVALID_STATE if the VM is being terminated or if the virtual
 *          CPU handle is invalid.
 * @retval  VERR_NOT_SUPPORTED is the type of address cannot be converted.
 * @retval  VERR_PAGE_NOT_PRESENT
 * @retval  VERR_PAGE_TABLE_NOT_PRESENT
 * @retval  VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
 * @retval  VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
 * @retval  VERR_PGM_PHYS_PAGE_RESERVED
 * @retval  VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
 *
 * @param   pVM             The VM handle.
 * @param   idCpu           The ID of the CPU context to convert virtual
 *                          addresses.
 * @param   pAddress        The address.
 * @param   pHCPhys         Where to return the physical address.
 */
VMMR3DECL(int)  DBGFR3AddrToHostPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys)
{
    /*
     * Parameter validation.
     */
    AssertPtr(pHCPhys);
    *pHCPhys = NIL_RTHCPHYS;
    AssertPtr(pAddress);
    AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_STATE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_PARAMETER);

    /*
     * Convert it if we can.
     */
    int rc;
    if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
        rc = VERR_NOT_SUPPORTED; /** @todo implement this */
    else
    {
        RTGCPHYS GCPhys;
        rc = DBGFR3AddrToPhys(pVM, idCpu, pAddress, &GCPhys);
        if (RT_SUCCESS(rc))
            rc = PGMPhysGCPhys2HCPhys(pVM, pAddress->FlatPtr, pHCPhys);
    }
    return rc;
}
Ejemplo n.º 8
0
/**
 * Query an address space by process ID.
 *
 * @returns Retained address space handle if found, NIL_RTDBGAS if not.
 *
 * @param   pVM         Pointer to the VM.
 * @param   ProcId      The process ID.
 */
VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId)
{
    /*
     * Validate the input.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_RTDBGAS);
    AssertReturn(ProcId != NIL_RTPROCESS, NIL_RTDBGAS);

    /*
     * Look it up in the PID tree and retain the result.
     */
    RTDBGAS hDbgAs = NIL_RTDBGAS;
    DBGF_AS_DB_LOCK_READ(pVM);

    PAVLU32NODECORE pNode = RTAvlU32Get(&pVM->dbgf.s.AsPidTree, ProcId);
    if (pNode)
    {
        PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, PidCore);
        hDbgAs = (RTDBGAS)pDbNode->HandleCore.Key;
        uint32_t cRefs = RTDbgAsRetain(hDbgAs);
        if (RT_UNLIKELY(cRefs == UINT32_MAX))
            hDbgAs = NIL_RTDBGAS;
    }
    DBGF_AS_DB_UNLOCK_READ(pVM);

    return hDbgAs;
}
Ejemplo n.º 9
0
/**
 * Scan guest memory for an exact byte string.
 *
 * @returns VBox status codes:
 * @retval  VINF_SUCCESS and *pGCPtrHit on success.
 * @retval  VERR_DBGF_MEM_NOT_FOUND if not found.
 * @retval  VERR_INVALID_POINTER if any of the pointer arguments are invalid.
 * @retval  VERR_INVALID_ARGUMENT if any other arguments are invalid.
 *
 * @param   pVM         The VM handle.
 * @param   idCpu       The ID of the CPU context to search in.
 * @param   pAddress    Where to store the mixed address.
 * @param   cbRange     The number of bytes to scan.
 * @param   uAlign      The alignment restriction imposed on the result.
 *                      Usually set to 1.
 * @param   pvNeedle    What to search for - exact search.
 * @param   cbNeedle    Size of the search byte string.
 * @param   pHitAddress Where to put the address of the first hit.
 *
 * @thread  Any thread.
 */
VMMR3DECL(int) DBGFR3MemScan(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, RTGCUINTPTR uAlign,
                             const void *pvNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress)
{
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    return VMR3ReqPriorityCallWait(pVM, idCpu, (PFNRT)dbgfR3MemScan, 8,
                                   pVM, idCpu, pAddress, &cbRange, &uAlign, pvNeedle, cbNeedle, pHitAddress);

}
Ejemplo n.º 10
0
/**
 * Worker for DBGFR3SelQueryInfo that calls into SELM.
 */
static DECLCALLBACK(int) dbgfR3SelQueryInfo(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo)
{
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);

    /*
     * Make the query.
     */
    int rc;
    if (!(fFlags & DBGFSELQI_FLAGS_DT_SHADOW))
    {
        PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
        VMCPU_ASSERT_EMT(pVCpu);
        rc = SELMR3GetSelectorInfo(pVM, pVCpu, Sel, pSelInfo);

        /*
         * 64-bit mode HACKS for making data and stack selectors wide open when
         * queried. This is voodoo magic.
         */
        if (fFlags & DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE)
        {
            /* Expand 64-bit data and stack selectors. The check is a bit bogus... */
            if (    RT_SUCCESS(rc)
                &&  (pSelInfo->fFlags & (  DBGFSELINFO_FLAGS_LONG_MODE | DBGFSELINFO_FLAGS_REAL_MODE | DBGFSELINFO_FLAGS_PROT_MODE
                                         | DBGFSELINFO_FLAGS_GATE      | DBGFSELINFO_FLAGS_HYPER
                                         | DBGFSELINFO_FLAGS_INVALID   | DBGFSELINFO_FLAGS_NOT_PRESENT))
                     == DBGFSELINFO_FLAGS_LONG_MODE
                &&  pSelInfo->cbLimit != ~(RTGCPTR)0
                &&  CPUMIsGuestIn64BitCode(pVCpu) )
            {
                pSelInfo->GCPtrBase = 0;
                pSelInfo->cbLimit   = ~(RTGCPTR)0;
            }
            else if (   Sel == 0
                     && CPUMIsGuestIn64BitCode(pVCpu))
            {
                pSelInfo->GCPtrBase = 0;
                pSelInfo->cbLimit   = ~(RTGCPTR)0;
                pSelInfo->Sel       = 0;
                pSelInfo->SelGate   = 0;
                pSelInfo->fFlags    = DBGFSELINFO_FLAGS_LONG_MODE;
                pSelInfo->u.Raw64.Gen.u1Present  = 1;
                pSelInfo->u.Raw64.Gen.u1Long     = 1;
                pSelInfo->u.Raw64.Gen.u1DescType = 1;
                rc = VINF_SUCCESS;
            }
        }
    }
    else
    {
        if (HMIsEnabled(pVM))
            rc = VERR_INVALID_STATE;
        else
            rc = SELMR3GetShadowSelectorInfo(pVM, Sel, pSelInfo);
    }
    return rc;
}
Ejemplo n.º 11
0
/**
 * Resolves the address space handle into a real handle if it's an alias.
 *
 * @returns Real address space handle. NIL_RTDBGAS if invalid handle.
 *
 * @param   pVM             Pointer to the VM.
 * @param   hAlias          The possibly address space alias.
 *
 * @remarks Doesn't take any locks.
 */
VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias)
{
    VM_ASSERT_VALID_EXT_RETURN(pVM, NULL);
    AssertCompileNS(NIL_RTDBGAS == (RTDBGAS)0);

    uintptr_t   iAlias = DBGF_AS_ALIAS_2_INDEX(hAlias);
    if (iAlias < DBGF_AS_COUNT)
        ASMAtomicReadHandle(&pVM->dbgf.s.ahAsAliases[iAlias], &hAlias);
    return hAlias;
}
Ejemplo n.º 12
0
/**
 * Attaches a debugger to the specified VM.
 *
 * Only one debugger at a time.
 *
 * @returns VBox status code.
 * @param   pVM     Pointer to the VM.
 */
VMMR3DECL(int) DBGFR3Attach(PVM pVM)
{
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);

    /*
     * Call the VM, use EMT for serialization.
     */
    /** @todo SMP */
    return VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3Attach, 1, pVM);
}
Ejemplo n.º 13
0
/**
 * Scan guest memory for an exact byte string.
 *
 * @returns VBox status code.
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The ID of the CPU context to search in.
 * @param   pAddress    Where to store the mixed address.
 * @param   puAlign     The alignment restriction imposed on the search result.
 * @param   pcbRange    The number of bytes to scan. Passed as a pointer because
 *                      it may be 64-bit.
 * @param   pabNeedle   What to search for - exact search.
 * @param   cbNeedle    Size of the search byte string.
 * @param   pHitAddress Where to put the address of the first hit.
 */
static DECLCALLBACK(int) dbgfR3MemScan(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, PCRTGCUINTPTR pcbRange,
                                       RTGCUINTPTR *puAlign, const uint8_t *pabNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress)
{
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    Assert(idCpu == VMMGetCpuId(pVM));

    /*
     * Validate the input we use, PGM does the rest.
     */
    RTGCUINTPTR cbRange = *pcbRange;
    if (!DBGFR3AddrIsValid(pUVM, pAddress))
        return VERR_INVALID_POINTER;
    if (!VALID_PTR(pHitAddress))
        return VERR_INVALID_POINTER;
    if (DBGFADDRESS_IS_HMA(pAddress))
        return VERR_INVALID_POINTER;

    /*
     * Select DBGF worker by addressing mode.
     */
    int     rc;
    PVMCPU  pVCpu   = VMMGetCpuById(pVM, idCpu);
    PGMMODE enmMode = PGMGetGuestMode(pVCpu);
    if (    enmMode == PGMMODE_REAL
        ||  enmMode == PGMMODE_PROTECTED
        ||  DBGFADDRESS_IS_PHYS(pAddress)
        )
    {
        RTGCPHYS GCPhysAlign = *puAlign;
        if (GCPhysAlign != *puAlign)
            return VERR_OUT_OF_RANGE;
        RTGCPHYS PhysHit;
        rc = PGMR3DbgScanPhysical(pVM, pAddress->FlatPtr, cbRange, GCPhysAlign, pabNeedle, cbNeedle, &PhysHit);
        if (RT_SUCCESS(rc))
            DBGFR3AddrFromPhys(pUVM, pHitAddress, PhysHit);
    }
    else
    {
#if GC_ARCH_BITS > 32
        if (    (   pAddress->FlatPtr >= _4G
                 || pAddress->FlatPtr + cbRange > _4G)
            &&  enmMode != PGMMODE_AMD64
            &&  enmMode != PGMMODE_AMD64_NX)
            return VERR_DBGF_MEM_NOT_FOUND;
#endif
        RTGCUINTPTR GCPtrHit;
        rc = PGMR3DbgScanVirtual(pVM, pVCpu, pAddress->FlatPtr, cbRange, *puAlign, pabNeedle, cbNeedle, &GCPtrHit);
        if (RT_SUCCESS(rc))
            DBGFR3AddrFromFlat(pUVM, pHitAddress, GCPtrHit);
    }

    return rc;
}
Ejemplo n.º 14
0
/**
 * Read guest memory.
 *
 * @returns VBox status code.
 *
 * @param   pVM             Pointer to the shared VM structure.
 * @param   idCpu           The ID of the source CPU context (for the address).
 * @param   pAddress        Where to start reading.
 * @param   pvBuf           Where to store the data we've read.
 * @param   cbRead          The number of bytes to read.
 */
VMMR3DECL(int) DBGFR3MemRead(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
{
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    if ((pAddress->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_RING0)
    {
        AssertCompile(sizeof(RTHCUINTPTR) <= sizeof(pAddress->FlatPtr));
        return VMMR3ReadR0Stack(pVM, idCpu, (RTHCUINTPTR)pAddress->FlatPtr, pvBuf, cbRead);
    }
    return VMR3ReqPriorityCallWait(pVM, idCpu, (PFNRT)dbgfR3MemRead, 5, pVM, idCpu, pAddress, pvBuf, cbRead);
}
/**
 * Get the current CPU mode.
 *
 * @returns The CPU mode on success, CPUMMODE_INVALID on failure.
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The target CPU ID.
 */
VMMR3DECL(CPUMMODE) DBGFR3CpuGetMode(PUVM pUVM, VMCPUID idCpu)
{
    UVM_ASSERT_VALID_EXT_RETURN(pUVM, CPUMMODE_INVALID);
    VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, CPUMMODE_INVALID);
    AssertReturn(idCpu < pUVM->pVM->cCpus, CPUMMODE_INVALID);

    CPUMMODE enmMode;
    int rc = VMR3ReqPriorityCallWaitU(pUVM, idCpu, (PFNRT)dbgfR3CpuGetMode, 3, pUVM->pVM, idCpu, &enmMode);
    if (RT_FAILURE(rc))
        return CPUMMODE_INVALID;
    return enmMode;
}
/**
 * Checks if the given CPU is executing 64-bit code or not.
 *
 * @returns true / false accordingly.
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The target CPU ID.
 */
VMMR3DECL(bool) DBGFR3CpuIsIn64BitCode(PUVM pUVM, VMCPUID idCpu)
{
    UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
    VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, false);
    AssertReturn(idCpu < pUVM->pVM->cCpus, false);

    bool fIn64BitCode;
    int rc = VMR3ReqPriorityCallWaitU(pUVM, idCpu, (PFNRT)dbgfR3CpuIn64BitCode, 3, pUVM->pVM, idCpu, &fIn64BitCode);
    if (RT_FAILURE(rc))
        return false;
    return fIn64BitCode;
}
Ejemplo n.º 17
0
/**
 * Query the trace configuration specification string.
 *
 * @returns VBox status code.
 * @retval  VINF_SUCCESS
 * @retval  VERR_INVALID_VM_HANDLE
 * @retval  VERR_INVALID_POINTER
 * @retval  VERR_BUFFER_OVERFLOW if the buffer is too small. Buffer will be
 *          empty.

 * @param   pVM                 The cross context VM structure.
 * @param   pszConfig           Pointer to the output buffer.
 * @param   cbConfig            The size of the output buffer.
 */
VMMDECL(int) DBGFR3TraceQueryConfig(PVM pVM, char *pszConfig, size_t cbConfig)
{
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertPtrReturn(pszConfig, VERR_INVALID_POINTER);
    if (cbConfig < 1)
        return VERR_BUFFER_OVERFLOW;
    *pszConfig = '\0';

    if (pVM->hTraceBufR3 == NIL_RTTRACEBUF)
        return VERR_DBGF_NO_TRACE_BUFFER;

    int             rc           = VINF_SUCCESS;
    uint32_t const  fTraceGroups = pVM->aCpus[0].fTraceGroups;
    if (   fTraceGroups == UINT32_MAX
        && PDMR3TracingAreAll(pVM, true /*fEnabled*/))
        rc = RTStrCopy(pszConfig, cbConfig, "all");
    else if (   fTraceGroups == 0
             && PDMR3TracingAreAll(pVM, false /*fEnabled*/))
        rc = RTStrCopy(pszConfig, cbConfig, "-all");
    else
    {
        char   *pszDst = pszConfig;
        size_t  cbDst  = cbConfig;
        uint32_t i = RT_ELEMENTS(g_aVmmTpGroups);
        while (i-- > 0)
            if (g_aVmmTpGroups[i].fMask & fTraceGroups)
            {
                size_t cchThis = g_aVmmTpGroups[i].cchName + (pszDst != pszConfig);
                if (cchThis >= cbDst)
                {
                    rc = VERR_BUFFER_OVERFLOW;
                    break;
                }
                if (pszDst != pszConfig)
                {
                    *pszDst = ' ';
                    memcpy(pszDst + 1, g_aVmmTpGroups[i].pszName, g_aVmmTpGroups[i].cchName + 1);
                }
                else
                    memcpy(pszDst, g_aVmmTpGroups[i].pszName, g_aVmmTpGroups[i].cchName + 1);
                pszDst += cchThis;
                cbDst  -= cchThis;
            }

        if (RT_SUCCESS(rc))
            rc = PDMR3TracingQueryConfig(pVM, pszDst, cbDst);
    }

    if (RT_FAILURE(rc))
        *pszConfig = '\0';
    return rc;
}
Ejemplo n.º 18
0
/**
 * Common worker for DBGFR3StackWalkBeginGuestEx, DBGFR3StackWalkBeginHyperEx,
 * DBGFR3StackWalkBeginGuest and DBGFR3StackWalkBeginHyper.
 */
static int dbgfR3StackWalkBeginCommon(PUVM pUVM,
                                      VMCPUID idCpu,
                                      DBGFCODETYPE enmCodeType,
                                      PCDBGFADDRESS pAddrFrame,
                                      PCDBGFADDRESS pAddrStack,
                                      PCDBGFADDRESS pAddrPC,
                                      DBGFRETURNTYPE enmReturnType,
                                      PCDBGFSTACKFRAME *ppFirstFrame)
{
    /*
     * Validate parameters.
     */
    *ppFirstFrame = NULL;
    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    if (pAddrFrame)
        AssertReturn(DBGFR3AddrIsValid(pUVM, pAddrFrame), VERR_INVALID_PARAMETER);
    if (pAddrStack)
        AssertReturn(DBGFR3AddrIsValid(pUVM, pAddrStack), VERR_INVALID_PARAMETER);
    if (pAddrPC)
        AssertReturn(DBGFR3AddrIsValid(pUVM, pAddrPC), VERR_INVALID_PARAMETER);
    AssertReturn(enmReturnType >= DBGFRETURNTYPE_INVALID && enmReturnType < DBGFRETURNTYPE_END, VERR_INVALID_PARAMETER);

    /*
     * Get the CPUM context pointer and pass it on the specified EMT.
     */
    RTDBGAS         hAs;
    PCCPUMCTXCORE   pCtxCore;
    switch (enmCodeType)
    {
        case DBGFCODETYPE_GUEST:
            pCtxCore = CPUMGetGuestCtxCore(VMMGetCpuById(pVM, idCpu));
            hAs = DBGF_AS_GLOBAL;
            break;
        case DBGFCODETYPE_HYPER:
            pCtxCore = CPUMGetHyperCtxCore(VMMGetCpuById(pVM, idCpu));
            hAs = DBGF_AS_RC_AND_GC_GLOBAL;
            break;
        case DBGFCODETYPE_RING0:
            pCtxCore = NULL;    /* No valid context present. */
            hAs = DBGF_AS_R0;
            break;
        default:
            AssertFailedReturn(VERR_INVALID_PARAMETER);
    }
    return VMR3ReqPriorityCallWaitU(pUVM, idCpu, (PFNRT)dbgfR3StackWalkCtxFull, 10,
                                    pUVM, idCpu, pCtxCore, hAs, enmCodeType,
                                    pAddrFrame, pAddrStack, pAddrPC, enmReturnType, ppFirstFrame);
}
Ejemplo n.º 19
0
/**
 * Read guest memory.
 *
 * @returns VBox status code.
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The ID of the CPU context to read memory from.
 * @param   pAddress    Where to start reading.
 * @param   pvBuf       Where to store the data we've read.
 * @param   cbRead      The number of bytes to read.
 */
static DECLCALLBACK(int) dbgfR3MemRead(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
{
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    Assert(idCpu == VMMGetCpuId(pVM));

    /*
     * Validate the input we use, PGM does the rest.
     */
    if (!DBGFR3AddrIsValid(pUVM, pAddress))
        return VERR_INVALID_POINTER;
    if (!VALID_PTR(pvBuf))
        return VERR_INVALID_POINTER;

    /*
     * HMA is special
     */
    int rc;
    if (DBGFADDRESS_IS_HMA(pAddress))
    {
        if (DBGFADDRESS_IS_PHYS(pAddress))
            rc = VERR_INVALID_POINTER;
        else
            rc = MMR3HyperReadGCVirt(pVM, pvBuf, pAddress->FlatPtr, cbRead);
    }
    else
    {
        /*
         * Select DBGF worker by addressing mode.
         */
        PVMCPU  pVCpu   = VMMGetCpuById(pVM, idCpu);
        PGMMODE enmMode = PGMGetGuestMode(pVCpu);
        if (    enmMode == PGMMODE_REAL
            ||  enmMode == PGMMODE_PROTECTED
            ||  DBGFADDRESS_IS_PHYS(pAddress) )
            rc = PGMPhysSimpleReadGCPhys(pVM, pvBuf, pAddress->FlatPtr, cbRead);
        else
        {
#if GC_ARCH_BITS > 32
            if (    (   pAddress->FlatPtr >= _4G
                     || pAddress->FlatPtr + cbRead > _4G)
                &&  enmMode != PGMMODE_AMD64
                &&  enmMode != PGMMODE_AMD64_NX)
                return VERR_PAGE_TABLE_NOT_PRESENT;
#endif
            rc = PGMPhysSimpleReadGCPtr(pVCpu, pvBuf, pAddress->FlatPtr, cbRead);
        }
    }
    return rc;
}
Ejemplo n.º 20
0
/**
 * EMT worker for DBGFR3LogModifyGroups.
 *
 * @returns VBox status code.
 * @param   pUVM                The user mode VM handle.
 * @param   pszGroupSettings    The group settings string. (VBOX_LOG)
 */
static DECLCALLBACK(int) dbgfR3LogModifyGroups(PUVM pUVM, const char *pszGroupSettings)
{
    PRTLOGGER pLogger = dbgfR3LogResolvedLogger(&pszGroupSettings);
    if (!pLogger)
        return VINF_SUCCESS;

    int rc = RTLogGroupSettings(pLogger, pszGroupSettings);
    if (RT_SUCCESS(rc) && pUVM->pVM)
    {
        VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE);
        rc = VMMR3UpdateLoggers(pUVM->pVM);
    }
    return rc;
}
Ejemplo n.º 21
0
/**
 * Delete an address space from the database.
 *
 * The address space must not be engaged as any of the standard aliases.
 *
 * @returns VBox status code.
 * @retval  VERR_SHARING_VIOLATION if in use as an alias.
 * @retval  VERR_NOT_FOUND if not found in the address space database.
 *
 * @param   pVM             Pointer to the VM.
 * @param   hDbgAs          The address space handle. Aliases are not allowed.
 */
VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs)
{
    /*
     * Input validation. Retain the address space so it can be released outside
     * the lock as well as validated.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    if (hDbgAs == NIL_RTDBGAS)
        return VINF_SUCCESS;
    uint32_t cRefs = RTDbgAsRetain(hDbgAs);
    if (cRefs == UINT32_MAX)
        return VERR_INVALID_HANDLE;
    RTDbgAsRelease(hDbgAs);

    DBGF_AS_DB_LOCK_WRITE(pVM);

    /*
     * You cannot delete any of the aliases.
     */
    for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.ahAsAliases); i++)
        if (pVM->dbgf.s.ahAsAliases[i] == hDbgAs)
        {
            DBGF_AS_DB_UNLOCK_WRITE(pVM);
            return VERR_SHARING_VIOLATION;
        }

    /*
     * Ok, try remove it from the database.
     */
    PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)RTAvlPVRemove(&pVM->dbgf.s.AsHandleTree, hDbgAs);
    if (!pDbNode)
    {
        DBGF_AS_DB_UNLOCK_WRITE(pVM);
        return VERR_NOT_FOUND;
    }
    RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pDbNode->NameCore.pszString);
    if (pDbNode->PidCore.Key != NIL_RTPROCESS)
        RTAvlU32Remove(&pVM->dbgf.s.AsPidTree, pDbNode->PidCore.Key);

    DBGF_AS_DB_UNLOCK_WRITE(pVM);

    /*
     * Free the resources.
     */
    RTDbgAsRelease(hDbgAs);
    MMR3HeapFree(pDbNode);

    return VINF_SUCCESS;
}
Ejemplo n.º 22
0
/**
 * Query a symbol by name.
 *
 * The symbol can be prefixed by a module name pattern to scope the search. The
 * pattern is a simple string pattern with '*' and '?' as wild chars. See
 * RTStrSimplePatternMatch().
 *
 * @returns VBox status code. See RTDbgAsSymbolByAddr.
 *
 * @param   pVM                 Pointer to the VM.
 * @param   hDbgAs              The address space handle.
 * @param   pszSymbol           The symbol to search for, maybe prefixed by a
 *                              module pattern.
 * @param   pSymbol             Where to return the symbol information.
 *                              The returned symbol name will be prefixed by
 *                              the module name as far as space allows.
 * @param   phMod               Where to return the module handle. Optional.
 */
VMMR3DECL(int) DBGFR3AsSymbolByName(PVM pVM, RTDBGAS hDbgAs, const char *pszSymbol,
                                    PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod)
{
    /*
     * Implement the special address space aliases the lazy way.
     */
    if (hDbgAs == DBGF_AS_RC_AND_GC_GLOBAL)
    {
        int rc = DBGFR3AsSymbolByName(pVM, DBGF_AS_RC, pszSymbol, pSymbol, phMod);
        if (RT_FAILURE(rc))
            rc = DBGFR3AsSymbolByName(pVM, DBGF_AS_GLOBAL, pszSymbol, pSymbol, phMod);
        return rc;
    }

    /*
     * Input validation.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertPtrReturn(pSymbol, VERR_INVALID_POINTER);
    AssertPtrNullReturn(phMod, VERR_INVALID_POINTER);
    if (phMod)
        *phMod = NIL_RTDBGMOD;
    RTDBGAS hRealAS = DBGFR3AsResolveAndRetain(pVM, hDbgAs);
    if (hRealAS == NIL_RTDBGAS)
        return VERR_INVALID_HANDLE;


    /*
     * Do the lookup.
     */
    RTDBGMOD hMod;
    int rc = RTDbgAsSymbolByName(hRealAS, pszSymbol, pSymbol, &hMod);
    if (RT_SUCCESS(rc))
    {
        dbgfR3AsSymbolJoinNames(pSymbol, hMod);
        if (!phMod)
            RTDbgModRelease(hMod);
    }
    /* Temporary conversion. */
    else if (hDbgAs == DBGF_AS_GLOBAL)
    {
        DBGFSYMBOL DbgfSym;
        rc = DBGFR3SymbolByName(pVM, pszSymbol, &DbgfSym);
        if (RT_SUCCESS(rc))
            dbgfR3AsSymbolConvert(pSymbol, &DbgfSym);
    }

    return rc;
}
/**
 * Wakes up a CPU that has called VMR3WaitForDeviceReady.
 *
 * @returns VBox error status (never informational statuses).
 * @param   pVM                 The VM handle.
 * @param   idCpu               The id of the calling EMT.
 */
VMMR3DECL(int) VMR3NotifyCpuDeviceReady(PVM pVM, VMCPUID idCpu)
{
    /*
     * Validate caller and resolve the CPU ID.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    PVMCPU pVCpu = &pVM->aCpus[idCpu];

    /*
     * Pretend it was an FF that got set since we've got logic for that already.
     */
    VMR3NotifyCpuFFU(pVCpu->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
    return VINF_SUCCESS;
}
Ejemplo n.º 24
0
/**
 * Gets information about a selector.
 *
 * Intended for the debugger mostly and will prefer the guest
 * descriptor tables over the shadow ones.
 *
 * @returns VBox status code, the following are the common ones.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_INVALID_SELECTOR if the selector isn't fully inside the
 *          descriptor table.
 * @retval  VERR_SELECTOR_NOT_PRESENT if the LDT is invalid or not present. This
 *          is not returned if the selector itself isn't present, you have to
 *          check that for yourself (see DBGFSELINFO::fFlags).
 * @retval  VERR_PAGE_TABLE_NOT_PRESENT or VERR_PAGE_NOT_PRESENT if the
 *          pagetable or page backing the selector table wasn't present.
 *
 * @param   pVM         VM handle.
 * @param   idCpu       The ID of the virtual CPU context.
 * @param   Sel         The selector to get info about.
 * @param   fFlags      Flags, see DBGFQSEL_FLAGS_*.
 * @param   pSelInfo    Where to store the information. This will always be
 *                      updated.
 *
 * @remarks This is a wrapper around SELMR3GetSelectorInfo and
 *          SELMR3GetShadowSelectorInfo.
 */
VMMR3DECL(int) DBGFR3SelQueryInfo(PVM pVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo)
{
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    AssertReturn(!(fFlags & ~(DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_SHADOW | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE)), VERR_INVALID_PARAMETER);
    AssertReturn(    (fFlags & (DBGFSELQI_FLAGS_DT_SHADOW | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE))
                  !=           (DBGFSELQI_FLAGS_DT_SHADOW | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE), VERR_INVALID_PARAMETER);

    /* Clear the return data here on this thread. */
    memset(pSelInfo, 0, sizeof(*pSelInfo));

    /*
     * Dispatch the request to a worker running on the target CPU.
     */
    return VMR3ReqPriorityCallWait(pVM, idCpu, (PFNRT)dbgfR3SelQueryInfo, 5, pVM, idCpu, Sel, fFlags, pSelInfo);
}
Ejemplo n.º 25
0
/**
 * Writes guest memory.
 *
 * @returns VBox status code.
 *
 * @param   pUVM        The user mode VM handle.
 * @param   idCpu       The ID of the target CPU context (for the address).
 * @param   pAddress    Where to start writing.
 * @param   pvBuf       The data to write.
 * @param   cbWrite     The number of bytes to write.
 */
static DECLCALLBACK(int) dbgfR3MemWrite(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbWrite)
{
    /*
     * Validate the input we use, PGM does the rest.
     */
    if (!DBGFR3AddrIsValid(pUVM, pAddress))
        return VERR_INVALID_POINTER;
    if (!VALID_PTR(pvBuf))
        return VERR_INVALID_POINTER;
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);

    /*
     * HMA is always special.
     */
    int rc;
    if (DBGFADDRESS_IS_HMA(pAddress))
    {
        /** @todo write to HMA. */
        rc = VERR_ACCESS_DENIED;
    }
    else
    {
        /*
         * Select PGM function by addressing mode.
         */
        PVMCPU  pVCpu   = VMMGetCpuById(pVM, idCpu);
        PGMMODE enmMode = PGMGetGuestMode(pVCpu);
        if (    enmMode == PGMMODE_REAL
            ||  enmMode == PGMMODE_PROTECTED
            ||  DBGFADDRESS_IS_PHYS(pAddress) )
            rc = PGMPhysSimpleWriteGCPhys(pVM, pAddress->FlatPtr, pvBuf, cbWrite);
        else
        {
#if GC_ARCH_BITS > 32
            if (    (   pAddress->FlatPtr >= _4G
                     || pAddress->FlatPtr + cbWrite > _4G)
                &&  enmMode != PGMMODE_AMD64
                &&  enmMode != PGMMODE_AMD64_NX)
                return VERR_PAGE_TABLE_NOT_PRESENT;
#endif
            rc = PGMPhysSimpleWriteGCPtr(pVCpu, pAddress->FlatPtr, pvBuf, cbWrite);
        }
    }
    return rc;
}
Ejemplo n.º 26
0
/**
 * Converts an address to a volatile host virtual address.
 *
 * @returns VBox status code.
 * @retval  VINF_SUCCESS
 * @retval  VERR_INVALID_PARAMETER if the address is invalid.
 * @retval  VERR_INVALID_STATE if the VM is being terminated or if the virtual
 *          CPU handle is invalid.
 * @retval  VERR_NOT_SUPPORTED is the type of address cannot be converted.
 * @retval  VERR_PAGE_NOT_PRESENT
 * @retval  VERR_PAGE_TABLE_NOT_PRESENT
 * @retval  VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
 * @retval  VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
 * @retval  VERR_PGM_PHYS_PAGE_RESERVED
 * @retval  VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
 *
 * @param   pVM             The VM handle.
 * @param   idCpu           The ID of the CPU context to convert virtual
 *                          addresses.
 * @param   pAddress        The address.
 * @param   fReadOnly       Whether returning a read-only page is fine or not.
 *                          If set to thru the page may have to be made writable
 *                          before we return.
 * @param   ppvR3Ptr        Where to return the address.
 */
VMMR3DECL(int)  DBGFR3AddrToVolatileR3Ptr(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr)
{
    /*
     * Parameter validation.
     */
    AssertPtr(ppvR3Ptr);
    *ppvR3Ptr = NULL;
    AssertPtr(pAddress);
    AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_STATE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_PARAMETER);

    /*
     * Convert it.
     */
    return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3AddrToVolatileR3PtrOnVCpu, 5, pVM, idCpu, pAddress, fReadOnly, ppvR3Ptr);
}
Ejemplo n.º 27
0
/**
 * Read a zero terminated string from guest memory.
 *
 * @returns VBox status code.
 *
 * @param   pVM             Pointer to the shared VM structure.
 * @param   idCpu           The ID of the source CPU context (for the address).
 * @param   pAddress        Where to start reading.
 * @param   pszBuf          Where to store the string.
 * @param   cchBuf          The size of the buffer.
 */
VMMR3DECL(int) DBGFR3MemReadString(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cchBuf)
{
    /*
     * Validate and zero output.
     */
    if (!VALID_PTR(pszBuf))
        return VERR_INVALID_POINTER;
    if (cchBuf <= 0)
        return VERR_INVALID_PARAMETER;
    memset(pszBuf, 0, cchBuf);
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);

    /*
     * Pass it on to the EMT.
     */
    return VMR3ReqPriorityCallWait(pVM, idCpu, (PFNRT)dbgfR3MemReadString, 5, pVM, idCpu, pAddress, pszBuf, cchBuf);
}
/**
 * Special interface for implementing a HLT-like port on a device.
 *
 * This can be called directly from device code, provide the device is trusted
 * to access the VMM directly.  Since we may not have an accurate register set
 * and the caller certainly shouldn't (device code does not access CPU
 * registers), this function will return when interrupts are pending regardless
 * of the actual EFLAGS.IF state.
 *
 * @returns VBox error status (never informational statuses).
 * @param   pVM                 The VM handle.
 * @param   idCpu               The id of the calling EMT.
 */
VMMR3DECL(int) VMR3WaitForDeviceReady(PVM pVM, VMCPUID idCpu)
{
    /*
     * Validate caller and resolve the CPU ID.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
    PVMCPU pVCpu = &pVM->aCpus[idCpu];
    VMCPU_ASSERT_EMT_RETURN(pVCpu, VERR_VM_THREAD_NOT_EMT);

    /*
     * Tag along with the HLT mechanics for now.
     */
    int rc = VMR3WaitHalted(pVM, pVCpu, false /*fIgnoreInterrupts*/);
    if (RT_SUCCESS(rc))
        return VINF_SUCCESS;
    return rc;
}
Ejemplo n.º 29
0
/**
 * Adds the address space to the database.
 *
 * @returns VBox status code.
 * @param   pVM             Pointer to the VM.
 * @param   hDbgAs          The address space handle. The reference of the
 *                          caller will NOT be consumed.
 * @param   ProcId          The process id or NIL_RTPROCESS.
 */
VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId)
{
    /*
     * Input validation.
     */
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    const char *pszName = RTDbgAsName(hDbgAs);
    if (!pszName)
        return VERR_INVALID_HANDLE;
    uint32_t cRefs = RTDbgAsRetain(hDbgAs);
    if (cRefs == UINT32_MAX)
        return VERR_INVALID_HANDLE;

    /*
     * Allocate a tracking node.
     */
    int rc = VERR_NO_MEMORY;
    PDBGFASDBNODE pDbNode = (PDBGFASDBNODE)MMR3HeapAlloc(pVM, MM_TAG_DBGF_AS, sizeof(*pDbNode));
    if (pDbNode)
    {
        pDbNode->HandleCore.Key     = hDbgAs;
        pDbNode->PidCore.Key        = ProcId;
        pDbNode->NameCore.pszString = pszName;
        pDbNode->NameCore.cchString = strlen(pszName);
        DBGF_AS_DB_LOCK_WRITE(pVM);
        if (RTStrSpaceInsert(&pVM->dbgf.s.AsNameSpace, &pDbNode->NameCore))
        {
            if (RTAvlPVInsert(&pVM->dbgf.s.AsHandleTree, &pDbNode->HandleCore))
            {
                DBGF_AS_DB_UNLOCK_WRITE(pVM);
                return VINF_SUCCESS;
            }

            /* bail out */
            RTStrSpaceRemove(&pVM->dbgf.s.AsNameSpace, pszName);
        }
        DBGF_AS_DB_UNLOCK_WRITE(pVM);
        MMR3HeapFree(pDbNode);
    }
    RTDbgAsRelease(hDbgAs);
    return rc;
}
Ejemplo n.º 30
0
/**
 * @callback_method_impl{FNDBGCCMD, The '.pgmsharedmodules' command.}
 */
DECLCALLBACK(int) pgmR3CmdShowSharedModules(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
    NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
    PVM pVM = pUVM->pVM;
    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);

    pgmLock(pVM);
    for (unsigned i = 0; i < RT_ELEMENTS(g_apSharedModules); i++)
    {
        if (g_apSharedModules[i])
        {
            pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Shared module %s (%s):\n", g_apSharedModules[i]->szName, g_apSharedModules[i]->szVersion);
            for (unsigned j = 0; j < g_apSharedModules[i]->cRegions; j++)
                pCmdHlp->pfnPrintf(pCmdHlp, NULL, "--- Region %d: base %RGv size %x\n", j, g_apSharedModules[i]->aRegions[j].GCRegionAddr, g_apSharedModules[i]->aRegions[j].cbRegion);
        }
    }
    pgmUnlock(pVM);

    return VINF_SUCCESS;
}