Changeset 64720 in vbox
- Timestamp:
- Nov 20, 2016 2:00:02 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 112004
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/cpum.h
r62476 r64720 1066 1066 VMMDECL(RTSEL) CPUMGetGuestGS(PVMCPU pVCpu); 1067 1067 VMMDECL(RTSEL) CPUMGetGuestSS(PVMCPU pVCpu); 1068 VMMDECL(uint64_t) CPUMGetGuestFlatPC(PVMCPU pVCpu); 1069 VMMDECL(uint64_t) CPUMGetGuestFlatSP(PVMCPU pVCpu); 1068 1070 VMMDECL(uint64_t) CPUMGetGuestDR0(PVMCPU pVCpu); 1069 1071 VMMDECL(uint64_t) CPUMGetGuestDR1(PVMCPU pVCpu); -
trunk/include/VBox/vmm/dbgf.h
r64590 r64720 87 87 /** A physical address. */ 88 88 #define DBGFADDRESS_FLAGS_PHYS 4 89 /** A physical address. */89 /** A ring-0 host address (internal use only). */ 90 90 #define DBGFADDRESS_FLAGS_RING0 5 91 91 /** The address type mask. */ … … 109 109 /** Checks if the mixed address is far 16:64 or not. */ 110 110 #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 ) 111 115 /** 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) 113 117 /** 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) 115 119 /** @} */ 116 120 … … 546 550 VMMR3DECL(int) DBGFR3QueryWaitable(PUVM pUVM); 547 551 VMMR3DECL(int) DBGFR3Resume(PUVM pUVM); 552 VMMR3DECL(int) DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu); 548 553 VMMR3DECL(int) DBGFR3Step(PUVM pUVM, VMCPUID idCpu); 549 VMMR3DECL(int) DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu); 554 VMMR3DECL(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 /** @} */ 550 586 551 587 /** … … 853 889 VMMR3DECL(VMCPUID) DBGFR3CpuGetCount(PUVM pUVM); 854 890 VMMR3DECL(bool) DBGFR3CpuIsIn64BitCode(PUVM pUVM, VMCPUID idCpu); 891 VMMR3DECL(bool) DBGFR3CpuIsInV86Code(PUVM pUVM, VMCPUID idCpu); 855 892 #endif 856 893 -
trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
r64655 r64720 913 913 { 914 914 return pVCpu->cpum.s.Guest.ss.Sel; 915 } 916 917 918 VMMDECL(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 928 VMMDECL(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; 915 935 } 916 936 -
trunk/src/VBox/VMM/VMMR3/DBGF.cpp
r63560 r64720 94 94 95 95 /********************************************************************************************************************************* 96 * Structures and Typedefs * 97 *********************************************************************************************************************************/ 98 /** 99 * Instruction type returned by dbgfStepGetCurInstrType. 100 */ 101 typedef 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 /********************************************************************************************************************************* 96 113 * Internal Functions * 97 114 *********************************************************************************************************************************/ … … 99 116 static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution); 100 117 static DECLCALLBACK(int) dbgfR3Attach(PVM pVM); 118 static DBGFSTEPINSTRTYPE dbgfStepGetCurInstrType(PVM pVM, PVMCPU pVCpu); 119 static bool dbgfStepAreWeThereYet(PVM pVM, PVMCPU pVCpu); 101 120 102 121 … … 140 159 AssertCompile(sizeof(pUVM->dbgf.s) <= sizeof(pUVM->dbgf.padding)); 141 160 AssertCompile(sizeof(pUVM->aCpus[0].dbgf.s) <= sizeof(pUVM->aCpus[0].dbgf.padding)); 161 162 pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID; 142 163 143 164 /* … … 550 571 static int dbgfR3SendEvent(PVM pVM) 551 572 { 573 pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID; 574 552 575 int rc = RTSemPing(&pVM->dbgf.s.PingPong); 553 576 if (RT_SUCCESS(rc)) … … 613 636 VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent) 614 637 { 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 615 650 int rc = dbgfR3EventPrologue(pVM, enmEvent); 616 651 if (RT_FAILURE(rc)) … … 891 926 /** 892 927 * Executes command from debugger. 928 * 893 929 * The caller is responsible for waiting or resuming execution based on the 894 930 * value returned in the *pfResumeExecution indicator. … … 947 983 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_DETACH_DONE; 948 984 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_OTHER; 985 pVM->dbgf.s.SteppingFilter.idCpu = NIL_VMCPUID; 949 986 fSendEvent = true; 950 987 fResume = true; … … 969 1006 { 970 1007 Log2(("Single step\n")); 971 rc = VINF_EM_DBG_STEP;972 1008 /** @todo SMP */ 973 1009 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 } 977 1032 break; 978 1033 } … … 1279 1334 1280 1335 /** 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 */ 1343 static 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 */ 1438 static 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 /** 1281 1537 * Step Into. 1282 1538 * … … 1289 1545 */ 1290 1546 VMMR3DECL(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 */ 1591 VMMR3DECL(int) DBGFR3StepEx(PUVM pUVM, VMCPUID idCpu, uint32_t fFlags, PCDBGFADDRESS pStopPcAddr, 1592 PCDBGFADDRESS pStopPopAddr, RTGCUINTPTR cbStopPop, uint32_t cMaxSteps) 1291 1593 { 1292 1594 /* … … 1297 1599 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1298 1600 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 1299 1618 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED); 1300 1619 if (RT_LIKELY(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong))) … … 1302 1621 else 1303 1622 return VERR_SEM_OUT_OF_TURN; 1623 Assert(pVM->dbgf.s.SteppingFilter.idCpu == NIL_VMCPUID); 1304 1624 1305 1625 /* 1306 1626 * Send the ping back to the emulation thread telling it to run. 1307 1627 */ 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 1308 1652 /** @todo SMP (idCpu) */ 1309 1653 dbgfR3SetCmd(pVM, DBGFCMD_SINGLE_STEP); -
trunk/src/VBox/VMM/VMMR3/DBGFCpu.cpp
r62478 r64720 109 109 110 110 /** 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 */ 118 static 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 */ 134 VMMR3DECL(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 /** 111 149 * Get the number of CPUs (or threads if you insist). 112 150 * -
trunk/src/VBox/VMM/include/DBGFInternal.h
r64499 r64720 247 247 * Not all commands take data. */ 248 248 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; 249 277 250 278 uint32_t u32Padding; /**< Alignment padding. */
Note:
See TracChangeset
for help on using the changeset viewer.