VirtualBox

Changeset 102092 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Nov 14, 2023 11:53:15 PM (16 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
160209
Message:

VMM/DBGF,DBGC,Main: Added DBGFR3RegNmQueryEx and fixed some issues with DBGFR3RegNmQueryAll that lead to assertions in Main and empty entries in VBoxManage output. Extended the 'r' and 'rg' debugger commands to make use of the two APIs, the first by appending '.' to a register (e.g. r @cr0.) and the latter by using 'all' as the register name.

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

Legend:

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

    r99070 r102092  
    386386    else
    387387        RTStrPrintf(pRegSet->szPrefix, cchPrefix + 4 + 1, "%s%u", pszPrefix, iInstance);
    388 
    389388
    390389    /*
     
    478477            if (enmType == DBGFREGSETTYPE_CPU)
    479478            {
    480                 if (pRegSet->cDescs > DBGFREG_ALL_COUNT)
    481                     pUVM->dbgf.s.cRegs -= pRegSet->cDescs - DBGFREG_ALL_COUNT;
    482479                if (!strcmp(pszPrefix, "cpu"))
     480                {
     481                    if (!pUVM->dbgf.s.cPerCpuRegs)
     482                        pUVM->dbgf.s.cPerCpuRegs = pRegSet->cDescs;
     483                    else
     484                        AssertLogRelMsgStmt(pUVM->dbgf.s.cPerCpuRegs == pRegSet->cDescs,
     485                                            ("%d vs %d\n", pUVM->dbgf.s.cPerCpuRegs, pRegSet->cDescs),
     486                                            pUVM->dbgf.s.cPerCpuRegs = RT_MAX(pRegSet->cDescs, pUVM->dbgf.s.cPerCpuRegs));
    483487                    pUVM->aCpus[iInstance].dbgf.s.pGuestRegSet = pRegSet;
     488                }
    484489                else
     490                {
     491                    Assert(!strcmp(pszPrefix, "hypercpu"));
     492                    if (!pUVM->dbgf.s.cPerCpuHyperRegs)
     493                        pUVM->dbgf.s.cPerCpuHyperRegs = pRegSet->cDescs;
     494                    else
     495                        AssertLogRelMsgStmt(pUVM->dbgf.s.cPerCpuHyperRegs == pRegSet->cDescs,
     496                                            ("%d vs %d\n", pUVM->dbgf.s.cPerCpuHyperRegs, pRegSet->cDescs),
     497                                            pUVM->dbgf.s.cPerCpuHyperRegs = RT_MAX(pRegSet->cDescs, pUVM->dbgf.s.cPerCpuHyperRegs));
    485498                    pUVM->aCpus[iInstance].dbgf.s.pHyperRegSet = pRegSet;
     499                }
    486500            }
    487501
     
    533547    }
    534548
    535     return dbgfR3RegRegisterCommon(pUVM, paRegisters, DBGFREGSETTYPE_CPU, pVCpu,
    536                                   fGuestRegs ? "cpu" : "hypercpu", pVCpu->idCpu);
     549    AssertReturn(fGuestRegs, VERR_RAW_MODE_NOT_SUPPORTED);
     550    return dbgfR3RegRegisterCommon(pUVM, paRegisters, DBGFREGSETTYPE_CPU, pVCpu, fGuestRegs ? "cpu" : "hypercpu", pVCpu->idCpu);
    537551}
    538552
     
    18441858
    18451859
     1860/**
     1861 * Gets the number of bits in value of type @a enmValType.
     1862 */
     1863static unsigned dbgfR3RegGetBitsForValType(DBGFREGVALTYPE enmValType)
     1864{
     1865    switch (enmValType)
     1866    {
     1867        case DBGFREGVALTYPE_U8:     return 8;
     1868        case DBGFREGVALTYPE_U16:    return 16;
     1869        case DBGFREGVALTYPE_U32:    return 32;
     1870        case DBGFREGVALTYPE_U64:    return 64;
     1871        case DBGFREGVALTYPE_U128:   return 128;
     1872        case DBGFREGVALTYPE_U256:   return 256;
     1873        case DBGFREGVALTYPE_U512:   return 512;
     1874        case DBGFREGVALTYPE_R80:    return 80;
     1875        case DBGFREGVALTYPE_DTR:    return 80;
     1876        /* no default, want gcc warnings */
     1877        case DBGFREGVALTYPE_32BIT_HACK:
     1878        case DBGFREGVALTYPE_END:
     1879        case DBGFREGVALTYPE_INVALID:
     1880            break;
     1881    }
     1882    return 512;
     1883}
     1884
     1885
     1886/**
     1887 * On CPU worker for the extended register queries, used by DBGFR3RegNmQueryEx.
     1888 *
     1889 * @returns VBox status code.
     1890 *
     1891 * @param   pUVM                The user mode VM handle.
     1892 * @param   pLookupRec          The register lookup record.
     1893 * @param   fFlags              DBGFR3REG_QUERY_EX_F_XXX
     1894 * @param   paRegs              Where to return the register values.
     1895 * @param   cRegs               The number of register values to return.
     1896 *                              The caller has checked that this is sufficient
     1897 *                              to store the entire result.
     1898 */
     1899static DECLCALLBACK(int) dbgfR3RegNmQueryExWorkerOnCpu(PUVM pUVM, PCDBGFREGLOOKUP pLookupRec, uint32_t fFlags,
     1900                                                       PDBGFREGENTRYNM paRegs, size_t cRegs)
     1901{
     1902    PCDBGFREGDESC       pDesc = pLookupRec->pDesc;
     1903    PCDBGFREGSET        pSet  = pLookupRec->pSet;
     1904    Assert(!pLookupRec->pSubField);
     1905    NOREF(pUVM);
     1906
     1907    /*
     1908     * The register first.
     1909     */
     1910    AssertReturn(cRegs > 0, VERR_BUFFER_OVERFLOW);
     1911    dbgfR3RegValClear(&paRegs[0].Val);
     1912    paRegs[0].pszName   = pLookupRec->Core.pszString;
     1913    paRegs[0].enmType   = pDesc->enmType;
     1914    paRegs[0].u.uInfo   = 0;
     1915    paRegs[0].u.s.fMain = true;
     1916    int rc = pDesc->pfnGet(pSet->uUserArg.pv, pDesc, &paRegs[0].Val);
     1917    AssertRCReturn(rc, rc);
     1918    DBGFREGVAL const MainValue = paRegs[0].Val;
     1919    uint32_t iReg = 1;
     1920
     1921    /* If it's a alias we looked up we may have to do some casting and
     1922       restricting the number of bits included in the sub-fields. */
     1923    unsigned cMaxBits = sizeof(paRegs[0].Val) * 8;
     1924    if (pLookupRec->pAlias)
     1925    {
     1926        paRegs[0].enmType    = pLookupRec->pAlias->enmType;
     1927        paRegs[0].u.uInfo    = 0;
     1928        paRegs[0].u.s.fAlias = true;
     1929        if (paRegs[0].enmType != pDesc->enmType)
     1930        {
     1931            dbgfR3RegValCast(&paRegs[0].Val, pDesc->enmType, paRegs[0].enmType);
     1932            cMaxBits = dbgfR3RegGetBitsForValType(paRegs[0].enmType);
     1933        }
     1934
     1935        /* Add the main value as the 2nd entry. */
     1936        paRegs[iReg].pszName  = pDesc->pszName;
     1937        paRegs[iReg].enmType  = pDesc->enmType;
     1938        paRegs[iReg].Val      = MainValue;
     1939        paRegs[iReg].u.uInfo   = 0;
     1940        paRegs[iReg].u.s.fMain = true;
     1941        iReg++;
     1942    }
     1943
     1944    /*
     1945     * (Other) Aliases.
     1946     */
     1947    if (   (fFlags & DBGFR3REG_QUERY_EX_F_ALIASES)
     1948        && pDesc->paAliases)
     1949    {
     1950        PCDBGFREGALIAS const paAliases = pDesc->paAliases;
     1951        for (uint32_t i = 0; paAliases[i].pszName != NULL; i++)
     1952            if (&paAliases[i] != pLookupRec->pAlias )
     1953            {
     1954                AssertReturn(iReg < cRegs, VERR_BUFFER_OVERFLOW);
     1955                paRegs[iReg].pszName    = paAliases[i].pszName;
     1956                paRegs[iReg].enmType    = paAliases[i].enmType;
     1957                paRegs[iReg].u.uInfo    = 0;
     1958                paRegs[iReg].u.s.fAlias = true;
     1959                paRegs[iReg].Val        = MainValue;
     1960                dbgfR3RegValCast(&paRegs[iReg].Val, pDesc->enmType, paAliases[i].enmType);
     1961                iReg++;
     1962            }
     1963    }
     1964
     1965    /*
     1966     * Subfields.
     1967     */
     1968    if (   (fFlags & DBGFR3REG_QUERY_EX_F_SUBFIELDS)
     1969        && pDesc->paSubFields)
     1970    {
     1971        PCDBGFREGSUBFIELD const paSubFields = pDesc->paSubFields;
     1972        for (uint32_t i = 0; paSubFields[i].pszName != NULL; i++)
     1973            if (paSubFields[i].iFirstBit < cMaxBits || paSubFields[i].pfnGet)
     1974            {
     1975                AssertReturn(iReg < cRegs, VERR_BUFFER_OVERFLOW);
     1976                int rc2;
     1977                paRegs[iReg].pszName       = paSubFields[i].pszName;
     1978                paRegs[iReg].u.uInfo       = 0;
     1979                paRegs[iReg].u.s.fSubField = true;
     1980                paRegs[iReg].u.s.cBits     = paSubFields[i].cBits + paSubFields[i].cShift;
     1981                if (paSubFields[i].pfnGet)
     1982                {
     1983                    dbgfR3RegValClear(&paRegs[iReg].Val);
     1984                    rc2 = paSubFields[i].pfnGet(pSet->uUserArg.pv, &paSubFields[i], &paRegs[iReg].Val.u128);
     1985                }
     1986                else
     1987                {
     1988                    paRegs[iReg].Val = MainValue;
     1989                    rc2 = dbgfR3RegValCast(&paRegs[iReg].Val, pDesc->enmType, DBGFREGVALTYPE_U128);
     1990                    if (RT_SUCCESS(rc2))
     1991                    {
     1992                        RTUInt128AssignShiftLeft(&paRegs[iReg].Val.u128, -paSubFields[i].iFirstBit);
     1993                        RTUInt128AssignAndNFirstBits(&paRegs[iReg].Val.u128, paSubFields[i].cBits);
     1994                        if (paSubFields[i].cShift)
     1995                            RTUInt128AssignShiftLeft(&paRegs[iReg].Val.u128, paSubFields[i].cShift);
     1996                    }
     1997                }
     1998                if (RT_SUCCESS(rc2))
     1999                {
     2000                    unsigned const cBits = paSubFields[i].cBits + paSubFields[i].cShift;
     2001                    if (cBits <= 8)
     2002                        paRegs[iReg].enmType = DBGFREGVALTYPE_U8;
     2003                    else if (cBits <= 16)
     2004                        paRegs[iReg].enmType = DBGFREGVALTYPE_U16;
     2005                    else if (cBits <= 32)
     2006                        paRegs[iReg].enmType = DBGFREGVALTYPE_U32;
     2007                    else if (cBits <= 64)
     2008                        paRegs[iReg].enmType = DBGFREGVALTYPE_U64;
     2009                    else
     2010                        paRegs[iReg].enmType = DBGFREGVALTYPE_U128;
     2011                    rc2 = dbgfR3RegValCast(&paRegs[iReg].Val, DBGFREGVALTYPE_U128, paRegs[iReg].enmType);
     2012                }
     2013                if (RT_SUCCESS(rc2))
     2014                    iReg++;
     2015                else
     2016                    rc = rc2;
     2017            }
     2018    }
     2019    return rc;
     2020}
     2021
     2022
     2023/**
     2024 * Queries a register with aliases and/or sub-fields.
     2025 *
     2026 * @retval  VINF_SUCCESS
     2027 * @retval  VERR_INVALID_VM_HANDLE
     2028 * @retval  VERR_INVALID_CPU_ID
     2029 * @retval  VERR_BUFFER_OVERFLOW w/ *pcRegs set to the required size.
     2030 *          No other data returned.
     2031 * @retval  VERR_DBGF_REGISTER_NOT_FOUND
     2032 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     2033 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     2034 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
     2035 *
     2036 * @param   pUVM        The user mode VM handle.
     2037 * @param   idDefCpu    The default target CPU ID, VMCPUID_ANY if not
     2038 *                      applicable.  Can be OR'ed with DBGFREG_HYPER_VMCPUID.
     2039 * @param   pszReg      The register that's being queried.  Except for CPU
     2040 *                      registers, this must be on the form "set.reg[.sub]".
     2041 * @param   fFlags      DBGFR3REG_QUERY_EX_F_XXX
     2042 * @param   paRegs
     2043 * @param   pcRegs      On input this is the size of the paRegs buffer.
     2044 *                      On successful return this is set to the number of
     2045 *                      registers returned.  This is set to the required number
     2046 *                      of register entries when VERR_BUFFER_OVERFLOW is
     2047 *                      returned.
     2048 */
     2049VMMR3DECL(int) DBGFR3RegNmQueryEx(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t fFlags,
     2050                                  PDBGFREGENTRYNM paRegs, size_t *pcRegs)
     2051{
     2052    /*
     2053     * Validate input.
     2054     */
     2055    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     2056    VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE);
     2057    AssertReturn((idDefCpu & ~DBGFREG_HYPER_VMCPUID) < pUVM->cCpus || idDefCpu == VMCPUID_ANY, VERR_INVALID_CPU_ID);
     2058    AssertPtrReturn(pszReg, VERR_INVALID_POINTER);
     2059    AssertReturn(!(fFlags & ~DBGFR3REG_QUERY_EX_F_VALID_MASK), VERR_INVALID_FLAGS);
     2060    AssertPtrReturn(pcRegs, VERR_INVALID_POINTER);
     2061    AssertPtrNullReturn(paRegs, VERR_INVALID_POINTER);
     2062
     2063    /*
     2064     * Resolve the register and call the getter on the relevant CPU.
     2065     */
     2066    bool fGuestRegs = true;
     2067    if ((idDefCpu & DBGFREG_HYPER_VMCPUID) && idDefCpu != VMCPUID_ANY)
     2068    {
     2069        fGuestRegs = false;
     2070        idDefCpu &= ~DBGFREG_HYPER_VMCPUID;
     2071    }
     2072    PCDBGFREGLOOKUP pLookupRec = dbgfR3RegResolve(pUVM, idDefCpu, pszReg, fGuestRegs);
     2073    if (pLookupRec)
     2074    {
     2075        /*
     2076         * Determine how many register values we'd be returning.
     2077         */
     2078        uint32_t cRegs = 1; /* we always return the direct hit. */
     2079
     2080        if (   (fFlags & DBGFR3REG_QUERY_EX_F_ALIASES)
     2081            && !pLookupRec->pSubField
     2082            && pLookupRec->pDesc->paAliases)
     2083        {
     2084            PCDBGFREGALIAS const paAliases = pLookupRec->pDesc->paAliases;
     2085            for (uint32_t i = 0; paAliases[i].pszName != NULL; i++)
     2086                cRegs++;
     2087        }
     2088        else if (pLookupRec->pAlias)
     2089            cRegs++;
     2090
     2091        if (   (fFlags & DBGFR3REG_QUERY_EX_F_SUBFIELDS)
     2092            && !pLookupRec->pSubField
     2093            && pLookupRec->pDesc->paSubFields)
     2094        {
     2095            unsigned const cMaxBits = !pLookupRec->pAlias ? sizeof(paRegs[0].Val) * 8
     2096                                    : dbgfR3RegGetBitsForValType(pLookupRec->pAlias->enmType);
     2097            PCDBGFREGSUBFIELD const paSubFields = pLookupRec->pDesc->paSubFields;
     2098            for (uint32_t i = 0; paSubFields[i].pszName != NULL; i++)
     2099                if (paSubFields[i].iFirstBit < cMaxBits || paSubFields[i].pfnGet)
     2100                    cRegs++;
     2101        }
     2102
     2103        /*
     2104         * Did the caller provide sufficient room for the register values, then
     2105         * retrieve the register on the specified CPU.
     2106         */
     2107        if (paRegs && *pcRegs >= cRegs)
     2108        {
     2109            *pcRegs = cRegs;
     2110
     2111            if (pLookupRec->pSet->enmType == DBGFREGSETTYPE_CPU)
     2112                idDefCpu = pLookupRec->pSet->uUserArg.pVCpu->idCpu;
     2113            else if (idDefCpu != VMCPUID_ANY)
     2114                idDefCpu &= ~DBGFREG_HYPER_VMCPUID;
     2115
     2116            /* If we hit a sub-field we'll just use the regular worker to get it. */
     2117            if (!pLookupRec->pSubField)
     2118                return VMR3ReqPriorityCallWaitU(pUVM, idDefCpu, (PFNRT)dbgfR3RegNmQueryExWorkerOnCpu, 5,
     2119                                                pUVM, pLookupRec, fFlags, paRegs, cRegs);
     2120            Assert(cRegs == 1);
     2121            paRegs[0].pszName       = pLookupRec->Core.pszString;
     2122            paRegs[0].enmType       = DBGFREGVALTYPE_END;
     2123            paRegs[0].u.uInfo       = 0;
     2124            paRegs[0].u.s.cBits     = pLookupRec->pSubField->cBits + pLookupRec->pSubField->cShift;
     2125            paRegs[0].u.s.fSubField = true;
     2126            dbgfR3RegValClear(&paRegs[0].Val);
     2127            return VMR3ReqPriorityCallWaitU(pUVM, idDefCpu, (PFNRT)dbgfR3RegNmQueryWorkerOnCpu, 5,
     2128                                            pUVM, pLookupRec, DBGFREGVALTYPE_END, &paRegs[0].Val, &paRegs[0].enmType);
     2129        }
     2130        *pcRegs = cRegs;
     2131        return VERR_BUFFER_OVERFLOW;
     2132    }
     2133    return VERR_DBGF_REGISTER_NOT_FOUND;
     2134
     2135}
     2136
     2137
    18462138/// @todo VMMR3DECL(int) DBGFR3RegNmQueryBatch(PUVM pUVM,VMCPUID idDefCpu, DBGFREGENTRYNM paRegs, size_t cRegs);
    18472139
     
    18812173            paRegs[iReg].pszName = NULL;
    18822174            paRegs[iReg].enmType = DBGFREGVALTYPE_END;
     2175            paRegs[iReg].u.uInfo = 0;
    18832176            dbgfR3RegValClear(&paRegs[iReg].Val);
    18842177            iReg++;
     
    19052198    for (size_t iReg = 0; iReg < cRegsToQuery; iReg++)
    19062199    {
    1907         paRegs[iReg].enmType = pSet->paDescs[iReg].enmType;
    1908         paRegs[iReg].pszName = pSet->paLookupRecs[iReg].Core.pszString;
     2200        paRegs[iReg].enmType   = pSet->paDescs[iReg].enmType;
     2201        paRegs[iReg].pszName   = pSet->paLookupRecs[iReg].Core.pszString;
     2202        paRegs[iReg].u.uInfo   = 0;
     2203        paRegs[iReg].u.s.fMain = true;
    19092204        dbgfR3RegValClear(&paRegs[iReg].Val);
    19102205        int rc2 = pSet->paDescs[iReg].pfnGet(pSet->uUserArg.pv, &pSet->paDescs[iReg], &paRegs[iReg].Val);
     
    19512246     * My guest CPU registers.
    19522247     */
    1953     size_t iCpuReg = pVCpu->idCpu * DBGFREG_ALL_COUNT;
     2248    size_t iCpuReg = pVCpu->idCpu * pUVM->dbgf.s.cPerCpuRegs;
    19542249    if (pUVCpu->dbgf.s.pGuestRegSet)
    19552250    {
    19562251        if (iCpuReg < cRegs)
    1957             dbgfR3RegNmQueryAllInSet(pUVCpu->dbgf.s.pGuestRegSet, DBGFREG_ALL_COUNT, &paRegs[iCpuReg], cRegs - iCpuReg);
     2252            dbgfR3RegNmQueryAllInSet(pUVCpu->dbgf.s.pGuestRegSet, pUVM->dbgf.s.cPerCpuRegs, &paRegs[iCpuReg], cRegs - iCpuReg);
    19582253    }
    19592254    else
    1960         dbgfR3RegNmQueryAllPadEntries(paRegs, cRegs, iCpuReg, DBGFREG_ALL_COUNT);
     2255        dbgfR3RegNmQueryAllPadEntries(paRegs, cRegs, iCpuReg, pUVM->dbgf.s.cPerCpuRegs);
    19612256
    19622257    /*
    19632258     * My hypervisor CPU registers.
    19642259     */
    1965     iCpuReg = pUVM->cCpus * DBGFREG_ALL_COUNT + pUVCpu->idCpu * DBGFREG_ALL_COUNT;
     2260    iCpuReg = pUVM->cCpus * pUVM->dbgf.s.cPerCpuRegs + pUVCpu->idCpu * pUVM->dbgf.s.cPerCpuHyperRegs;
    19662261    if (pUVCpu->dbgf.s.pHyperRegSet)
    19672262    {
    19682263        if (iCpuReg < cRegs)
    1969             dbgfR3RegNmQueryAllInSet(pUVCpu->dbgf.s.pHyperRegSet, DBGFREG_ALL_COUNT, &paRegs[iCpuReg], cRegs - iCpuReg);
     2264            dbgfR3RegNmQueryAllInSet(pUVCpu->dbgf.s.pHyperRegSet, pUVM->dbgf.s.cPerCpuHyperRegs, &paRegs[iCpuReg], cRegs - iCpuReg);
    19702265    }
    19712266    else
    1972         dbgfR3RegNmQueryAllPadEntries(paRegs, cRegs, iCpuReg, DBGFREG_ALL_COUNT);
     2267        dbgfR3RegNmQueryAllPadEntries(paRegs, cRegs, iCpuReg, pUVM->dbgf.s.cPerCpuHyperRegs);
    19732268
    19742269    /*
     
    19772272    if (pUVCpu->idCpu == 0)
    19782273    {
    1979         pArgs->iReg = pUVM->cCpus * DBGFREG_ALL_COUNT * 2;
     2274        pArgs->iReg = pUVM->cCpus * (pUVM->dbgf.s.cPerCpuRegs + pUVM->dbgf.s.cPerCpuHyperRegs);
    19802275        RTStrSpaceEnumerate(&pUVM->dbgf.s.RegSetSpace, dbgfR3RegNmQueryAllEnum, pArgs);
    19812276        dbgfR3RegNmQueryAllPadEntries(paRegs, cRegs, pArgs->iReg, cRegs);
  • trunk/src/VBox/VMM/VMMR3/VMMR3.def

    r100184 r102092  
    145145    DBGFR3RegFormatValue
    146146    DBGFR3RegNmQuery
     147    DBGFR3RegNmQueryEx
    147148    DBGFR3RegNmQueryAll
    148149    DBGFR3RegNmQueryAllCount
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