VirtualBox

Changeset 35586 in vbox for trunk/src


Ignore:
Timestamp:
Jan 17, 2011 2:20:59 PM (14 years ago)
Author:
vboxsync
Message:

DBGFReg.cpp: Added DBGFR3RegFormatValue, DBGFR3RegFormatValueEx, DBGFR3RegNmPrintfV and DBGFR3RegNmPrintf.

Location:
trunk/src/VBox
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/MachineDebuggerImpl.cpp

    r35551 r35586  
    10531053 * @param   a_enmType           The type of the value.
    10541054 */
    1055 static HRESULT formatRegisterValue(Bstr *a_pbstr, PCDBGFREGVAL a_pValue, DBGFREGVALTYPE a_enmType)
    1056 {
    1057     char szHex[128]; /* Must be big because RTStrFormatNumber is unsafe. */
    1058 
    1059     switch (a_enmType)
    1060     {
    1061         case DBGFREGVALTYPE_U8:
    1062             RTStrFormatNumber(szHex, a_pValue->u8,  16,  2+2, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_8BIT);
    1063             *a_pbstr = szHex;
    1064             return S_OK;
    1065 
    1066         case DBGFREGVALTYPE_U16:
    1067             RTStrFormatNumber(szHex, a_pValue->u16, 16,  2+4, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_16BIT);
    1068             *a_pbstr = szHex;
    1069             return S_OK;
    1070 
    1071         case DBGFREGVALTYPE_U32:
    1072             RTStrFormatNumber(szHex, a_pValue->u32, 16,  2+8, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_32BIT);
    1073             *a_pbstr = szHex;
    1074             return S_OK;
    1075 
    1076         case DBGFREGVALTYPE_U64:
    1077             RTStrFormatNumber(szHex, a_pValue->u64, 16, 2+16, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    1078             *a_pbstr = szHex;
    1079             return S_OK;
    1080 
    1081         case DBGFREGVALTYPE_U128:
    1082             RTStrFormatNumber(szHex, a_pValue->au64[1], 16, 2+16, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    1083             RTStrFormatNumber(&szHex[2+16], a_pValue->au64[0], 16, 16, 0, RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    1084             *a_pbstr = szHex;
    1085             return S_OK;
    1086 
    1087         case DBGFREGVALTYPE_R80:
    1088         {
    1089             char *pszHex = szHex;
    1090             if (a_pValue->r80.s.fSign)
    1091                 *pszHex++ = '-';
    1092             else
    1093                 *pszHex++ = '+';
    1094 
    1095             if (a_pValue->r80.s.uExponent == 0)
    1096             {
    1097                 if (   !a_pValue->r80.sj64.u63Fraction
    1098                     && a_pValue->r80.sj64.fInteger)
    1099                     *pszHex++ = '0';
    1100                 /* else: Denormal, handled way below. */
    1101             }
    1102             else if (a_pValue->r80.sj64.uExponent == UINT16_C(0x7fff))
    1103             {
    1104                 /** @todo Figure out Pseudo inf/nan... */
    1105                 if (a_pValue->r80.sj64.fInteger)
    1106                     *pszHex++ = 'P';
    1107                 if (a_pValue->r80.sj64.u63Fraction == 0)
    1108                 {
    1109                     *pszHex++ = 'I';
    1110                     *pszHex++ = 'n';
    1111                     *pszHex++ = 'f';
    1112                 }
    1113                 else
    1114                 {
    1115                     *pszHex++ = 'N';
    1116                     *pszHex++ = 'a';
    1117                     *pszHex++ = 'N';
    1118                 }
    1119             }
    1120             if (pszHex != &szHex[1])
    1121                 *pszHex = '\0';
    1122             else
    1123             {
    1124                 *pszHex++ = a_pValue->r80.sj64.fInteger ? '1' : '0';
    1125                 *pszHex++ = 'm';
    1126                 pszHex += RTStrFormatNumber(pszHex, a_pValue->r80.sj64.u63Fraction, 16, 2+16, 0,
    1127                                             RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    1128 
    1129                 *pszHex++ = 'e';
    1130                 pszHex += RTStrFormatNumber(pszHex, (int32_t)a_pValue->r80.sj64.uExponent - 16383, 10, 0, 0,
    1131                                             RTSTR_F_ZEROPAD | RTSTR_F_32BIT | RTSTR_F_VALSIGNED);
    1132             }
    1133             *a_pbstr = szHex;
    1134             return S_OK;
    1135         }
    1136 
    1137         case DBGFREGVALTYPE_DTR:
    1138             RTStrFormatNumber(szHex, a_pValue->dtr.u64Base, 16, 2+16, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    1139             szHex[2+16] = ':';
    1140             RTStrFormatNumber(&szHex[2+16+1], a_pValue->dtr.u32Limit, 16, 4, 0, RTSTR_F_ZEROPAD | RTSTR_F_32BIT);
    1141             *a_pbstr = szHex;
    1142             return S_OK;
    1143 
    1144         case DBGFREGVALTYPE_INVALID:
    1145         case DBGFREGVALTYPE_END:
    1146         case DBGFREGVALTYPE_32BIT_HACK:
    1147             break;
    1148         /* no default */
    1149     }
    1150 
    1151     return E_UNEXPECTED;
     1055DECLINLINE(HRESULT) formatRegisterValue(Bstr *a_pbstr, PCDBGFREGVAL a_pValue, DBGFREGVALTYPE a_enmType)
     1056{
     1057    char szHex[160];
     1058    ssize_t cch = DBGFR3RegFormatValue(szHex, sizeof(szHex), a_pValue, a_enmType, true /*fSpecial*/);
     1059    if (RT_UNLIKELY(cch <= 0))
     1060        return E_UNEXPECTED;
     1061    *a_pbstr = szHex;
     1062    return S_OK;
    11521063}
    11531064
  • trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp

    r35550 r35586  
    150150/** Pointer to a const register lookup record. */
    151151typedef DBGFREGLOOKUP const *PCDBGFREGLOOKUP;
     152
     153
     154/**
     155 * Argument packet from DBGFR3RegNmQueryAll to dbgfR3RegNmQueryAllWorker.
     156 */
     157typedef struct DBGFR3REGNMQUERYALLARGS
     158{
     159    /** The output register array. */
     160    PDBGFREGENTRYNM paRegs;
     161    /** The number of entries in the output array. */
     162    size_t          cRegs;
     163    /** The current register number when enumerating the string space. */
     164    size_t          iReg;
     165} DBGFR3REGNMQUERYALLARGS;
     166/** Pointer to a dbgfR3RegNmQueryAllWorker argument packet. */
     167typedef DBGFR3REGNMQUERYALLARGS *PDBGFR3REGNMQUERYALLARGS;
     168
     169
     170/**
     171 * Argument packet passed by DBGFR3RegNmPrintfV to dbgfR3RegNmPrintfCbOutput
     172 * and dbgfR3RegNmPrintfCbFormat.
     173 */
     174typedef struct DBGFR3REGNMPRINTFARGS
     175{
     176    /** The VM handle. */
     177    PVM         pVM;
     178    /** The target CPU. */
     179    VMCPUID     idCpu;
     180    /** The output buffer. */
     181    char       *pszBuf;
     182    /** The format string. */
     183    const char *pszFormat;
     184    /** The va list with format arguments. */
     185    va_list     va;
     186
     187    /** The current buffer offset. */
     188    size_t      offBuf;
     189    /** The amount of buffer space left, not counting the terminator char. */
     190    size_t      cchLeftBuf;
     191    /** The status code of the whole operation.  First error is return,
     192     * subsequent ones are suppressed. */
     193    int         rc;
     194} DBGFR3REGNMPRINTFARGS;
     195/** Pointer to a DBGFR3RegNmPrintfV argument packet. */
     196typedef DBGFR3REGNMPRINTFARGS *PDBGFR3REGNMPRINTFARGS;
     197
    152198
    153199
     
    11731219
    11741220/**
    1175  * On CPU worker for the register queries, used by dbgfR3RegNmQueryWorker.
     1221 * On CPU worker for the register queries, used by dbgfR3RegNmQueryWorker and
     1222 * dbgfR3RegNmPrintfCbFormat.
    11761223 *
    11771224 * @returns VBox status code.
     
    15911638}
    15921639
    1593 /**
    1594  * Argument packet from DBGFR3RegNmQueryAll to dbgfR3RegNmQueryAllWorker.
    1595  */
    1596 typedef struct DBGFR3REGNMQUERYALLARGS
    1597 {
    1598     /** The output register array. */
    1599     PDBGFREGENTRYNM paRegs;
    1600     /** The number of entries in the output array. */
    1601     size_t          cRegs;
    1602     /** The current register number when enumerating the string space. */
    1603     size_t          iReg;
    1604 } DBGFR3REGNMQUERYALLARGS;
    1605 /** Pointer to a dbgfR3RegNmQueryAllWorker argument packet. */
    1606 typedef DBGFR3REGNMQUERYALLARGS *PDBGFR3REGNMQUERYALLARGS;
    1607 
    16081640
    16091641/**
     
    16911723    size_t const                cRegs  = pArgs->cRegs;
    16921724
     1725    DBGF_REG_DB_LOCK_READ(pVM);
     1726
    16931727    /*
    16941728     * My CPU registers.
     
    17131747    }
    17141748
     1749    DBGF_REG_DB_UNLOCK_READ(pVM);
    17151750    return VINF_SUCCESS; /* Ignore errors. */
    17161751}
     
    17431778
    17441779
    1745 /// @todo VMMR3DECL(int) DBGFR3RegNmPrintf(PVM pVM, VMCPUID idDefCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
    1746 /// @todo VMMR3DECL(int) DBGFR3RegNmPrintfV(PVM pVM, VMCPUID idDefCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
    1747 
     1780/**
     1781 * Internal worker for DBGFR3RegFormatValue, cbTmp is sufficent.
     1782 *
     1783 * @copydoc DBGFR3RegFormatValue
     1784 */
     1785DECLINLINE(ssize_t) dbgfR3RegFormatValueInt(char *pszTmp, size_t cbTmp, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType,
     1786                                            unsigned uBase, signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
     1787{
     1788    switch (enmType)
     1789    {
     1790        case DBGFREGVALTYPE_U8:
     1791            return RTStrFormatU8(pszTmp, cbTmp, pValue->u8, uBase, cchWidth, cchPrecision, fFlags);
     1792        case DBGFREGVALTYPE_U16:
     1793            return RTStrFormatU16(pszTmp, cbTmp, pValue->u16, uBase, cchWidth, cchPrecision, fFlags);
     1794        case DBGFREGVALTYPE_U32:
     1795            return RTStrFormatU32(pszTmp, cbTmp, pValue->u32, uBase, cchWidth, cchPrecision, fFlags);
     1796        case DBGFREGVALTYPE_U64:
     1797            return RTStrFormatU64(pszTmp, cbTmp, pValue->u64, uBase, cchWidth, cchPrecision, fFlags);
     1798        case DBGFREGVALTYPE_U128:
     1799            return RTStrFormatU128(pszTmp, cbTmp, &pValue->u128, uBase, cchWidth, cchPrecision, fFlags);
     1800        case DBGFREGVALTYPE_R80:
     1801            return RTStrFormatR80u2(pszTmp, cbTmp, &pValue->r80, cchWidth, cchPrecision, fFlags);
     1802        case DBGFREGVALTYPE_DTR:
     1803        {
     1804            ssize_t cch = RTStrFormatU64(pszTmp, cbTmp, pValue->dtr.u64Base,
     1805                                         16, 2+16, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD);
     1806            AssertReturn(cch > 0, VERR_INTERNAL_ERROR_4);
     1807            pszTmp[cch++] = ':';
     1808            cch += RTStrFormatU64(&pszTmp[cch], cbTmp - cch, pValue->dtr.u32Limit,
     1809                                  16, 4, 0, RTSTR_F_ZEROPAD | RTSTR_F_32BIT);
     1810            return cch;
     1811        }
     1812
     1813        case DBGFREGVALTYPE_32BIT_HACK:
     1814        case DBGFREGVALTYPE_END:
     1815        case DBGFREGVALTYPE_INVALID:
     1816            break;
     1817        /* no default, want gcc warnings */
     1818    }
     1819
     1820    RTStrPrintf(pszTmp, cbTmp, "!enmType=%d!", enmType);
     1821    return VERR_INTERNAL_ERROR_5;
     1822}
     1823
     1824
     1825
     1826/**
     1827 * Format a register value, extended version.
     1828 *
     1829 * @returns The number of bytes returned, VERR_BUFFER_OVERFLOW on failure.
     1830 * @param   pszBuf          The output buffer.
     1831 * @param   cbBuf           The size of the output buffer.
     1832 * @param   pValue          The value to format.
     1833 * @param   enmType         The value type.
     1834 * @param   uBase           The base (ignored if not applicable).
     1835 * @param   cchWidth        The width if RTSTR_F_WIDTH is set, otherwise
     1836 *                          ignored.
     1837 * @param   cchPrecision    The width if RTSTR_F_PRECISION is set, otherwise
     1838 *                          ignored.
     1839 * @param   fFlags          String formatting flags, RTSTR_F_XXX.
     1840 */
     1841VMMDECL(ssize_t) DBGFR3RegFormatValueEx(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType,
     1842                                        unsigned uBase, signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
     1843{
     1844    /*
     1845     * Format to temporary buffer using worker shared with dbgfR3RegNmPrintfCbFormat.
     1846     */
     1847    char szTmp[160];
     1848    ssize_t cchOutput = dbgfR3RegFormatValueInt(szTmp, sizeof(szTmp), pValue, enmType, uBase, cchWidth, cchPrecision, fFlags);
     1849    if (cchOutput > 0)
     1850    {
     1851        if ((size_t)cchOutput < cbBuf)
     1852            memcpy(pszBuf, szTmp, cchOutput + 1);
     1853        else
     1854        {
     1855            if (cbBuf)
     1856            {
     1857                memcpy(pszBuf, szTmp, cbBuf - 1);
     1858                pszBuf[cbBuf - 1] = '\0';
     1859            }
     1860            cchOutput = VERR_BUFFER_OVERFLOW;
     1861        }
     1862    }
     1863    return cchOutput;
     1864}
     1865
     1866
     1867/**
     1868 * Format a register value as hexadecimal and with default width according to
     1869 * the type.
     1870 *
     1871 * @returns The number of bytes returned, VERR_BUFFER_OVERFLOW on failure.
     1872 * @param   pszBuf          The output buffer.
     1873 * @param   cbBuf           The size of the output buffer.
     1874 * @param   pValue          The value to format.
     1875 * @param   enmType         The value type.
     1876 * @param   fSpecial        Same as RTSTR_F_SPECIAL.
     1877 */
     1878VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial)
     1879{
     1880    int cchWidth = 0;
     1881    switch (enmType)
     1882    {
     1883        case DBGFREGVALTYPE_U8:     cchWidth = 2  + fSpecial*2; break;
     1884        case DBGFREGVALTYPE_U16:    cchWidth = 4  + fSpecial*2; break;
     1885        case DBGFREGVALTYPE_U32:    cchWidth = 8  + fSpecial*2; break;
     1886        case DBGFREGVALTYPE_U64:    cchWidth = 16 + fSpecial*2; break;
     1887        case DBGFREGVALTYPE_U128:   cchWidth = 32 + fSpecial*2; break;
     1888        case DBGFREGVALTYPE_R80:    cchWidth = 0; break;
     1889        case DBGFREGVALTYPE_DTR:    cchWidth = 16+1+4 + fSpecial*2; break;
     1890
     1891        case DBGFREGVALTYPE_32BIT_HACK:
     1892        case DBGFREGVALTYPE_END:
     1893        case DBGFREGVALTYPE_INVALID:
     1894            break;
     1895        /* no default, want gcc warnings */
     1896    }
     1897    uint32_t fFlags = RTSTR_F_ZEROPAD;
     1898    if (fSpecial)
     1899        fFlags |= RTSTR_F_SPECIAL;
     1900    if (cchWidth != 0)
     1901        fFlags |= RTSTR_F_WIDTH;
     1902    return DBGFR3RegFormatValueEx(pszBuf, cbBuf, pValue, enmType, 16, cchWidth, 0, fFlags);
     1903}
     1904
     1905
     1906/**
     1907 * @callback_method_impl{FNSTRFORMAT}
     1908 */
     1909static DECLCALLBACK(size_t)
     1910dbgfR3RegNmPrintfCbFormat(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
     1911                          const char **ppszFormat, va_list *pArgs, int cchWidth,
     1912                          int cchPrecision, unsigned fFlags, char chArgSize)
     1913{
     1914    PDBGFR3REGNMPRINTFARGS pThis = (PDBGFR3REGNMPRINTFARGS)pvArg;
     1915
     1916    /*
     1917     * Parse out the register bits of the register format type.  Noisily reject
     1918     * unknown format types.
     1919     */
     1920    const char *pszFormat = *ppszFormat;
     1921    if (    pszFormat[0] != 'V'
     1922        ||  pszFormat[1] != 'R')
     1923    {
     1924        AssertMsgFailed(("'%s'\n", pszFormat));
     1925        return 0;
     1926    }
     1927    unsigned uBase;
     1928    if (pszFormat[2] == '{')
     1929        uBase = 16;
     1930    else if (   pszFormat[2] == 'U'
     1931             && pszFormat[3] == '{')
     1932        uBase = 10;
     1933    else if (   pszFormat[2] == 'O'
     1934             && pszFormat[3] == '{')
     1935        uBase = 8;
     1936    else if (   pszFormat[2] == 'B'
     1937             && pszFormat[3] == '{')
     1938        uBase = 2;
     1939    else
     1940    {
     1941        AssertMsgFailed(("'%s'\n", pszFormat));
     1942        return 0;
     1943    }
     1944
     1945    const char * const  pachReg = &pszFormat[3];
     1946    const char         *pszEnd = strchr(&pachReg[3], '}');
     1947    AssertMsgReturn(pszEnd, ("Missing closing curly bracket: '%s'\n", pszFormat), 0);
     1948
     1949    size_t const cchReg = pachReg - pszEnd;
     1950
     1951    /*
     1952     * Look up the register - same as dbgfR3RegResolve, except for locking and
     1953     * input string termination.
     1954     */
     1955    char szTmp[DBGF_REG_MAX_NAME * 4 + 64];
     1956
     1957    /* Try looking up the name without any case folding or cpu prefixing. */
     1958    PCDBGFREGLOOKUP pLookupRec = (PCDBGFREGLOOKUP)RTStrSpaceGetN(&pThis->pVM->dbgf.s.RegSpace, pachReg, cchReg);
     1959    if (!pLookupRec)
     1960    {
     1961        /* Lower case it and try again. */
     1962        ssize_t cchFolded = dbgfR3RegCopyToLower(pachReg, cchReg, szTmp, sizeof(szTmp) - DBGF_REG_MAX_NAME);
     1963        if (cchFolded > 0)
     1964            pLookupRec = (PCDBGFREGLOOKUP)RTStrSpaceGet(&pThis->pVM->dbgf.s.RegSpace, szTmp);
     1965        if (   !pLookupRec
     1966            && cchFolded >= 0
     1967            && pThis->idCpu != VMCPUID_ANY)
     1968        {
     1969            /* Prefix it with the specified CPU set. */
     1970            size_t cchCpuSet = RTStrPrintf(szTmp, sizeof(szTmp), "cpu%u.", pThis->idCpu);
     1971            dbgfR3RegCopyToLower(pachReg, cchReg, &szTmp[cchCpuSet], sizeof(szTmp) - cchCpuSet);
     1972            pLookupRec = (PCDBGFREGLOOKUP)RTStrSpaceGet(&pThis->pVM->dbgf.s.RegSpace, szTmp);
     1973        }
     1974    }
     1975    AssertMsgReturn(pLookupRec, ("'%s'\n", pszFormat), 0);
     1976    AssertMsgReturn(   pLookupRec->pSet->enmType != DBGFREGSETTYPE_CPU
     1977                    || pLookupRec->pSet->uUserArg.pVCpu->idCpu == pThis->idCpu,
     1978                    ("'%s' idCpu=%u, pSet/cpu=%u\n", pszFormat, pThis->idCpu, pLookupRec->pSet->uUserArg.pVCpu->idCpu),
     1979                    0);
     1980
     1981    /* Commit the format type parsing so we can return more freely below. */
     1982    *ppszFormat = pszFormat;
     1983
     1984    /*
     1985     * Get the register value.
     1986     */
     1987    DBGFREGVAL      Value;
     1988    DBGFREGVALTYPE  enmType;
     1989    int rc = dbgfR3RegNmQueryWorkerOnCpu(pThis->pVM, pLookupRec, DBGFREGVALTYPE_END, &Value, &enmType);
     1990    if (RT_FAILURE(rc))
     1991    {
     1992        PCRTSTATUSMSG pErr = RTErrGet(rc);
     1993        if (pErr)
     1994            return pfnOutput(pvArgOutput, pErr->pszDefine, strlen(pErr->pszDefine));
     1995        return pfnOutput(pvArgOutput, szTmp, RTStrPrintf(szTmp, sizeof(szTmp), "rc=%d", rc));
     1996    }
     1997
     1998    /*
     1999     * Format the value.
     2000     */
     2001    ssize_t cchOutput = dbgfR3RegFormatValueInt(szTmp, sizeof(szTmp), &Value, enmType, uBase, cchWidth, cchPrecision, fFlags);
     2002    if (RT_UNLIKELY(cchOutput <= 0))
     2003    {
     2004        AssertFailed();
     2005        return pfnOutput(pvArgOutput, "internal-error", sizeof("internal-error") - 1);
     2006    }
     2007    return pfnOutput(pvArgOutput, szTmp, cchOutput);
     2008}
     2009
     2010
     2011/**
     2012 * @callback_method_impl{FNRTSTROUTPUT}
     2013 */
     2014static DECLCALLBACK(size_t)
     2015dbgfR3RegNmPrintfCbOutput(void *pvArg, const char *pachChars, size_t cbChars)
     2016{
     2017    PDBGFR3REGNMPRINTFARGS  pArgs    = (PDBGFR3REGNMPRINTFARGS)pvArg;
     2018    size_t                  cbToCopy = cbChars;
     2019    if (cbToCopy >= pArgs->cchLeftBuf)
     2020    {
     2021        if (RT_SUCCESS(pArgs->rc))
     2022            pArgs->rc = VERR_BUFFER_OVERFLOW;
     2023        cbToCopy = pArgs->cchLeftBuf;
     2024    }
     2025    if (cbToCopy > 0)
     2026    {
     2027        memcpy(&pArgs->pszBuf[pArgs->offBuf], pachChars, cbChars);
     2028        pArgs->offBuf     += cbChars;
     2029        pArgs->cchLeftBuf -= cbChars;
     2030        pArgs->pszBuf[pArgs->offBuf] = '\0';
     2031    }
     2032    return cbToCopy;
     2033}
     2034
     2035
     2036/**
     2037 * On CPU worker for the register formatting, used by DBGFR3RegNmPrintfV.
     2038 *
     2039 * @returns VBox status code.
     2040 *
     2041 * @param   pArgs               The argument package and state.
     2042 */
     2043static DECLCALLBACK(int) dbgfR3RegNmPrintfWorkerOnCpu(PDBGFR3REGNMPRINTFARGS pArgs)
     2044{
     2045    DBGF_REG_DB_LOCK_READ(pArgs->pVM);
     2046    RTStrFormatV(dbgfR3RegNmPrintfCbOutput, pArgs, dbgfR3RegNmPrintfCbFormat, pArgs, pArgs->pszFormat, pArgs->va);
     2047    DBGF_REG_DB_UNLOCK_READ(pArgs->pVM);
     2048    return pArgs->rc;
     2049}
     2050
     2051
     2052/**
     2053 * Format a registers.
     2054 *
     2055 * This is restricted to registers from one CPU, that specified by @a idCpu.
     2056 *
     2057 * @returns VBox status code.
     2058 * @param   pVM                 The VM handle.
     2059 * @param   idCpu               The CPU ID of any CPU registers that may be
     2060 *                              printed, pass VMCPUID_ANY if not applicable.
     2061 * @param   pszBuf              The output buffer.
     2062 * @param   cbBuf               The size of the output buffer.
     2063 * @param   pszFormat           The format string.  Register names are given by
     2064 *                              %VR{name}, they take no arguments.
     2065 * @param   va                  Other format arguments.
     2066 */
     2067VMMR3DECL(int) DBGFR3RegNmPrintfV(PVM pVM, VMCPUID idCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, va_list va)
     2068{
     2069    AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
     2070    AssertReturn(cbBuf > 0, VERR_BUFFER_OVERFLOW);
     2071    *pszBuf = '\0';
     2072
     2073    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     2074    AssertReturn(idCpu < pVM->cCpus || idCpu == VMCPUID_ANY, VERR_INVALID_CPU_ID);
     2075    AssertPtrReturn(pszFormat, VERR_INVALID_POINTER);
     2076
     2077    /*
     2078     * Set up an argument package and execute the formatting on the
     2079     * specified CPU.
     2080     */
     2081    DBGFR3REGNMPRINTFARGS Args;
     2082    Args.pVM        = pVM;
     2083    Args.idCpu      = idCpu;
     2084    Args.pszBuf     = pszBuf;
     2085    Args.pszFormat  = pszFormat;
     2086    va_copy(Args.va, va);
     2087    Args.offBuf     = 0;
     2088    Args.cchLeftBuf = cbBuf - 1;
     2089    Args.rc         = VINF_SUCCESS;
     2090    int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegNmPrintfWorkerOnCpu, 1, &Args);
     2091    va_end(Args.va);
     2092    return rc;
     2093}
     2094
     2095
     2096/**
     2097 * Format a registers.
     2098 *
     2099 * This is restricted to registers from one CPU, that specified by @a idCpu.
     2100 *
     2101 * @returns VBox status code.
     2102 * @param   pVM                 The VM handle.
     2103 * @param   idCpu               The CPU ID of any CPU registers that may be
     2104 *                              printed, pass VMCPUID_ANY if not applicable.
     2105 * @param   pszBuf              The output buffer.
     2106 * @param   cbBuf               The size of the output buffer.
     2107 * @param   pszFormat           The format string.  Register names are given by
     2108 *                              %VR{name}, %VRU{name}, %VRO{name} and
     2109 *                              %VRB{name}, which are hexadecimal, (unsigned)
     2110 *                              decimal, octal and binary representation.  None
     2111 *                              of these types takes any arguments.
     2112 * @param   ...                 Other format arguments.
     2113 */
     2114VMMR3DECL(int) DBGFR3RegNmPrintf(PVM pVM, VMCPUID idCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, ...)
     2115{
     2116    va_list va;
     2117    va_start(va, pszFormat);
     2118    int rc = DBGFR3RegNmPrintfV(pVM, idCpu, pszBuf, cbBuf, pszFormat, va);
     2119    va_end(va);
     2120    return rc;
     2121}
     2122
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