- Timestamp:
- Nov 4, 2016 10:37:28 AM (8 years ago)
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFR3Cfg.cpp
r64530 r64552 132 132 133 133 /** 134 * Control flow graph iterator state. 135 */ 136 typedef struct DBGFCFGITINT 137 { 138 /** Pointer to the control flow graph (holding a reference). */ 139 PDBGFCFGINT pCfg; 140 /** Next basic block to return. */ 141 uint32_t idxBbNext; 142 /** Array of basic blocks sorted by the specified order - variable in size. */ 143 PDBGFCFGBBINT apBb[1]; 144 } DBGFCFGITINT; 145 /** Pointer to the internal control flow graph iterator state. */ 146 typedef DBGFCFGITINT *PDBGFCFGITINT; 147 148 /** 134 149 * Dumper state for a basic block. 135 150 */ … … 846 861 AssertFailed(); /* Should never get here. */ 847 862 return VERR_INTERNAL_ERROR; 863 } 864 865 866 /** 867 * Queries a basic block in the given control flow graph which covers the given 868 * address. 869 * 870 * @returns VBox status code. 871 * @retval VERR_NOT_FOUND if there is no basic block intersecting with the address. 872 * @param hCfg The control flow graph handle. 873 * @param pAddr The address to look for. 874 * @param phCfgBb Where to store the basic block handle on success. 875 */ 876 VMMR3DECL(int) DBGFR3CfgQueryBbByAddress(DBGFCFG hCfg, PDBGFADDRESS pAddr, PDBGFCFGBB phCfgBb) 877 { 878 PDBGFCFGINT pThis = hCfg; 879 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 880 AssertPtrReturn(phCfgBb, VERR_INVALID_POINTER); 881 882 PDBGFCFGBBINT pCfgBb = NULL; 883 RTListForEach(&pThis->LstCfgBb, pCfgBb, DBGFCFGBBINT, NdCfgBb) 884 { 885 if (dbgfR3CfgBbAddrIntersect(pCfgBb, pAddr)) 886 { 887 DBGFR3CfgBbRetain(pCfgBb); 888 *phCfgBb = pCfgBb; 889 return VINF_SUCCESS; 890 } 891 } 892 893 return VERR_NOT_FOUND; 894 } 895 896 897 /** 898 * Returns the number of basic blcoks inside the control flow graph. 899 * 900 * @returns Number of basic blocks. 901 * @param hCfg The control flow graph handle. 902 */ 903 VMMR3DECL(uint32_t) DBGFR3CfgGetBbCount(DBGFCFG hCfg) 904 { 905 PDBGFCFGINT pThis = hCfg; 906 AssertPtrReturn(pThis, 0); 907 908 return pThis->cBbs; 848 909 } 849 910 … … 1423 1484 1424 1485 /** 1486 * Returns the address the last instruction in the basic block branches to. 1487 * 1488 * @returns Pointer to DBGF adress containing the branch address of the basic block. 1489 * @param hCfgBb The basic block handle. 1490 * @param pAddrTarget Where to store the branch address of the basic block. 1491 * 1492 * @note This is only valid for unconditional or conditional branches and will assert 1493 * for every other basic block type. 1494 */ 1495 VMMR3DECL(PDBGFADDRESS) DBGFR3CfgBbGetBranchAddress(DBGFCFGBB hCfgBb, PDBGFADDRESS pAddrTarget) 1496 { 1497 PDBGFCFGBBINT pCfgBb = hCfgBb; 1498 AssertPtrReturn(pCfgBb, NULL); 1499 AssertPtrReturn(pAddrTarget, NULL); 1500 AssertReturn( pCfgBb->enmEndType == DBGFCFGBBENDTYPE_UNCOND_JMP 1501 || pCfgBb->enmEndType == DBGFCFGBBENDTYPE_COND, 1502 NULL); 1503 1504 *pAddrTarget = pCfgBb->AddrTarget; 1505 return pAddrTarget; 1506 } 1507 1508 1509 /** 1510 * Returns the address of the next block following this one in the instruction stream. 1511 * (usually end address + 1). 1512 * 1513 * @returns Pointer to DBGF adress containing the following address of the basic block. 1514 * @param hCfgBb The basic block handle. 1515 * @param pAddrFollow Where to store the following address of the basic block. 1516 * 1517 * @note This is only valid for conditional branches and if the last instruction in the 1518 * given basic block doesn't change the control flow but the blocks were split 1519 * because the successor is referenced by multiple other blocks as an entry point. 1520 */ 1521 VMMR3DECL(PDBGFADDRESS) DBGFR3CfgBbGetFollowingAddress(DBGFCFGBB hCfgBb, PDBGFADDRESS pAddrFollow) 1522 { 1523 PDBGFCFGBBINT pCfgBb = hCfgBb; 1524 AssertPtrReturn(pCfgBb, NULL); 1525 AssertPtrReturn(pAddrFollow, NULL); 1526 AssertReturn( pCfgBb->enmEndType == DBGFCFGBBENDTYPE_UNCOND 1527 || pCfgBb->enmEndType == DBGFCFGBBENDTYPE_COND, 1528 NULL); 1529 1530 *pAddrFollow = pCfgBb->AddrEnd; 1531 DBGFR3AddrAdd(pAddrFollow, 1); 1532 return pAddrFollow; 1533 } 1534 1535 1536 /** 1425 1537 * Returns the type of the last instruction in the basic block. 1426 1538 * … … 1468 1580 1469 1581 /** 1582 * Returns the error status and message if the given basic block has an error. 1583 * 1584 * @returns VBox status code of the error for the basic block. 1585 * @param hCfgBb The basic block handle. 1586 * @param ppszErr Where to store the pointer to the error message - optional. 1587 */ 1588 VMMR3DECL(int) DBGFR3CfgBbQueryError(DBGFCFGBB hCfgBb, const char **ppszErr) 1589 { 1590 PDBGFCFGBBINT pCfgBb = hCfgBb; 1591 AssertPtrReturn(pCfgBb, VERR_INVALID_HANDLE); 1592 1593 if (ppszErr) 1594 *ppszErr = pCfgBb->pszErr; 1595 1596 return pCfgBb->rcError; 1597 } 1598 1599 1600 /** 1470 1601 * Store the disassembled instruction as a string in the given output buffer. 1471 1602 * 1472 1603 * @returns VBox status code. 1473 * @retval VERR_BUFFER_OVERFLOW if the size of the output buffer can't hold the complete string.1474 1604 * @param hCfgBb The basic block handle. 1475 1605 * @param idxInstr The instruction to query. 1476 1606 * @param pAddrInstr Where to store the guest instruction address on success, optional. 1477 1607 * @param pcbInstr Where to store the instruction size on success, optional. 1478 * @param pszOutput Where to store the disassembled instruction, optional. 1479 * @param cbOutput Size of the output buffer. 1608 * @param ppszInstr Where to store the pointer to the disassembled instruction string, optional. 1480 1609 */ 1481 1610 VMMR3DECL(int) DBGFR3CfgBbQueryInstr(DBGFCFGBB hCfgBb, uint32_t idxInstr, PDBGFADDRESS pAddrInstr, 1482 uint32_t *pcbInstr, char *pszOutput, uint32_t cbOutput) 1483 { 1484 int rc = VINF_SUCCESS; 1611 uint32_t *pcbInstr, const char **ppszInstr) 1612 { 1485 1613 PDBGFCFGBBINT pCfgBb = hCfgBb; 1486 1614 AssertPtrReturn(pCfgBb, VERR_INVALID_POINTER); 1487 1615 AssertReturn(idxInstr < pCfgBb->cInstr, VERR_INVALID_PARAMETER); 1488 AssertReturn( (VALID_PTR(pszOutput) && cbOutput > 0)1489 || (!pszOutput && !cbOutput), VERR_INVALID_PARAMETER);1490 1616 1491 1617 if (pAddrInstr) … … 1493 1619 if (pcbInstr) 1494 1620 *pcbInstr = pCfgBb->aInstr[idxInstr].cbInstr; 1495 if ( cbOutput)1496 rc = RTStrCopy(pszOutput, cbOutput, pCfgBb->aInstr[idxInstr].pszInstr);1497 1498 return rc;1621 if (ppszInstr) 1622 *ppszInstr = pCfgBb->aInstr[idxInstr].pszInstr; 1623 1624 return VINF_SUCCESS; 1499 1625 } 1500 1626 … … 1505 1631 * @returns VBox status code. 1506 1632 * @param hCfgBb The basic block handle. 1507 * @param pahCfgBbSucc Where to store the handles to the basic blocks succeeding the given one. 1508 * @param cSucc Number of entries the handle array can hold. 1509 */ 1510 VMMR3DECL(int) DBGFR3CfgBbQuerySuccessors(DBGFCFGBB hCfgBb, PDBGFCFGBB pahCfgBbSucc, uint32_t cSucc) 1511 { 1512 RT_NOREF3(hCfgBb, pahCfgBbSucc, cSucc); 1513 return VERR_NOT_IMPLEMENTED; 1633 * @param phCfgBbFollow Where to store the handle to the basic block following 1634 * this one (optional). 1635 * @param phCfgBbTarget Where to store the handle to the basic block being the 1636 * branch target for this one (optional). 1637 */ 1638 VMMR3DECL(int) DBGFR3CfgBbQuerySuccessors(DBGFCFGBB hCfgBb, PDBGFCFGBB phCfgBbFollow, PDBGFCFGBB phCfgBbTarget) 1639 { 1640 PDBGFCFGBBINT pCfgBb = hCfgBb; 1641 AssertPtrReturn(pCfgBb, VERR_INVALID_POINTER); 1642 1643 if ( phCfgBbFollow 1644 && ( pCfgBb->enmEndType == DBGFCFGBBENDTYPE_UNCOND 1645 || pCfgBb->enmEndType == DBGFCFGBBENDTYPE_COND)) 1646 { 1647 DBGFADDRESS AddrStart = pCfgBb->AddrEnd; 1648 DBGFR3AddrAdd(&AddrStart, 1); 1649 int rc = DBGFR3CfgQueryBbByAddress(pCfgBb->pCfg, &AddrStart, phCfgBbFollow); 1650 AssertRC(rc); 1651 } 1652 1653 if ( phCfgBbTarget 1654 && ( pCfgBb->enmEndType == DBGFCFGBBENDTYPE_UNCOND_JMP 1655 || pCfgBb->enmEndType == DBGFCFGBBENDTYPE_COND)) 1656 { 1657 int rc = DBGFR3CfgQueryBbByAddress(pCfgBb->pCfg, &pCfgBb->AddrTarget, phCfgBbTarget); 1658 AssertRC(rc); 1659 } 1660 1661 return VINF_SUCCESS; 1514 1662 } 1515 1663 … … 1520 1668 * @returns Number of other basic blocks referencing this one. 1521 1669 * @param hCfgBb The basic block handle. 1670 * 1671 * @note If the given basic block references itself (loop, etc.) this will be counted as well. 1522 1672 */ 1523 1673 VMMR3DECL(uint32_t) DBGFR3CfgBbGetRefBbCount(DBGFCFGBB hCfgBb) 1524 1674 { 1525 RT_NOREF1(hCfgBb); 1526 return 0; 1675 PDBGFCFGBBINT pCfgBb = hCfgBb; 1676 AssertPtrReturn(pCfgBb, 0); 1677 1678 uint32_t cRefsBb = 0; 1679 PDBGFCFGBBINT pCfgBbCur = NULL; 1680 RTListForEach(&pCfgBb->pCfg->LstCfgBb, pCfgBbCur, DBGFCFGBBINT, NdCfgBb) 1681 { 1682 if (pCfgBbCur->fFlags & DBGF_CFG_BB_F_INCOMPLETE_ERR) 1683 continue; 1684 1685 if ( pCfgBbCur->enmEndType == DBGFCFGBBENDTYPE_UNCOND 1686 || pCfgBbCur->enmEndType == DBGFCFGBBENDTYPE_COND) 1687 { 1688 DBGFADDRESS AddrStart = pCfgBb->AddrEnd; 1689 DBGFR3AddrAdd(&AddrStart, 1); 1690 if (dbgfR3CfgBbAddrEqual(&pCfgBbCur->AddrStart, &AddrStart)) 1691 cRefsBb++; 1692 } 1693 1694 if ( ( pCfgBbCur->enmEndType == DBGFCFGBBENDTYPE_UNCOND_JMP 1695 || pCfgBbCur->enmEndType == DBGFCFGBBENDTYPE_COND) 1696 && dbgfR3CfgBbAddrEqual(&pCfgBbCur->AddrStart, &pCfgBb->AddrTarget)) 1697 cRefsBb++; 1698 } 1699 return cRefsBb; 1527 1700 } 1528 1701 … … 1532 1705 * 1533 1706 * @returns VBox status code. 1707 * @retval VERR_BUFFER_OVERFLOW if the array can't hold all the basic blocks. 1534 1708 * @param hCfgBb The basic block handle. 1535 1709 * @param paCfgBbRef Pointer to the array containing the referencing basic block handles on success. … … 1542 1716 } 1543 1717 1718 1719 /** 1720 * @callback_method_impl{FNRTSORTCMP} 1721 */ 1722 static DECLCALLBACK(int) dbgfR3CfgItSortCmp(void const *pvElement1, void const *pvElement2, void *pvUser) 1723 { 1724 PDBGFCFGITORDER penmOrder = (PDBGFCFGITORDER)pvUser; 1725 PDBGFCFGBBINT pCfgBb1 = *(PDBGFCFGBBINT *)pvElement1; 1726 PDBGFCFGBBINT pCfgBb2 = *(PDBGFCFGBBINT *)pvElement2; 1727 1728 if (dbgfR3CfgBbAddrEqual(&pCfgBb1->AddrStart, &pCfgBb2->AddrStart)) 1729 return 0; 1730 1731 if (*penmOrder == DBGFCFGITORDER_BY_ADDR_LOWEST_FIRST) 1732 { 1733 if (dbgfR3CfgBbAddrLower(&pCfgBb1->AddrStart, &pCfgBb2->AddrStart)) 1734 return -1; 1735 else 1736 return 1; 1737 } 1738 else 1739 { 1740 if (dbgfR3CfgBbAddrLower(&pCfgBb1->AddrStart, &pCfgBb2->AddrStart)) 1741 return 1; 1742 else 1743 return -1; 1744 } 1745 1746 AssertFailed(); 1747 } 1748 1749 1750 /** 1751 * Creates a new iterator for the given control flow graph. 1752 * 1753 * @returns VBox status code. 1754 * @param hCfg The control flow graph handle. 1755 * @param enmOrder The order in which the basic blocks are enumerated. 1756 * @param phCfgIt Where to store the handle to the iterator on success. 1757 */ 1758 VMMR3DECL(int) DBGFR3CfgItCreate(DBGFCFG hCfg, DBGFCFGITORDER enmOrder, PDBGFCFGIT phCfgIt) 1759 { 1760 int rc = VINF_SUCCESS; 1761 PDBGFCFGINT pCfg = hCfg; 1762 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1763 AssertPtrReturn(phCfgIt, VERR_INVALID_POINTER); 1764 AssertReturn(enmOrder > DBGFCFGITORDER_INVALID && enmOrder < DBGFCFGITORDER_BREADTH_FIRST, 1765 VERR_INVALID_PARAMETER); 1766 AssertReturn(enmOrder < DBGFCFGITORDER_DEPTH_FRIST, VERR_NOT_IMPLEMENTED); /** @todo */ 1767 1768 PDBGFCFGITINT pIt = (PDBGFCFGITINT)RTMemAllocZ(RT_OFFSETOF(DBGFCFGITINT, apBb[pCfg->cBbs])); 1769 if (RT_LIKELY(pIt)) 1770 { 1771 DBGFR3CfgRetain(hCfg); 1772 pIt->pCfg = pCfg; 1773 pIt->idxBbNext = 0; 1774 /* Fill the list and then sort. */ 1775 PDBGFCFGBBINT pCfgBb; 1776 uint32_t idxBb = 0; 1777 RTListForEach(&pCfg->LstCfgBb, pCfgBb, DBGFCFGBBINT, NdCfgBb) 1778 { 1779 DBGFR3CfgBbRetain(pCfgBb); 1780 pIt->apBb[idxBb++] = pCfgBb; 1781 } 1782 1783 /* Sort the blocks by address. */ 1784 RTSortShell(&pIt->apBb[0], pCfg->cBbs, sizeof(PDBGFCFGBBINT), dbgfR3CfgItSortCmp, &enmOrder); 1785 1786 *phCfgIt = pIt; 1787 } 1788 else 1789 rc = VERR_NO_MEMORY; 1790 1791 return rc; 1792 } 1793 1794 1795 /** 1796 * Destroys a given control flow graph iterator. 1797 * 1798 * @returns nothing. 1799 * @param hCfgIt The control flow graph iterator handle. 1800 */ 1801 VMMR3DECL(void) DBGFR3CfgItDestroy(DBGFCFGIT hCfgIt) 1802 { 1803 PDBGFCFGITINT pIt = hCfgIt; 1804 AssertPtrReturnVoid(pIt); 1805 1806 for (unsigned i = 0; i < pIt->pCfg->cBbs; i++) 1807 DBGFR3CfgBbRelease(pIt->apBb[i]); 1808 1809 DBGFR3CfgRelease(pIt->pCfg); 1810 RTMemFree(pIt); 1811 } 1812 1813 1814 /** 1815 * Returns the next basic block in the iterator or NULL if there is no 1816 * basic block left. 1817 * 1818 * @returns Handle to the next basic block in the iterator or NULL if the end 1819 * was reached. 1820 * @param hCfgIt The iterator handle. 1821 * 1822 * @note If a valid handle is returned it must be release with DBGFR3CfgBbRelease() 1823 * when not required anymore. 1824 */ 1825 VMMR3DECL(DBGFCFGBB) DBGFR3CfgItNext(DBGFCFGIT hCfgIt) 1826 { 1827 PDBGFCFGITINT pIt = hCfgIt; 1828 AssertPtrReturn(pIt, NULL); 1829 1830 PDBGFCFGBBINT pCfgBb = NULL; 1831 if (pIt->idxBbNext < pIt->pCfg->cBbs) 1832 { 1833 pCfgBb = pIt->apBb[pIt->idxBbNext++]; 1834 DBGFR3CfgBbRetain(pCfgBb); 1835 } 1836 1837 return pCfgBb; 1838 } 1839 1840 1841 /** 1842 * Resets the given iterator to the beginning. 1843 * 1844 * @returns VBox status code. 1845 * @param hCfgIt The iterator handle. 1846 */ 1847 VMMR3DECL(int) DBGFR3CfgItReset(DBGFCFGIT hCfgIt) 1848 { 1849 PDBGFCFGITINT pIt = hCfgIt; 1850 AssertPtrReturn(pIt, VERR_INVALID_HANDLE); 1851 1852 pIt->idxBbNext = 0; 1853 return VINF_SUCCESS; 1854 } -
trunk/src/VBox/VMM/VMMR3/VMMR3.def
r64500 r64552 134 134 DBGFR3CfgRelease 135 135 DBGFR3CfgQueryStartBb 136 DBGFR3CfgQueryBbByAddress 137 DBGFR3CfgGetBbCount 136 138 DBGFR3CfgDump 137 139 DBGFR3CfgBbRetain … … 139 141 DBGFR3CfgBbGetStartAddress 140 142 DBGFR3CfgBbGetEndAddress 143 DBGFR3CfgBbGetBranchAddress 144 DBGFR3CfgBbGetFollowingAddress 141 145 DBGFR3CfgBbGetType 142 146 DBGFR3CfgBbGetInstrCount 143 147 DBGFR3CfgBbGetFlags 148 DBGFR3CfgBbQueryError 144 149 DBGFR3CfgBbQueryInstr 145 150 DBGFR3CfgBbQuerySuccessors 146 151 DBGFR3CfgBbGetRefBbCount 147 152 DBGFR3CfgBbGetRefBb 153 DBGFR3CfgItCreate 154 DBGFR3CfgItDestroy 155 DBGFR3CfgItNext 156 DBGFR3CfgItReset 148 157 DBGFR3PlugInLoad 149 158 DBGFR3PlugInUnload
Note:
See TracChangeset
for help on using the changeset viewer.