VirtualBox

Changeset 64552 in vbox for trunk/src


Ignore:
Timestamp:
Nov 4, 2016 10:37:28 AM (8 years ago)
Author:
vboxsync
Message:

DBGFR3Cfg: Additions to the API

Location:
trunk/src/VBox/VMM/VMMR3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/DBGFR3Cfg.cpp

    r64530 r64552  
    132132
    133133/**
     134 * Control flow graph iterator state.
     135 */
     136typedef 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. */
     146typedef DBGFCFGITINT *PDBGFCFGITINT;
     147
     148/**
    134149 * Dumper state for a basic block.
    135150 */
     
    846861    AssertFailed(); /* Should never get here. */
    847862    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 */
     876VMMR3DECL(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 */
     903VMMR3DECL(uint32_t) DBGFR3CfgGetBbCount(DBGFCFG hCfg)
     904{
     905    PDBGFCFGINT pThis = hCfg;
     906    AssertPtrReturn(pThis, 0);
     907
     908    return pThis->cBbs;
    848909}
    849910
     
    14231484
    14241485/**
     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 */
     1495VMMR3DECL(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 */
     1521VMMR3DECL(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/**
    14251537 * Returns the type of the last instruction in the basic block.
    14261538 *
     
    14681580
    14691581/**
     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 */
     1588VMMR3DECL(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/**
    14701601 * Store the disassembled instruction as a string in the given output buffer.
    14711602 *
    14721603 * @returns VBox status code.
    1473  * @retval VERR_BUFFER_OVERFLOW if the size of the output buffer can't hold the complete string.
    14741604 * @param   hCfgBb              The basic block handle.
    14751605 * @param   idxInstr            The instruction to query.
    14761606 * @param   pAddrInstr          Where to store the guest instruction address on success, optional.
    14771607 * @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.
    14801609 */
    14811610VMMR3DECL(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{
    14851613    PDBGFCFGBBINT pCfgBb = hCfgBb;
    14861614    AssertPtrReturn(pCfgBb, VERR_INVALID_POINTER);
    14871615    AssertReturn(idxInstr < pCfgBb->cInstr, VERR_INVALID_PARAMETER);
    1488     AssertReturn(   (VALID_PTR(pszOutput) && cbOutput > 0)
    1489                  || (!pszOutput && !cbOutput), VERR_INVALID_PARAMETER);
    14901616
    14911617    if (pAddrInstr)
     
    14931619    if (pcbInstr)
    14941620        *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;
    14991625}
    15001626
     
    15051631 * @returns VBox status code.
    15061632 * @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 */
     1638VMMR3DECL(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;
    15141662}
    15151663
     
    15201668 * @returns Number of other basic blocks referencing this one.
    15211669 * @param   hCfgBb              The basic block handle.
     1670 *
     1671 * @note If the given basic block references itself (loop, etc.) this will be counted as well.
    15221672 */
    15231673VMMR3DECL(uint32_t) DBGFR3CfgBbGetRefBbCount(DBGFCFGBB hCfgBb)
    15241674{
    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;
    15271700}
    15281701
     
    15321705 *
    15331706 * @returns VBox status code.
     1707 * @retval  VERR_BUFFER_OVERFLOW if the array can't hold all the basic blocks.
    15341708 * @param   hCfgBb              The basic block handle.
    15351709 * @param   paCfgBbRef          Pointer to the array containing the referencing basic block handles on success.
     
    15421716}
    15431717
     1718
     1719/**
     1720 * @callback_method_impl{FNRTSORTCMP}
     1721 */
     1722static 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 */
     1758VMMR3DECL(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 */
     1801VMMR3DECL(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 */
     1825VMMR3DECL(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 */
     1847VMMR3DECL(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  
    134134    DBGFR3CfgRelease
    135135    DBGFR3CfgQueryStartBb
     136    DBGFR3CfgQueryBbByAddress
     137    DBGFR3CfgGetBbCount
    136138    DBGFR3CfgDump
    137139    DBGFR3CfgBbRetain
     
    139141    DBGFR3CfgBbGetStartAddress
    140142    DBGFR3CfgBbGetEndAddress
     143    DBGFR3CfgBbGetBranchAddress
     144    DBGFR3CfgBbGetFollowingAddress
    141145    DBGFR3CfgBbGetType
    142146    DBGFR3CfgBbGetInstrCount
    143147    DBGFR3CfgBbGetFlags
     148    DBGFR3CfgBbQueryError
    144149    DBGFR3CfgBbQueryInstr
    145150    DBGFR3CfgBbQuerySuccessors
    146151    DBGFR3CfgBbGetRefBbCount
    147152    DBGFR3CfgBbGetRefBb
     153    DBGFR3CfgItCreate
     154    DBGFR3CfgItDestroy
     155    DBGFR3CfgItNext
     156    DBGFR3CfgItReset
    148157    DBGFR3PlugInLoad
    149158    DBGFR3PlugInUnload
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