VirtualBox

Changeset 64720 in vbox


Ignore:
Timestamp:
Nov 20, 2016 2:00:02 AM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
112004
Message:

DBGF: Added DBGFR3StepEx for simple step-over support as well as both step/trace to call, step/trace to return, step/trace to one instruction after return. Also added DBGFR3CpuIsInV86Code.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/cpum.h

    r62476 r64720  
    10661066VMMDECL(RTSEL)      CPUMGetGuestGS(PVMCPU pVCpu);
    10671067VMMDECL(RTSEL)      CPUMGetGuestSS(PVMCPU pVCpu);
     1068VMMDECL(uint64_t)   CPUMGetGuestFlatPC(PVMCPU pVCpu);
     1069VMMDECL(uint64_t)   CPUMGetGuestFlatSP(PVMCPU pVCpu);
    10681070VMMDECL(uint64_t)   CPUMGetGuestDR0(PVMCPU pVCpu);
    10691071VMMDECL(uint64_t)   CPUMGetGuestDR1(PVMCPU pVCpu);
  • trunk/include/VBox/vmm/dbgf.h

    r64590 r64720  
    8787/** A physical address. */
    8888#define DBGFADDRESS_FLAGS_PHYS          4
    89 /** A physical address. */
     89/** A ring-0 host address (internal use only). */
    9090#define DBGFADDRESS_FLAGS_RING0         5
    9191/** The address type mask. */
     
    109109/** Checks if the mixed address is far 16:64 or not. */
    110110#define DBGFADDRESS_IS_FAR64(pAddress)   ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR64 )
     111/** Checks if the mixed address host context ring-0 (special). */
     112#define DBGFADDRESS_IS_R0_HC(pAddress)   ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_RING0 )
     113/** Checks if the mixed address a virtual guest context address (incl HMA). */
     114#define DBGFADDRESS_IS_VIRT_GC(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) <= DBGFADDRESS_FLAGS_FLAT )
    111115/** Checks if the mixed address is valid. */
    112 #define DBGFADDRESS_IS_VALID(pAddress)   ( !!((pAddress)->fFlags & DBGFADDRESS_FLAGS_VALID) )
     116#define DBGFADDRESS_IS_VALID(pAddress)   RT_BOOL((pAddress)->fFlags & DBGFADDRESS_FLAGS_VALID)
    113117/** Checks if the address is flagged as within the HMA. */
    114 #define DBGFADDRESS_IS_HMA(pAddress)     ( !!((pAddress)->fFlags & DBGFADDRESS_FLAGS_HMA) )
     118#define DBGFADDRESS_IS_HMA(pAddress)     RT_BOOL((pAddress)->fFlags & DBGFADDRESS_FLAGS_HMA)
    115119/** @} */
    116120
     
    546550VMMR3DECL(int)          DBGFR3QueryWaitable(PUVM pUVM);
    547551VMMR3DECL(int)          DBGFR3Resume(PUVM pUVM);
     552VMMR3DECL(int)          DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu);
    548553VMMR3DECL(int)          DBGFR3Step(PUVM pUVM, VMCPUID idCpu);
    549 VMMR3DECL(int)          DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu);
     554VMMR3DECL(int)          DBGFR3StepEx(PUVM pUVM, VMCPUID idCpu, uint32_t fFlags, PCDBGFADDRESS pStopPcAddr,
     555                                     PCDBGFADDRESS pStopPopAddr, RTGCUINTPTR cbStopPop, uint32_t cMaxSteps);
     556
     557/** @name DBGF_STEP_F_XXX - Flags for DBGFR3StepEx.
     558 *
     559 * @note The stop filters are not applied to the starting instruction.
     560 *
     561 * @{ */
     562/** Step into CALL, INT, SYSCALL and SYSENTER instructions. */
     563#define DBGF_STEP_F_INTO                RT_BIT_32(0)
     564/** Step over CALL, INT, SYSCALL and SYSENTER instruction when considering
     565 *  what's "next". */
     566#define DBGF_STEP_F_OVER                RT_BIT_32(1)
     567
     568/** Stop on the next CALL, INT, SYSCALL, SYSENTER instruction. */
     569#define DBGF_STEP_F_STOP_ON_CALL        RT_BIT_32(8)
     570/** Stop on the next RET, IRET, SYSRET, SYSEXIT instruction. */
     571#define DBGF_STEP_F_STOP_ON_RET         RT_BIT_32(9)
     572/** Stop after the next RET, IRET, SYSRET, SYSEXIT instruction. */
     573#define DBGF_STEP_F_STOP_AFTER_RET      RT_BIT_32(10)
     574/** Stop on the given address.
     575 * The comparison will be made using effective (flat) addresses.  */
     576#define DBGF_STEP_F_STOP_ON_ADDRESS     RT_BIT_32(11)
     577/** Stop when the stack pointer pops to or past the given address.
     578 * The comparison will be made using effective (flat) addresses.  */
     579#define DBGF_STEP_F_STOP_ON_STACK_POP   RT_BIT_32(12)
     580/** Mask of stop filter flags. */
     581#define DBGF_STEP_F_STOP_FILTER_MASK    UINT32_C(0x00001f00)
     582
     583/** Mask of valid flags. */
     584#define DBGF_STEP_F_VALID_MASK          UINT32_C(0x00001f03)
     585/** @} */
    550586
    551587/**
     
    853889VMMR3DECL(VMCPUID)          DBGFR3CpuGetCount(PUVM pUVM);
    854890VMMR3DECL(bool)             DBGFR3CpuIsIn64BitCode(PUVM pUVM, VMCPUID idCpu);
     891VMMR3DECL(bool)             DBGFR3CpuIsInV86Code(PUVM pUVM, VMCPUID idCpu);
    855892#endif
    856893
  • trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp

    r64655 r64720  
    913913{
    914914    return pVCpu->cpum.s.Guest.ss.Sel;
     915}
     916
     917
     918VMMDECL(uint64_t)   CPUMGetGuestFlatPC(PVMCPU pVCpu)
     919{
     920    CPUMSELREG_LAZY_LOAD_HIDDEN_PARTS(pVCpu, &pVCpu->cpum.s.Guest.cs);
     921    if (   !CPUMIsGuestInLongMode(pVCpu)
     922        || pVCpu->cpum.s.Guest.cs.Attr.n.u1Long)
     923        return pVCpu->cpum.s.Guest.eip + (uint32_t)pVCpu->cpum.s.Guest.cs.u64Base;
     924    return pVCpu->cpum.s.Guest.rip + pVCpu->cpum.s.Guest.cs.u64Base;
     925}
     926
     927
     928VMMDECL(uint64_t)   CPUMGetGuestFlatSP(PVMCPU pVCpu)
     929{
     930    CPUMSELREG_LAZY_LOAD_HIDDEN_PARTS(pVCpu, &pVCpu->cpum.s.Guest.ss);
     931    if (   !CPUMIsGuestInLongMode(pVCpu)
     932        || pVCpu->cpum.s.Guest.ss.Attr.n.u1Long)
     933        return pVCpu->cpum.s.Guest.eip + (uint32_t)pVCpu->cpum.s.Guest.ss.u64Base;
     934    return pVCpu->cpum.s.Guest.rip + pVCpu->cpum.s.Guest.ss.u64Base;
    915935}
    916936
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r63560 r64720  
    9494
    9595/*********************************************************************************************************************************
     96*   Structures and Typedefs                                                                                                      *
     97*********************************************************************************************************************************/
     98/**
     99 * Instruction type returned by dbgfStepGetCurInstrType.
     100 */
     101typedef enum DBGFSTEPINSTRTYPE
     102{
     103    DBGFSTEPINSTRTYPE_INVALID = 0,
     104    DBGFSTEPINSTRTYPE_OTHER,
     105    DBGFSTEPINSTRTYPE_RET,
     106    DBGFSTEPINSTRTYPE_CALL,
     107    DBGFSTEPINSTRTYPE_END,
     108    DBGFSTEPINSTRTYPE_32BIT_HACK = 0x7fffffff
     109} DBGFSTEPINSTRTYPE;
     110
     111
     112/*********************************************************************************************************************************
    96113*   Internal Functions                                                                                                           *
    97114*********************************************************************************************************************************/
     
    99116static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution);
    100117static DECLCALLBACK(int) dbgfR3Attach(PVM pVM);
     118static DBGFSTEPINSTRTYPE dbgfStepGetCurInstrType(PVM pVM, PVMCPU pVCpu);
     119static bool dbgfStepAreWeThereYet(PVM pVM,  PVMCPU pVCpu);
    101120
    102121
     
    140159    AssertCompile(sizeof(pUVM->dbgf.s)          <= sizeof(pUVM->dbgf.padding));
    141160    AssertCompile(sizeof(pUVM->aCpus[0].dbgf.s) <= sizeof(pUVM->aCpus[0].dbgf.padding));
     161
     162    pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
    142163
    143164    /*
     
    550571static int dbgfR3SendEvent(PVM pVM)
    551572{
     573    pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
     574
    552575    int rc = RTSemPing(&pVM->dbgf.s.PingPong);
    553576    if (RT_SUCCESS(rc))
     
    613636VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent)
    614637{
     638    /*
     639     * Do stepping filtering.
     640     */
     641    /** @todo Would be better if we did some of this inside the execution
     642     *        engines. */
     643    if (   enmEvent == DBGFEVENT_STEPPED
     644        || enmEvent == DBGFEVENT_STEPPED_HYPER)
     645    {
     646        if (!dbgfStepAreWeThereYet(pVM, VMMGetCpu(pVM)))
     647            return VINF_EM_DBG_STEP;
     648    }
     649
    615650    int rc = dbgfR3EventPrologue(pVM, enmEvent);
    616651    if (RT_FAILURE(rc))
     
    891926/**
    892927 * Executes command from debugger.
     928 *
    893929 * The caller is responsible for waiting or resuming execution based on the
    894930 * value returned in the *pfResumeExecution indicator.
     
    947983            pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_DETACH_DONE;
    948984            pVM->dbgf.s.DbgEvent.enmCtx  = DBGFEVENTCTX_OTHER;
     985            pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
    949986            fSendEvent = true;
    950987            fResume = true;
     
    9691006        {
    9701007            Log2(("Single step\n"));
    971             rc = VINF_EM_DBG_STEP;
    9721008            /** @todo SMP */
    9731009            PVMCPU pVCpu = VMMGetCpu0(pVM);
    974             pVCpu->dbgf.s.fSingleSteppingRaw = true;
    975             fSendEvent = false;
    976             fResume = true;
     1010            if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_OVER)
     1011            {
     1012                if (dbgfStepGetCurInstrType(pVM, pVCpu) == DBGFSTEPINSTRTYPE_CALL)
     1013                    pVM->dbgf.s.SteppingFilter.uCallDepth++;
     1014            }
     1015            if (pVM->dbgf.s.SteppingFilter.cMaxSteps > 0)
     1016            {
     1017                pVCpu->dbgf.s.fSingleSteppingRaw = true;
     1018                fSendEvent = false;
     1019                fResume = true;
     1020                rc = VINF_EM_DBG_STEP;
     1021            }
     1022            else
     1023            {
     1024                /* Stop after zero steps. Nonsense, but whatever. */
     1025                pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
     1026                pVM->dbgf.s.DbgEvent.enmCtx  = dbgfR3FigureEventCtx(pVM);
     1027                pVM->dbgf.s.DbgEvent.enmType = pVM->dbgf.s.DbgEvent.enmCtx != DBGFEVENTCTX_HYPER
     1028                                             ? DBGFEVENT_STEPPED : DBGFEVENT_STEPPED_HYPER;
     1029                fSendEvent = false;
     1030                fResume = false;
     1031            }
    9771032            break;
    9781033        }
     
    12791334
    12801335/**
     1336 * Classifies the current instruction.
     1337 *
     1338 * @returns Type of instruction.
     1339 * @param   pVM                 The cross context VM structure.
     1340 * @param   pVCpu               The current CPU.
     1341 * @thread  EMT(pVCpu)
     1342 */
     1343static DBGFSTEPINSTRTYPE dbgfStepGetCurInstrType(PVM pVM, PVMCPU pVCpu)
     1344{
     1345    /*
     1346     * Read the instruction.
     1347     */
     1348    bool     fIsHyper = dbgfR3FigureEventCtx(pVM) == DBGFEVENTCTX_HYPER;
     1349    size_t   cbRead   = 0;
     1350    uint8_t  abOpcode[16] = { 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0 };
     1351    int rc = PGMR3DbgReadGCPtr(pVM, abOpcode, !fIsHyper ? CPUMGetGuestFlatPC(pVCpu) : CPUMGetHyperRIP(pVCpu),
     1352                               sizeof(abOpcode) - 1, 0 /*fFlags*/, &cbRead);
     1353    if (RT_SUCCESS(rc))
     1354    {
     1355        /*
     1356         * Do minimal parsing.  No real need to involve the disassembler here.
     1357         */
     1358        uint8_t *pb = abOpcode;
     1359        for (;;)
     1360        {
     1361            switch (*pb++)
     1362            {
     1363                default:
     1364                    return DBGFSTEPINSTRTYPE_OTHER;
     1365
     1366                case 0xe8: /* call rel16/32 */
     1367                case 0x9a: /* call farptr */
     1368                case 0xcc: /* int3 */
     1369                case 0xcd: /* int xx */
     1370                // case 0xce: /* into */
     1371                    return DBGFSTEPINSTRTYPE_CALL;
     1372
     1373                case 0xc2: /* ret xx */
     1374                case 0xc3: /* ret */
     1375                case 0xca: /* retf xx */
     1376                case 0xcb: /* retf */
     1377                case 0xcf: /* iret */
     1378                    return DBGFSTEPINSTRTYPE_RET;
     1379
     1380                case 0xff:
     1381                    if (   ((*pb >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) == 2  /* call indir */
     1382                        || ((*pb >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) == 3) /* call indir-farptr */
     1383                        return DBGFSTEPINSTRTYPE_CALL;
     1384                    return DBGFSTEPINSTRTYPE_OTHER;
     1385
     1386                case 0x0f:
     1387                    switch (*pb++)
     1388                    {
     1389                        case 0x05: /* syscall */
     1390                        case 0x34: /* sysenter */
     1391                            return DBGFSTEPINSTRTYPE_CALL;
     1392                        case 0x07: /* sysret */
     1393                        case 0x35: /* sysexit */
     1394                            return DBGFSTEPINSTRTYPE_RET;
     1395                    }
     1396                    break;
     1397
     1398                /* Must handle some REX prefixes. So we do all normal prefixes. */
     1399                case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
     1400                case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
     1401                    if (fIsHyper) /* ASSUMES 32-bit raw-mode! */
     1402                        return DBGFSTEPINSTRTYPE_OTHER;
     1403                    if (!CPUMIsGuestIn64BitCode(pVCpu))
     1404                        return DBGFSTEPINSTRTYPE_OTHER;
     1405                    break;
     1406
     1407                case 0x2e: /* CS */
     1408                case 0x36: /* SS */
     1409                case 0x3e: /* DS */
     1410                case 0x26: /* ES */
     1411                case 0x64: /* FS */
     1412                case 0x65: /* GS */
     1413                case 0x66: /* op size */
     1414                case 0x67: /* addr size */
     1415                case 0xf0: /* lock */
     1416                case 0xf2: /* REPNZ */
     1417                case 0xf3: /* REPZ */
     1418                    break;
     1419            }
     1420        }
     1421    }
     1422
     1423    return DBGFSTEPINSTRTYPE_INVALID;
     1424}
     1425
     1426
     1427/**
     1428 * Checks if the stepping has reached a stop point.
     1429 *
     1430 * Called when raising a stepped event.
     1431 *
     1432 * @returns true if the event should be raised, false if we should take one more
     1433 *          step first.
     1434 * @param   pVM         The cross context VM structure.
     1435 * @param   pVCpu       The cross context per CPU structure of the calling EMT.
     1436 * @thread  EMT(pVCpu)
     1437 */
     1438static bool dbgfStepAreWeThereYet(PVM pVM, PVMCPU pVCpu)
     1439{
     1440    /*
     1441     * Check valid pVCpu and that it matches the CPU one stepping.
     1442     */
     1443    if (pVCpu)
     1444    {
     1445        if (pVCpu->idCpu == pVM->dbgf.s.SteppingFilter.idCpu)
     1446        {
     1447            /*
     1448             * Increase the number of steps and see if we've reached the max.
     1449             */
     1450            pVM->dbgf.s.SteppingFilter.cSteps++;
     1451            if (pVM->dbgf.s.SteppingFilter.cSteps < pVM->dbgf.s.SteppingFilter.cMaxSteps)
     1452            {
     1453                /*
     1454                 * Check PC and SP address filtering.
     1455                 */
     1456                if (pVM->dbgf.s.SteppingFilter.fFlags & (DBGF_STEP_F_STOP_ON_ADDRESS || DBGF_STEP_F_STOP_ON_STACK_POP))
     1457                {
     1458                    bool fIsHyper = dbgfR3FigureEventCtx(pVM) == DBGFEVENTCTX_HYPER;
     1459                    if (   (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_ON_ADDRESS)
     1460                        && pVM->dbgf.s.SteppingFilter.AddrPc == (!fIsHyper ? CPUMGetGuestFlatPC(pVCpu) : CPUMGetHyperRIP(pVCpu)))
     1461                        return true;
     1462                    if (   (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_ON_STACK_POP)
     1463                        &&     (!fIsHyper ? CPUMGetGuestFlatSP(pVCpu) : (uint64_t)CPUMGetHyperESP(pVCpu))
     1464                             - pVM->dbgf.s.SteppingFilter.AddrStackPop
     1465                           < pVM->dbgf.s.SteppingFilter.cbStackPop)
     1466                        return true;
     1467                }
     1468
     1469                /*
     1470                 * Do step-over filtering separate from the step-into one.
     1471                 */
     1472                if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_OVER)
     1473                {
     1474                    DBGFSTEPINSTRTYPE enmType = dbgfStepGetCurInstrType(pVM, pVCpu);
     1475                    switch (enmType)
     1476                    {
     1477                        default:
     1478                            if (   pVM->dbgf.s.SteppingFilter.uCallDepth != 0
     1479                                || (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_FILTER_MASK))
     1480                                break;
     1481                            return true;
     1482                        case DBGFSTEPINSTRTYPE_CALL:
     1483                            if (   (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_ON_CALL)
     1484                                && pVM->dbgf.s.SteppingFilter.uCallDepth == 0)
     1485                                return true;
     1486                            pVM->dbgf.s.SteppingFilter.uCallDepth++;
     1487                            break;
     1488                        case DBGFSTEPINSTRTYPE_RET:
     1489                            if (pVM->dbgf.s.SteppingFilter.uCallDepth == 0)
     1490                            {
     1491                                if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_ON_RET)
     1492                                    return true;
     1493                                /* If after return, we use the cMaxStep limit to stop the next time. */
     1494                                if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_AFTER_RET)
     1495                                    pVM->dbgf.s.SteppingFilter.cMaxSteps = pVM->dbgf.s.SteppingFilter.cSteps + 1;
     1496                            }
     1497                            else if (pVM->dbgf.s.SteppingFilter.uCallDepth > 0)
     1498                                pVM->dbgf.s.SteppingFilter.uCallDepth--;
     1499                            break;
     1500                    }
     1501                    return false;
     1502                }
     1503                /*
     1504                 * Filtered step-into.
     1505                 */
     1506                else if (  pVM->dbgf.s.SteppingFilter.fFlags
     1507                         & (DBGF_STEP_F_STOP_ON_CALL | DBGF_STEP_F_STOP_ON_RET | DBGF_STEP_F_STOP_AFTER_RET))
     1508                {
     1509                    DBGFSTEPINSTRTYPE enmType = dbgfStepGetCurInstrType(pVM, pVCpu);
     1510                    switch (enmType)
     1511                    {
     1512                        default:
     1513                            break;
     1514                        case DBGFSTEPINSTRTYPE_CALL:
     1515                            if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_ON_CALL)
     1516                                return true;
     1517                            break;
     1518                        case DBGFSTEPINSTRTYPE_RET:
     1519                            if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_ON_RET)
     1520                                return true;
     1521                            /* If after return, we use the cMaxStep limit to stop the next time. */
     1522                            if (pVM->dbgf.s.SteppingFilter.fFlags & DBGF_STEP_F_STOP_AFTER_RET)
     1523                                pVM->dbgf.s.SteppingFilter.cMaxSteps = pVM->dbgf.s.SteppingFilter.cSteps + 1;
     1524                            break;
     1525                    }
     1526                    return false;
     1527                }
     1528            }
     1529        }
     1530    }
     1531
     1532    return true;
     1533}
     1534
     1535
     1536/**
    12811537 * Step Into.
    12821538 *
     
    12891545 */
    12901546VMMR3DECL(int) DBGFR3Step(PUVM pUVM, VMCPUID idCpu)
     1547{
     1548    return DBGFR3StepEx(pUVM, idCpu, DBGF_STEP_F_INTO, NULL, NULL, 0, 1);
     1549}
     1550
     1551
     1552/**
     1553 * Full fleged step.
     1554 *
     1555 * This extended stepping API allows for doing multiple steps before raising an
     1556 * event, helping implementing step over, step out and other more advanced
     1557 * features.
     1558 *
     1559 * Like the DBGFR3Step() API, this will normally generate a DBGFEVENT_STEPPED or
     1560 * DBGFEVENT_STEPPED_EVENT.  However the stepping may be interrupted by other
     1561 * events, which will abort the stepping.
     1562 *
     1563 * The stop on pop area feature is for safeguarding step out.
     1564 *
     1565 * Please note though, that it will always use stepping and never breakpoints.
     1566 * While this allows for a much greater flexibility it can at times be rather
     1567 * slow.
     1568 *
     1569 * @returns VBox status code.
     1570 * @param   pUVM            The user mode VM handle.
     1571 * @param   idCpu           The ID of the CPU to single step on.
     1572 * @param   fFlags          Flags controlling the stepping, DBGF_STEP_F_XXX.
     1573 *                          Either DBGF_STEP_F_INTO or DBGF_STEP_F_OVER must
     1574 *                          always be specified.
     1575 * @param   pStopPcAddr     Address to stop executing at.  Completely ignored
     1576 *                          unless DBGF_STEP_F_STOP_ON_ADDRESS is specified.
     1577 * @param   pStopPopAddr    Stack address that SP must be lower than when
     1578 *                          performing DBGF_STEP_F_STOP_ON_STACK_POP filtering.
     1579 * @param   cbStopPop       The range starting at @a pStopPopAddr which is
     1580 *                          considered to be within the same thread stack. Note
     1581 *                          that the API allows @a pStopPopAddr and @a cbStopPop
     1582 *                          to form an area that wraps around and it will
     1583 *                          consider the part starting at 0 as included.
     1584 * @param   cMaxStep        The maximum number of steps to take.  This is to
     1585 *                          prevent stepping for ever, so passing UINT32_MAX is
     1586 *                          not recommended.
     1587 *
     1588 * @remarks The two address arguments must be guest context virtual addresses,
     1589 *          or HMA.  The code doesn't make much of a point of out HMA, though.
     1590 */
     1591VMMR3DECL(int) DBGFR3StepEx(PUVM pUVM, VMCPUID idCpu, uint32_t fFlags, PCDBGFADDRESS pStopPcAddr,
     1592                            PCDBGFADDRESS pStopPopAddr, RTGCUINTPTR cbStopPop, uint32_t cMaxSteps)
    12911593{
    12921594    /*
     
    12971599    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    12981600    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_PARAMETER);
     1601    AssertReturn(!(fFlags & ~DBGF_STEP_F_VALID_MASK), VERR_INVALID_FLAGS);
     1602    AssertReturn(RT_BOOL(fFlags & DBGF_STEP_F_INTO) != RT_BOOL(fFlags & DBGF_STEP_F_OVER), VERR_INVALID_FLAGS);
     1603    if (fFlags & DBGF_STEP_F_STOP_ON_ADDRESS)
     1604    {
     1605        AssertReturn(RT_VALID_PTR(pStopPcAddr), VERR_INVALID_POINTER);
     1606        AssertReturn(DBGFADDRESS_IS_VALID(pStopPcAddr), VERR_INVALID_PARAMETER);
     1607        AssertReturn(DBGFADDRESS_IS_VIRT_GC(pStopPcAddr), VERR_INVALID_PARAMETER);
     1608    }
     1609    AssertReturn(!(fFlags & DBGF_STEP_F_STOP_ON_STACK_POP) || RT_VALID_PTR(pStopPopAddr), VERR_INVALID_POINTER);
     1610    if (fFlags & DBGF_STEP_F_STOP_ON_STACK_POP)
     1611    {
     1612        AssertReturn(RT_VALID_PTR(pStopPopAddr), VERR_INVALID_POINTER);
     1613        AssertReturn(DBGFADDRESS_IS_VALID(pStopPopAddr), VERR_INVALID_PARAMETER);
     1614        AssertReturn(DBGFADDRESS_IS_VIRT_GC(pStopPopAddr), VERR_INVALID_PARAMETER);
     1615        AssertReturn(cbStopPop > 0, VERR_INVALID_PARAMETER);
     1616    }
     1617
    12991618    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
    13001619    if (RT_LIKELY(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong)))
     
    13021621    else
    13031622        return VERR_SEM_OUT_OF_TURN;
     1623    Assert(pVM->dbgf.s.SteppingFilter.idCpu == NIL_VMCPUID);
    13041624
    13051625    /*
    13061626     * Send the ping back to the emulation thread telling it to run.
    13071627     */
     1628    if (fFlags == DBGF_STEP_F_INTO)
     1629        pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID;
     1630    else
     1631        pVM->dbgf.s.SteppingFilter.idCpu = idCpu;
     1632    pVM->dbgf.s.SteppingFilter.fFlags = fFlags;
     1633    if (fFlags & DBGF_STEP_F_STOP_ON_ADDRESS)
     1634        pVM->dbgf.s.SteppingFilter.AddrPc = pStopPcAddr->FlatPtr;
     1635    else
     1636        pVM->dbgf.s.SteppingFilter.AddrPc = 0;
     1637    if (fFlags & DBGF_STEP_F_STOP_ON_STACK_POP)
     1638    {
     1639        pVM->dbgf.s.SteppingFilter.AddrStackPop = pStopPopAddr->FlatPtr;
     1640        pVM->dbgf.s.SteppingFilter.cbStackPop   = cbStopPop;
     1641    }
     1642    else
     1643    {
     1644        pVM->dbgf.s.SteppingFilter.AddrStackPop = 0;
     1645        pVM->dbgf.s.SteppingFilter.cbStackPop   = RTGCPTR_MAX;
     1646    }
     1647
     1648    pVM->dbgf.s.SteppingFilter.cMaxSteps    = cMaxSteps;
     1649    pVM->dbgf.s.SteppingFilter.cSteps       = 0;
     1650    pVM->dbgf.s.SteppingFilter.uCallDepth   = 0;
     1651
    13081652/** @todo SMP (idCpu) */
    13091653    dbgfR3SetCmd(pVM, DBGFCMD_SINGLE_STEP);
  • trunk/src/VBox/VMM/VMMR3/DBGFCpu.cpp

    r62478 r64720  
    109109
    110110/**
     111 * Wrapper around CPUMIsGuestInV86Code.
     112 *
     113 * @returns VINF_SUCCESS.
     114 * @param   pVM             The cross context VM structure.
     115 * @param   idCpu           The current CPU ID.
     116 * @param   pfInV86Code     Where to return the result.
     117 */
     118static DECLCALLBACK(int) dbgfR3CpuInV86Code(PVM pVM, VMCPUID idCpu, bool *pfInV86Code)
     119{
     120    Assert(idCpu == VMMGetCpuId(pVM));
     121    PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
     122    *pfInV86Code = CPUMIsGuestInV86ModeEx(CPUMQueryGuestCtxPtr(pVCpu));
     123    return VINF_SUCCESS;
     124}
     125
     126
     127/**
     128 * Checks if the given CPU is executing V8086 code or not.
     129 *
     130 * @returns true / false accordingly.
     131 * @param   pUVM        The user mode VM handle.
     132 * @param   idCpu       The target CPU ID.
     133 */
     134VMMR3DECL(bool) DBGFR3CpuIsInV86Code(PUVM pUVM, VMCPUID idCpu)
     135{
     136    UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     137    VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, false);
     138    AssertReturn(idCpu < pUVM->pVM->cCpus, false);
     139
     140    bool fInV86Code;
     141    int rc = VMR3ReqPriorityCallWaitU(pUVM, idCpu, (PFNRT)dbgfR3CpuInV86Code, 3, pUVM->pVM, idCpu, &fInV86Code);
     142    if (RT_FAILURE(rc))
     143        return false;
     144    return fInV86Code;
     145}
     146
     147
     148/**
    111149 * Get the number of CPUs (or threads if you insist).
    112150 *
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r64499 r64720  
    247247     * Not all commands take data. */
    248248    DBGFCMDDATA                 VMMCmdData;
     249
     250    /** Stepping filtering. */
     251    struct
     252    {
     253        /** The CPU doing the stepping.
     254         * Set to NIL_VMCPUID when filtering is inactive */
     255        VMCPUID                 idCpu;
     256        /** The specified flags. */
     257        uint32_t                fFlags;
     258        /** The effective PC address to stop at, if given. */
     259        RTGCPTR                 AddrPc;
     260        /** The lowest effective stack address to stop at.
     261         * Together with cbStackPop, this forms a range of effective stack pointer
     262         * addresses that we stop for.   */
     263        RTGCPTR                 AddrStackPop;
     264        /** The size of the stack stop area starting at AddrStackPop. */
     265        RTGCPTR                 cbStackPop;
     266        /** Maximum number of steps. */
     267        uint32_t                cMaxSteps;
     268
     269        /** Number of steps made thus far. */
     270        uint32_t                cSteps;
     271        /** Current call counting balance for step-over handling. */
     272        uint32_t                uCallDepth;
     273
     274        uint32_t                u32Padding; /**< Alignment padding. */
     275
     276    } SteppingFilter;
    249277
    250278    uint32_t                    u32Padding; /**< Alignment padding. */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette