- Timestamp:
- Jan 17, 2011 2:20:59 PM (14 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/MachineDebuggerImpl.cpp
r35551 r35586 1053 1053 * @param a_enmType The type of the value. 1054 1054 */ 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; 1055 DECLINLINE(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; 1152 1063 } 1153 1064 -
trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp
r35550 r35586 150 150 /** Pointer to a const register lookup record. */ 151 151 typedef DBGFREGLOOKUP const *PCDBGFREGLOOKUP; 152 153 154 /** 155 * Argument packet from DBGFR3RegNmQueryAll to dbgfR3RegNmQueryAllWorker. 156 */ 157 typedef 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. */ 167 typedef DBGFR3REGNMQUERYALLARGS *PDBGFR3REGNMQUERYALLARGS; 168 169 170 /** 171 * Argument packet passed by DBGFR3RegNmPrintfV to dbgfR3RegNmPrintfCbOutput 172 * and dbgfR3RegNmPrintfCbFormat. 173 */ 174 typedef 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. */ 196 typedef DBGFR3REGNMPRINTFARGS *PDBGFR3REGNMPRINTFARGS; 197 152 198 153 199 … … 1173 1219 1174 1220 /** 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. 1176 1223 * 1177 1224 * @returns VBox status code. … … 1591 1638 } 1592 1639 1593 /**1594 * Argument packet from DBGFR3RegNmQueryAll to dbgfR3RegNmQueryAllWorker.1595 */1596 typedef struct DBGFR3REGNMQUERYALLARGS1597 {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 1608 1640 1609 1641 /** … … 1691 1723 size_t const cRegs = pArgs->cRegs; 1692 1724 1725 DBGF_REG_DB_LOCK_READ(pVM); 1726 1693 1727 /* 1694 1728 * My CPU registers. … … 1713 1747 } 1714 1748 1749 DBGF_REG_DB_UNLOCK_READ(pVM); 1715 1750 return VINF_SUCCESS; /* Ignore errors. */ 1716 1751 } … … 1743 1778 1744 1779 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 */ 1785 DECLINLINE(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 */ 1841 VMMDECL(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 */ 1878 VMMDECL(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 */ 1909 static DECLCALLBACK(size_t) 1910 dbgfR3RegNmPrintfCbFormat(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 */ 2014 static DECLCALLBACK(size_t) 2015 dbgfR3RegNmPrintfCbOutput(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 */ 2043 static 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 */ 2067 VMMR3DECL(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 */ 2114 VMMR3DECL(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.