Beispiel #1
0
/**
 * @interface_method_impl{DBGCCMDHLP,pfnVarConvert}
 */
static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pInVar, DBGCVARTYPE enmToType, bool fConvSyms,
                                           PDBGCVAR pResult)
{
    PDBGC           pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    DBGCVAR const   InVar = *pInVar;    /* if pInVar == pResult  */
    PCDBGCVAR       pArg = &InVar;      /* lazy bird, clean up later */
    DBGFADDRESS     Address;
    int             rc;

    Assert(pDbgc->pUVM);

    *pResult = InVar;
    switch (InVar.enmType)
    {
        case DBGCVAR_TYPE_GC_FLAT:
            switch (enmToType)
            {
                case DBGCVAR_TYPE_GC_FLAT:
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_GC_FAR:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_PHYS:
                    pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
                    rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu,
                                          DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
                                          &pResult->u.GCPhys);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_HC_FLAT:
                    pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
                    rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu,
                                                   DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
                                                   false /*fReadOnly */,
                                                   &pResult->u.pvHCFlat);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_HC_PHYS:
                    pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
                    rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu,
                                              DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
                                              &pResult->u.GCPhys);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_NUMBER:
                    pResult->enmType     = enmToType;
                    pResult->u.u64Number = InVar.u.GCFlat;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_STRING:
                case DBGCVAR_TYPE_SYMBOL:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_UNKNOWN:
                case DBGCVAR_TYPE_ANY:
                    break;
            }
            break;

        case DBGCVAR_TYPE_GC_FAR:
            switch (enmToType)
            {
                case DBGCVAR_TYPE_GC_FLAT:
                    rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
                    if (RT_SUCCESS(rc))
                    {
                        pResult->enmType  = DBGCVAR_TYPE_GC_FLAT;
                        pResult->u.GCFlat = Address.FlatPtr;
                        return VINF_SUCCESS;
                    }
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_GC_FAR:
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_GC_PHYS:
                    rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
                    if (RT_SUCCESS(rc))
                    {
                        pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
                        rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
                        if (RT_SUCCESS(rc))
                            return VINF_SUCCESS;
                    }
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_HC_FLAT:
                    rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
                    if (RT_SUCCESS(rc))
                    {
                        pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
                        rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, &Address,
                                                       false /*fReadOnly*/, &pResult->u.pvHCFlat);
                        if (RT_SUCCESS(rc))
                            return VINF_SUCCESS;
                    }
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_HC_PHYS:
                    rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
                    if (RT_SUCCESS(rc))
                    {
                        pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
                        rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
                        if (RT_SUCCESS(rc))
                            return VINF_SUCCESS;
                    }
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_NUMBER:
                    pResult->enmType     = enmToType;
                    pResult->u.u64Number = InVar.u.GCFar.off;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_STRING:
                case DBGCVAR_TYPE_SYMBOL:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_UNKNOWN:
                case DBGCVAR_TYPE_ANY:
                    break;
            }
            break;

        case DBGCVAR_TYPE_GC_PHYS:
            switch (enmToType)
            {
                case DBGCVAR_TYPE_GC_FLAT:
                    //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_FAR:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_PHYS:
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_HC_FLAT:
                    pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
                    rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu,
                                                   DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys),
                                                   false /*fReadOnly */,
                                                   &pResult->u.pvHCFlat);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_HC_PHYS:
                    pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
                    rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu,
                                              DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys),
                                              &pResult->u.HCPhys);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_NUMBER:
                    pResult->enmType     = enmToType;
                    pResult->u.u64Number = InVar.u.GCPhys;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_STRING:
                case DBGCVAR_TYPE_SYMBOL:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_UNKNOWN:
                case DBGCVAR_TYPE_ANY:
                    break;
            }
            break;

        case DBGCVAR_TYPE_HC_FLAT:
            switch (enmToType)
            {
                case DBGCVAR_TYPE_GC_FLAT:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_FAR:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_PHYS:
                    pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
                    rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    /** @todo more memory types! */
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_HC_FLAT:
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_HC_PHYS:
                    pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
                    rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    /** @todo more memory types! */
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_NUMBER:
                    pResult->enmType     = enmToType;
                    pResult->u.u64Number = (uintptr_t)InVar.u.pvHCFlat;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_STRING:
                case DBGCVAR_TYPE_SYMBOL:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_UNKNOWN:
                case DBGCVAR_TYPE_ANY:
                    break;
            }
            break;

        case DBGCVAR_TYPE_HC_PHYS:
            switch (enmToType)
            {
                case DBGCVAR_TYPE_GC_FLAT:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_FAR:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_PHYS:
                    pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
                    rc = PGMR3DbgHCPhys2GCPhys(pDbgc->pUVM, pArg->u.HCPhys, &pResult->u.GCPhys);
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    return VERR_DBGC_PARSE_CONVERSION_FAILED;

                case DBGCVAR_TYPE_HC_FLAT:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_HC_PHYS:
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_NUMBER:
                    pResult->enmType     = enmToType;
                    pResult->u.u64Number = InVar.u.HCPhys;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_STRING:
                case DBGCVAR_TYPE_SYMBOL:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_UNKNOWN:
                case DBGCVAR_TYPE_ANY:
                    break;
            }
            break;

        case DBGCVAR_TYPE_NUMBER:
            switch (enmToType)
            {
                case DBGCVAR_TYPE_GC_FLAT:
                    pResult->enmType  = DBGCVAR_TYPE_GC_FLAT;
                    pResult->u.GCFlat = (RTGCPTR)InVar.u.u64Number;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_GC_FAR:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_GC_PHYS:
                    pResult->enmType  = DBGCVAR_TYPE_GC_PHYS;
                    pResult->u.GCPhys = (RTGCPHYS)InVar.u.u64Number;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_HC_FLAT:
                    pResult->enmType    = DBGCVAR_TYPE_HC_FLAT;
                    pResult->u.pvHCFlat = (void *)(uintptr_t)InVar.u.u64Number;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_HC_PHYS:
                    pResult->enmType  = DBGCVAR_TYPE_HC_PHYS;
                    pResult->u.HCPhys = (RTHCPHYS)InVar.u.u64Number;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_NUMBER:
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_STRING:
                case DBGCVAR_TYPE_SYMBOL:
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_UNKNOWN:
                case DBGCVAR_TYPE_ANY:
                    break;
            }
            break;

        case DBGCVAR_TYPE_SYMBOL:
        case DBGCVAR_TYPE_STRING:
            switch (enmToType)
            {
                case DBGCVAR_TYPE_GC_FLAT:
                case DBGCVAR_TYPE_GC_FAR:
                case DBGCVAR_TYPE_GC_PHYS:
                case DBGCVAR_TYPE_HC_FLAT:
                case DBGCVAR_TYPE_HC_PHYS:
                case DBGCVAR_TYPE_NUMBER:
                    if (fConvSyms)
                    {
                        rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult);
                        if (RT_SUCCESS(rc))
                            return VINF_SUCCESS;
                    }
                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;

                case DBGCVAR_TYPE_STRING:
                case DBGCVAR_TYPE_SYMBOL:
                    pResult->enmType = enmToType;
                    return VINF_SUCCESS;

                case DBGCVAR_TYPE_UNKNOWN:
                case DBGCVAR_TYPE_ANY:
                    break;
            }
            break;

        case DBGCVAR_TYPE_UNKNOWN:
        case DBGCVAR_TYPE_ANY:
            break;
    }

    AssertMsgFailed(("f=%d t=%d\n", InVar.enmType, enmToType));
    return VERR_INVALID_PARAMETER;
}
Beispiel #2
0
/**
 * @interface_method_impl{DBGCCMDHLP,pfnMemWrite}
 */
static DECLCALLBACK(int) dbgcHlpMemWrite(PDBGCCMDHLP pCmdHlp, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten)
{
    PDBGC       pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    DBGFADDRESS Address;
    int         rc;

    /*
     * Dummy check.
     */
    if (cbWrite == 0)
    {
        if (*pcbWritten)
            *pcbWritten = 0;
        return VINF_SUCCESS;
    }

    /*
     * Convert Far addresses getting size and the correct base address.
     * Getting and checking the size is what makes this messy and slow.
     */
    DBGCVAR Var = *pVarPointer;
    switch (pVarPointer->enmType)
    {
        case DBGCVAR_TYPE_GC_FAR:
        {
            /* Use DBGFR3AddrFromSelOff for the conversion. */
            Assert(pDbgc->pUVM);
            rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
            if (RT_FAILURE(rc))
                return rc;

            /* don't bother with flat selectors (for now). */
            if (!DBGFADDRESS_IS_FLAT(&Address))
            {
                DBGFSELINFO SelInfo;
                rc = DBGFR3SelQueryInfo(pDbgc->pUVM, pDbgc->idCpu, Address.Sel,
                                        DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo);
                if (RT_SUCCESS(rc))
                {
                    RTGCUINTPTR cb; /* -1 byte */
                    if (DBGFSelInfoIsExpandDown(&SelInfo))
                    {
                        if (    !SelInfo.u.Raw.Gen.u1Granularity
                            &&  Address.off > UINT16_C(0xffff))
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        if (Address.off <= SelInfo.cbLimit)
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
                    }
                    else
                    {
                        if (Address.off > SelInfo.cbLimit)
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        cb = SelInfo.cbLimit - Address.off;
                    }
                    if (cbWrite - 1 > cb)
                    {
                        if (!pcbWritten)
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        cbWrite = cb + 1;
                    }
                }
            }
            Var.enmType = DBGCVAR_TYPE_GC_FLAT;
            Var.u.GCFlat = Address.FlatPtr;
        }
        /* fall thru */
        case DBGCVAR_TYPE_GC_FLAT:
            rc = DBGFR3MemWrite(pDbgc->pUVM, pDbgc->idCpu,
                                DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, Var.u.GCFlat),
                                pvBuffer, cbWrite);
            if (pcbWritten && RT_SUCCESS(rc))
                *pcbWritten = cbWrite;
            return rc;

        case DBGCVAR_TYPE_GC_PHYS:
            rc = DBGFR3MemWrite(pDbgc->pUVM, pDbgc->idCpu,
                                DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, Var.u.GCPhys),
                                pvBuffer, cbWrite);
            if (pcbWritten && RT_SUCCESS(rc))
                *pcbWritten = cbWrite;
            return rc;

        case DBGCVAR_TYPE_HC_FLAT:
        case DBGCVAR_TYPE_HC_PHYS:
        {
            /*
             * Copy HC memory page by page.
             */
            if (pcbWritten)
                *pcbWritten = 0;
            while (cbWrite > 0)
            {
                /* convert to flat address */
                DBGCVAR Var2;
                rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2);
                if (RT_FAILURE(rc))
                {
                    if (pcbWritten && *pcbWritten)
                        return -VERR_INVALID_POINTER;
                    return VERR_INVALID_POINTER;
                }

                /* calc size. */
                size_t cbChunk = PAGE_SIZE;
                cbChunk -= (uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK;
                if (cbChunk > cbWrite)
                    cbChunk = cbWrite;

                /** @todo protect this!!! */
                memcpy(Var2.u.pvHCFlat, pvBuffer, cbChunk);

                /* advance */
                if (Var.enmType == DBGCVAR_TYPE_HC_FLAT)
                    Var.u.pvHCFlat = (uint8_t *)Var.u.pvHCFlat + cbChunk;
                else
                    Var.u.HCPhys += cbChunk;
                pvBuffer = (uint8_t const *)pvBuffer + cbChunk;
                if (pcbWritten)
                    *pcbWritten += cbChunk;
                cbWrite -= cbChunk;
            }

            return VINF_SUCCESS;
        }

        default:
            return VERR_NOT_IMPLEMENTED;
    }
}
Beispiel #3
0
/**
 * Internal worker routine.
 *
 * On x86 the typical stack frame layout is like this:
 *     ..  ..
 *     16  parameter 2
 *     12  parameter 1
 *      8  parameter 0
 *      4  return address
 *      0  old ebp; current ebp points here
 *
 * @todo Add AMD64 support (needs teaming up with the module management for
 *       unwind tables).
 */
static int dbgfR3StackWalk(PUVM pUVM, VMCPUID idCpu, RTDBGAS hAs, PDBGFSTACKFRAME pFrame)
{
    /*
     * Stop if we got a read error in the previous run.
     */
    if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_LAST)
        return VERR_NO_MORE_FILES;

    /*
     * Read the raw frame data.
     */
    const DBGFADDRESS AddrOldPC = pFrame->AddrPC;
    const unsigned cbRetAddr = DBGFReturnTypeSize(pFrame->enmReturnType);
    unsigned cbStackItem;
    switch (AddrOldPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
    {
        case DBGFADDRESS_FLAGS_FAR16: cbStackItem = 2; break;
        case DBGFADDRESS_FLAGS_FAR32: cbStackItem = 4; break;
        case DBGFADDRESS_FLAGS_FAR64: cbStackItem = 8; break;
        case DBGFADDRESS_FLAGS_RING0: cbStackItem = sizeof(RTHCUINTPTR); break;
        default:
            switch (pFrame->enmReturnType)
            {
                case DBGFRETURNTYPE_FAR16:
                case DBGFRETURNTYPE_IRET16:
                case DBGFRETURNTYPE_IRET32_V86:
                case DBGFRETURNTYPE_NEAR16: cbStackItem = 2; break;

                case DBGFRETURNTYPE_FAR32:
                case DBGFRETURNTYPE_IRET32:
                case DBGFRETURNTYPE_IRET32_PRIV:
                case DBGFRETURNTYPE_NEAR32: cbStackItem = 4; break;

                case DBGFRETURNTYPE_FAR64:
                case DBGFRETURNTYPE_IRET64:
                case DBGFRETURNTYPE_NEAR64: cbStackItem = 8; break;

                default:
                    AssertMsgFailed(("%d\n", pFrame->enmReturnType));
                    cbStackItem = 4;
                    break;
            }
    }

    union
    {
        uint64_t *pu64;
        uint32_t *pu32;
        uint16_t *pu16;
        uint8_t  *pb;
        void     *pv;
    } u, uRet, uArgs, uBp;
    size_t cbRead = cbRetAddr + cbStackItem + sizeof(pFrame->Args);
    u.pv = alloca(cbRead);
    uBp = u;
    uRet.pb = u.pb + cbStackItem;
    uArgs.pb = u.pb + cbStackItem + cbRetAddr;

    Assert(DBGFADDRESS_IS_VALID(&pFrame->AddrFrame));
    int rc = dbgfR3Read(pUVM, idCpu, u.pv,
                        pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID
                        ? &pFrame->AddrReturnFrame
                        : &pFrame->AddrFrame,
                        cbRead, &cbRead);
    if (    RT_FAILURE(rc)
        ||  cbRead < cbRetAddr + cbStackItem)
        pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_LAST;

    /*
     * The first step is taken in a different way than the others.
     */
    if (!(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID))
    {
        pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_ALL_VALID;
        pFrame->iFrame = 0;

        /* Current PC - set by caller, just find symbol & line. */
        if (DBGFADDRESS_IS_VALID(&pFrame->AddrPC))
        {
            pFrame->pSymPC  = DBGFR3AsSymbolByAddrA(pUVM, hAs, &pFrame->AddrPC, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL,
                                                    NULL /*poffDisp*/, NULL /*phMod*/);
            pFrame->pLinePC = DBGFR3AsLineByAddrA(pUVM, hAs, &pFrame->AddrPC, NULL /*poffDisp*/, NULL /*phMod*/);
        }
    }
    else /* 2nd and subsequent steps */
    {
        /* frame, pc and stack is taken from the existing frames return members. */
        pFrame->AddrFrame = pFrame->AddrReturnFrame;
        pFrame->AddrPC    = pFrame->AddrReturnPC;
        pFrame->pSymPC    = pFrame->pSymReturnPC;
        pFrame->pLinePC   = pFrame->pLineReturnPC;

        /* increment the frame number. */
        pFrame->iFrame++;
    }

    /*
     * Return Frame address.
     */
    pFrame->AddrReturnFrame = pFrame->AddrFrame;
    switch (cbStackItem)
    {
        case 2:    pFrame->AddrReturnFrame.off = *uBp.pu16; break;
        case 4:    pFrame->AddrReturnFrame.off = *uBp.pu32; break;
        case 8:    pFrame->AddrReturnFrame.off = *uBp.pu64; break;
        default:    AssertMsgFailedReturn(("cbStackItem=%d\n", cbStackItem), VERR_DBGF_STACK_IPE_1);
    }
    pFrame->AddrReturnFrame.FlatPtr += pFrame->AddrReturnFrame.off - pFrame->AddrFrame.off;

    /*
     * Return PC and Stack Addresses.
     */
    /** @todo AddrReturnStack is not correct for stdcall and pascal. (requires scope info) */
    pFrame->AddrReturnStack          = pFrame->AddrFrame;
    pFrame->AddrReturnStack.off     += cbStackItem + cbRetAddr;
    pFrame->AddrReturnStack.FlatPtr += cbStackItem + cbRetAddr;

    pFrame->AddrReturnPC             = pFrame->AddrPC;
    switch (pFrame->enmReturnType)
    {
        case DBGFRETURNTYPE_NEAR16:
            if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
            {
                pFrame->AddrReturnPC.FlatPtr += *uRet.pu16 - pFrame->AddrReturnPC.off;
                pFrame->AddrReturnPC.off      = *uRet.pu16;
            }
            else
                DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu16);
            break;
        case DBGFRETURNTYPE_NEAR32:
            if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
            {
                pFrame->AddrReturnPC.FlatPtr += *uRet.pu32 - pFrame->AddrReturnPC.off;
                pFrame->AddrReturnPC.off      = *uRet.pu32;
            }
            else
                DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu32);
            break;
        case DBGFRETURNTYPE_NEAR64:
            if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
            {
                pFrame->AddrReturnPC.FlatPtr += *uRet.pu64 - pFrame->AddrReturnPC.off;
                pFrame->AddrReturnPC.off      = *uRet.pu64;
            }
            else
                DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu64);
            break;
        case DBGFRETURNTYPE_FAR16:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]);
            break;
        case DBGFRETURNTYPE_FAR32:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
            break;
        case DBGFRETURNTYPE_FAR64:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]);
            break;
        case DBGFRETURNTYPE_IRET16:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]);
            break;
        case DBGFRETURNTYPE_IRET32:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
            break;
        case DBGFRETURNTYPE_IRET32_PRIV:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
            break;
        case DBGFRETURNTYPE_IRET32_V86:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
            break;
        case DBGFRETURNTYPE_IRET64:
            DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]);
            break;
        default:
            AssertMsgFailed(("enmReturnType=%d\n", pFrame->enmReturnType));
            return VERR_INVALID_PARAMETER;
    }

    pFrame->pSymReturnPC  = DBGFR3AsSymbolByAddrA(pUVM, hAs, &pFrame->AddrReturnPC, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL,
                                                  NULL /*poffDisp*/, NULL /*phMod*/);
    pFrame->pLineReturnPC = DBGFR3AsLineByAddrA(pUVM, hAs, &pFrame->AddrReturnPC, NULL /*poffDisp*/, NULL /*phMod*/);

    /*
     * Frame bitness flag.
     */
    switch (cbStackItem)
    {
        case 2: pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_16BIT; break;
        case 4: pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_32BIT; break;
        case 8: pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_64BIT; break;
        default:    AssertMsgFailedReturn(("cbStackItem=%d\n", cbStackItem), VERR_DBGF_STACK_IPE_2);
    }

    /*
     * The arguments.
     */
    memcpy(&pFrame->Args, uArgs.pv, sizeof(pFrame->Args));

    return VINF_SUCCESS;
}
Beispiel #4
0
/**
 * @interface_method_impl{DBGCCMDHLP,pfnMemRead}
 */
static DECLCALLBACK(int) dbgcHlpMemRead(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
{
    PDBGC       pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    DBGFADDRESS Address;
    int         rc;

    /*
     * Dummy check.
     */
    if (cbRead == 0)
    {
        if (*pcbRead)
            *pcbRead = 0;
        return VINF_SUCCESS;
    }

    /*
     * Convert Far addresses getting size and the correct base address.
     * Getting and checking the size is what makes this messy and slow.
     */
    DBGCVAR Var = *pVarPointer;
    switch (pVarPointer->enmType)
    {
        case DBGCVAR_TYPE_GC_FAR:
            /* Use DBGFR3AddrFromSelOff for the conversion. */
            Assert(pDbgc->pUVM);
            rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
            if (RT_FAILURE(rc))
                return rc;

            /* don't bother with flat selectors (for now). */
            if (!DBGFADDRESS_IS_FLAT(&Address))
            {
                DBGFSELINFO SelInfo;
                rc = DBGFR3SelQueryInfo(pDbgc->pUVM, pDbgc->idCpu, Address.Sel,
                                        DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo);
                if (RT_SUCCESS(rc))
                {
                    RTGCUINTPTR cb; /* -1 byte */
                    if (DBGFSelInfoIsExpandDown(&SelInfo))
                    {
                        if (    !SelInfo.u.Raw.Gen.u1Granularity
                            &&  Address.off > UINT16_C(0xffff))
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        if (Address.off <= SelInfo.cbLimit)
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
                    }
                    else
                    {
                        if (Address.off > SelInfo.cbLimit)
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        cb = SelInfo.cbLimit - Address.off;
                    }
                    if (cbRead - 1 > cb)
                    {
                        if (!pcbRead)
                            return VERR_OUT_OF_SELECTOR_BOUNDS;
                        cbRead = cb + 1;
                    }
                }
            }
            Var.enmType = DBGCVAR_TYPE_GC_FLAT;
            Var.u.GCFlat = Address.FlatPtr;
            break;

        case DBGCVAR_TYPE_GC_FLAT:
        case DBGCVAR_TYPE_GC_PHYS:
        case DBGCVAR_TYPE_HC_FLAT:
        case DBGCVAR_TYPE_HC_PHYS:
            break;

        default:
            return VERR_NOT_IMPLEMENTED;
    }



    /*
     * Copy page by page.
     */
    size_t cbLeft = cbRead;
    for (;;)
    {
        /*
         * Calc read size.
         */
        size_t cb = RT_MIN(PAGE_SIZE, cbLeft);
        switch (pVarPointer->enmType)
        {
            case DBGCVAR_TYPE_GC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCFlat & PAGE_OFFSET_MASK)); break;
            case DBGCVAR_TYPE_GC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCPhys & PAGE_OFFSET_MASK)); break;
            case DBGCVAR_TYPE_HC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - ((uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK)); break;
            case DBGCVAR_TYPE_HC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - ((size_t)Var.u.HCPhys & PAGE_OFFSET_MASK)); break; /* size_t: MSC has braindead loss of data warnings! */
            default: break;
        }

        /*
         * Perform read.
         */
        switch (Var.enmType)
        {
            case DBGCVAR_TYPE_GC_FLAT:
                rc = DBGFR3MemRead(pDbgc->pUVM, pDbgc->idCpu,
                                   DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, Var.u.GCFlat),
                                   pvBuffer, cb);
                break;

            case DBGCVAR_TYPE_GC_PHYS:
                rc = DBGFR3MemRead(pDbgc->pUVM, pDbgc->idCpu,
                                   DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, Var.u.GCPhys),
                                   pvBuffer, cb);
                break;

            case DBGCVAR_TYPE_HC_PHYS:
            case DBGCVAR_TYPE_HC_FLAT:
            {
                DBGCVAR Var2;
                rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2);
                if (RT_SUCCESS(rc))
                {
                    /** @todo protect this!!! */
                    memcpy(pvBuffer, Var2.u.pvHCFlat, cb);
                    rc = 0;
                }
                else
                    rc = VERR_INVALID_POINTER;
                break;
            }

            default:
                rc = VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
        }

        /*
         * Check for failure.
         */
        if (RT_FAILURE(rc))
        {
            if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
                return VINF_SUCCESS;
            return rc;
        }

        /*
         * Next.
         */
        cbLeft -= cb;
        if (!cbLeft)
            break;
        pvBuffer = (char *)pvBuffer + cb;
        rc = DBGCCmdHlpEval(pCmdHlp, &Var, "%DV + %d", &Var, cb);
        if (RT_FAILURE(rc))
        {
            if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
                return VINF_SUCCESS;
            return rc;
        }
    }

    /*
     * Done
     */
    if (pcbRead)
        *pcbRead = cbRead;
    return 0;
}
Beispiel #5
0
/**
 * Walks the entire stack allocating memory as we walk.
 */
static DECLCALLBACK(int) dbgfR3StackWalkCtxFull(PUVM pUVM, VMCPUID idCpu, PCCPUMCTXCORE pCtxCore, RTDBGAS hAs,
                                                DBGFCODETYPE enmCodeType,
                                                PCDBGFADDRESS pAddrFrame,
                                                PCDBGFADDRESS pAddrStack,
                                                PCDBGFADDRESS pAddrPC,
                                                DBGFRETURNTYPE enmReturnType,
                                                PCDBGFSTACKFRAME *ppFirstFrame)
{
    /* alloc first frame. */
    PDBGFSTACKFRAME pCur = (PDBGFSTACKFRAME)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_STACK, sizeof(*pCur));
    if (!pCur)
        return VERR_NO_MEMORY;

    /*
     * Initialize the frame.
     */
    pCur->pNextInternal = NULL;
    pCur->pFirstInternal = pCur;

    int rc = VINF_SUCCESS;
    if (pAddrPC)
        pCur->AddrPC = *pAddrPC;
    else if (enmCodeType != DBGFCODETYPE_GUEST)
        DBGFR3AddrFromFlat(pUVM, &pCur->AddrPC, pCtxCore->rip);
    else
        rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrPC, pCtxCore->cs.Sel, pCtxCore->rip);
    if (RT_SUCCESS(rc))
    {
        if (enmReturnType == DBGFRETURNTYPE_INVALID)
            switch (pCur->AddrPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
            {
                case DBGFADDRESS_FLAGS_FAR16: pCur->enmReturnType = DBGFRETURNTYPE_NEAR16; break;
                case DBGFADDRESS_FLAGS_FAR32: pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; break;
                case DBGFADDRESS_FLAGS_FAR64: pCur->enmReturnType = DBGFRETURNTYPE_NEAR64; break;
                case DBGFADDRESS_FLAGS_RING0: pCur->enmReturnType = HC_ARCH_BITS == 64 ? DBGFRETURNTYPE_NEAR64 : DBGFRETURNTYPE_NEAR32; break;
                default:                      pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; break; /// @todo 64-bit guests
            }

        uint64_t fAddrMask;
        if (enmCodeType == DBGFCODETYPE_RING0)
            fAddrMask = HC_ARCH_BITS == 64 ? UINT64_MAX : UINT32_MAX;
        else if (enmCodeType == DBGFCODETYPE_HYPER)
            fAddrMask = UINT32_MAX;
        else if (DBGFADDRESS_IS_FAR16(&pCur->AddrPC))
            fAddrMask = UINT16_MAX;
        else if (DBGFADDRESS_IS_FAR32(&pCur->AddrPC))
            fAddrMask = UINT32_MAX;
        else if (DBGFADDRESS_IS_FAR64(&pCur->AddrPC))
            fAddrMask = UINT64_MAX;
        else
        {
            PVMCPU pVCpu = VMMGetCpuById(pUVM->pVM, idCpu);
            CPUMMODE CpuMode = CPUMGetGuestMode(pVCpu);
            if (CpuMode == CPUMMODE_REAL)
                fAddrMask = UINT16_MAX;
            else if (   CpuMode == CPUMMODE_PROTECTED
                     || !CPUMIsGuestIn64BitCode(pVCpu))
                fAddrMask = UINT32_MAX;
            else
                fAddrMask = UINT64_MAX;
        }

        if (pAddrStack)
            pCur->AddrStack = *pAddrStack;
        else if (enmCodeType != DBGFCODETYPE_GUEST)
            DBGFR3AddrFromFlat(pUVM, &pCur->AddrStack, pCtxCore->rsp & fAddrMask);
        else
            rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrStack, pCtxCore->ss.Sel, pCtxCore->rsp & fAddrMask);

        if (pAddrFrame)
            pCur->AddrFrame = *pAddrFrame;
        else if (enmCodeType != DBGFCODETYPE_GUEST)
            DBGFR3AddrFromFlat(pUVM, &pCur->AddrFrame, pCtxCore->rbp & fAddrMask);
        else if (RT_SUCCESS(rc))
            rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrFrame, pCtxCore->ss.Sel, pCtxCore->rbp & fAddrMask);
    }
    else
        pCur->enmReturnType = enmReturnType;

    /*
     * The first frame.
     */
    if (RT_SUCCESS(rc))
        rc = dbgfR3StackWalk(pUVM, idCpu, hAs, pCur);
    if (RT_FAILURE(rc))
    {
        DBGFR3StackWalkEnd(pCur);
        return rc;
    }

    /*
     * The other frames.
     */
    DBGFSTACKFRAME Next = *pCur;
    while (!(pCur->fFlags & (DBGFSTACKFRAME_FLAGS_LAST | DBGFSTACKFRAME_FLAGS_MAX_DEPTH | DBGFSTACKFRAME_FLAGS_LOOP)))
    {
        /* try walk. */
        rc = dbgfR3StackWalk(pUVM, idCpu, hAs, &Next);
        if (RT_FAILURE(rc))
            break;

        /* add the next frame to the chain. */
        PDBGFSTACKFRAME pNext = (PDBGFSTACKFRAME)MMR3HeapAllocU(pUVM, MM_TAG_DBGF_STACK, sizeof(*pNext));
        if (!pNext)
        {
            DBGFR3StackWalkEnd(pCur);
            return VERR_NO_MEMORY;
        }
        *pNext = Next;
        pCur->pNextInternal = pNext;
        pCur = pNext;
        Assert(pCur->pNextInternal == NULL);

        /* check for loop */
        for (PCDBGFSTACKFRAME pLoop = pCur->pFirstInternal;
             pLoop && pLoop != pCur;
             pLoop = pLoop->pNextInternal)
            if (pLoop->AddrFrame.FlatPtr == pCur->AddrFrame.FlatPtr)
            {
                pCur->fFlags |= DBGFSTACKFRAME_FLAGS_LOOP;
                break;
            }

        /* check for insane recursion */
        if (pCur->iFrame >= 2048)
            pCur->fFlags |= DBGFSTACKFRAME_FLAGS_MAX_DEPTH;
    }

    *ppFirstFrame = pCur->pFirstInternal;
    return rc;
}