VirtualBox

Changeset 102092 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 14, 2023 11:53:15 PM (18 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
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGCEmulateCodeView.cpp

    r99739 r102092  
    499499    { "pc",         0,        0,        &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace),  0,       dbgcCmdStepTrace,   "[count] [cmds]",       "Step to the next call instruction." },
    500500    { "pt",         0,        0,        &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace),  0,       dbgcCmdStepTrace,   "[count] [cmds]",       "Step to the next return instruction." },
    501     { "r",          0,        3,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdReg,         "[reg [[=] newval]]",   "Show or set register(s) - active reg set." },
    502     { "rg",         0,        3,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdRegGuest,    "[reg [[=] newval]]",   "Show or set register(s) - guest reg set." },
     501    { "r",          0,        3,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdReg,         "[reg [[=] newval]]",   "Show or set register(s) - active reg set. Special 'all' register for showing all. Append a dot '.' to display sub-fields and aliases." },
     502    { "rg",         0,        3,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdRegGuest,    "[reg [[=] newval]]",   "Show or set register(s) - guest reg set. Special 'all' register for showing all. Append a dot '.' to display sub-fields and aliases." },
    503503    { "rg32",       0,        0,        NULL,               0,                              0,       dbgcCmdRegGuest,    "",                     "Show 32-bit guest registers." },
    504504    { "rg64",       0,        0,        NULL,               0,                              0,       dbgcCmdRegGuest,    "",                     "Show 64-bit guest registers." },
     
    24312431{
    24322432    PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
     2433    int   rc;
    24332434    DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 1 || cArgs == 2 || cArgs == 3);
    24342435    DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0,    paArgs[0].enmType == DBGCVAR_TYPE_STRING
     
    24382439     * Parse the register name and kind.
    24392440     */
    2440     const char *pszReg = paArgs[0].u.pszString;
     2441    bool const  fAllRegs = strcmp(paArgs[0].u.pszString, "all") == 0;
     2442    const char *pszReg   = paArgs[0].u.pszString;
    24412443    if (*pszReg == '@')
    24422444        pszReg++;
     
    24502452    }
    24512453    const char * const pszActualPrefix = idCpu & DBGFREG_HYPER_VMCPUID ? "." : "";
    2452 
    2453     /*
    2454      * Query the register type & value (the setter needs the type).
    2455      */
    2456     DBGFREGVALTYPE  enmType;
    2457     DBGFREGVAL      Value;
    2458     int rc = DBGFR3RegNmQuery(pUVM, idCpu, pszReg, &Value, &enmType);
    2459     if (RT_FAILURE(rc))
    2460     {
    2461         if (rc == VERR_DBGF_REGISTER_NOT_FOUND)
    2462             return DBGCCmdHlpVBoxError(pCmdHlp, VERR_INVALID_PARAMETER, "Unknown register: '%s%s'.\n",
    2463                                        pszActualPrefix,  pszReg);
    2464         return DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegNmQuery failed querying '%s%s': %Rrc.\n",
    2465                                    pszActualPrefix,  pszReg, rc);
    2466     }
    24672454    if (cArgs == 1)
    24682455    {
    24692456        /*
    24702457         * Show the register.
     2458         *
     2459         * If it ends with a '.' or '.*', we'll show any subfields and aliases as
     2460         * well.  This is a special VBox twist.
    24712461         */
     2462        size_t cchReg    = strlen(pszReg);
     2463        size_t cchSuffix = 0;
     2464        if (cchReg >= 2 && pszReg[cchReg - 1] == '.')
     2465            cchSuffix = 1;
     2466        else if (cchReg >= 3 && pszReg[cchReg - 1] == '*' && pszReg[cchReg - 2] == '.')
     2467            cchSuffix = 2;
     2468
    24722469        char szValue[160];
    2473         rc = DBGFR3RegFormatValue(szValue, sizeof(szValue), &Value, enmType, true /*fSpecial*/);
    2474         if (RT_SUCCESS(rc))
    2475             rc = DBGCCmdHlpPrintf(pCmdHlp, "%s%s=%s\n", pszActualPrefix, pszReg, szValue);
     2470        if (!cchSuffix && !fAllRegs)
     2471        {
     2472            DBGFREGVALTYPE  enmType;
     2473            DBGFREGVAL      Value;
     2474            rc = DBGFR3RegNmQuery(pUVM, idCpu, pszReg, &Value, &enmType);
     2475            if (RT_FAILURE(rc))
     2476            {
     2477                if (rc == VERR_DBGF_REGISTER_NOT_FOUND)
     2478                    return DBGCCmdHlpVBoxError(pCmdHlp, VERR_INVALID_PARAMETER, "Unknown register: '%s%s'.\n",
     2479                                               pszActualPrefix,  pszReg);
     2480                return DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegNmQuery failed querying '%s%s': %Rrc.\n",
     2481                                           pszActualPrefix,  pszReg, rc);
     2482            }
     2483
     2484            rc = DBGFR3RegFormatValue(szValue, sizeof(szValue), &Value, enmType, true /*fSpecial*/);
     2485            if (RT_SUCCESS(rc))
     2486                rc = DBGCCmdHlpPrintf(pCmdHlp, "%s%s=%s\n", pszActualPrefix, pszReg, szValue);
     2487            else
     2488                rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegFormatValue failed: %Rrc.\n", rc);
     2489        }
    24762490        else
    2477             rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegFormatValue failed: %Rrc.\n", rc);
     2491        {
     2492            /*
     2493             * Register + aliases + subfields OR 'all'.
     2494             */
     2495            /* Duplicate the register specifier sans suffix. */
     2496            char            *pszRegBase = RTStrDupN(pszReg, cchReg - cchSuffix);
     2497            AssertReturn(pszRegBase, VERR_NO_STR_MEMORY);
     2498
     2499            /* Make a rough guess on how many entires we need, or query it in the case of 'all'. */
     2500            size_t          cRegsAlloc = 128;
     2501            if (fAllRegs)
     2502                DBGFR3RegNmQueryAllCount(pUVM, &cRegsAlloc);
     2503            PDBGFREGENTRYNM paRegs = (PDBGFREGENTRYNM)RTMemTmpAlloc(sizeof(paRegs[0]) * cRegsAlloc);
     2504            AssertReturnStmt(paRegs, RTStrFree(pszRegBase), VERR_NO_TMP_MEMORY);
     2505            size_t          cRegs = cRegsAlloc;
     2506
     2507            /* Query the registers.*/
     2508            if (fAllRegs)
     2509                rc = DBGFR3RegNmQueryAll(pUVM, paRegs, cRegs);
     2510            else
     2511                rc = DBGFR3RegNmQueryEx(pUVM, idCpu, pszRegBase, DBGFR3REG_QUERY_EX_F_SUBFIELDS | DBGFR3REG_QUERY_EX_F_ALIASES,
     2512                                        paRegs, &cRegs);
     2513            if (rc == VERR_BUFFER_OVERFLOW && !fAllRegs)
     2514            {
     2515                RTMemTmpFree(paRegs);
     2516                cRegsAlloc = cRegs;
     2517                paRegs = (PDBGFREGENTRYNM)RTMemTmpAlloc(sizeof(paRegs[0]) * cRegsAlloc);
     2518                AssertReturnStmt(paRegs, RTStrFree(pszRegBase), VERR_NO_TMP_MEMORY);
     2519                rc = DBGFR3RegNmQueryEx(pUVM, idCpu, pszRegBase,
     2520                                        DBGFR3REG_QUERY_EX_F_SUBFIELDS | DBGFR3REG_QUERY_EX_F_ALIASES, paRegs, &cRegs);
     2521            }
     2522            if (RT_SUCCESS(rc))
     2523            {
     2524                /* Find max lengths and sizes for producing pretty columns. */
     2525                size_t cchMaxNm         = 2;
     2526                size_t cchMaxSubFieldNm = 2;
     2527                size_t cMaxSubFieldBits = 1;
     2528                if (*pszActualPrefix == '\0')
     2529                    for (uint32_t iReg = 0; iReg < cRegs; iReg++)
     2530                    {
     2531                        size_t const cchName = strlen(paRegs[iReg].pszName);
     2532                        if (cchMaxNm < cchName)
     2533                            cchMaxNm = cchName;
     2534                        if (paRegs[iReg].u.s.fSubField)
     2535                        {
     2536                            cchMaxSubFieldNm = RT_MAX(cchMaxSubFieldNm, cchName);
     2537                            cMaxSubFieldBits = RT_MAX(cMaxSubFieldBits, paRegs[iReg].u.s.cBits);
     2538                        }
     2539                    }
     2540
     2541                /* Output the registers. */
     2542                size_t   cchMaxSubFieldValue = 2 + (cMaxSubFieldBits + 3) / 4;
     2543                size_t   cMaxSameLine        = 80 / (2 + cchMaxSubFieldNm + 1 + cchMaxSubFieldValue);
     2544                unsigned iSameLine           = 0;
     2545                for (uint32_t iReg = 0; iReg < cRegs; iReg++)
     2546                {
     2547                    if (   !paRegs[iReg].u.s.fSubField
     2548                        || !paRegs[iReg].u.s.cBits)
     2549                        rc = DBGFR3RegFormatValue(szValue, sizeof(szValue), &paRegs[iReg].Val,
     2550                                                  paRegs[iReg].enmType, true /*fSpecial*/);
     2551                    else
     2552                        rc = DBGFR3RegFormatValueEx(szValue, sizeof(szValue), &paRegs[iReg].Val, paRegs[iReg].enmType,
     2553                                                    16,
     2554                                                    (paRegs[iReg].u.s.cBits + 3) / 4,
     2555                                                    0,
     2556                                                    (paRegs[iReg].u.s.cBits == 1 ? 0 : RTSTR_F_SPECIAL) | RTSTR_F_WIDTH);
     2557                    if (RT_SUCCESS(rc))
     2558                    {
     2559                        if (!paRegs[iReg].u.s.fSubField)
     2560                        {
     2561                            if (iSameLine > 0)
     2562                                rc = DBGCCmdHlpPrintf(pCmdHlp, "\n");
     2563                            if (*pszActualPrefix == '\0')
     2564                                rc = DBGCCmdHlpPrintf(pCmdHlp, "%*s=%s\n", cchMaxNm, paRegs[iReg].pszName, szValue);
     2565                            else
     2566                                rc = DBGCCmdHlpPrintf(pCmdHlp, "%s%s=%s\n", pszActualPrefix, paRegs[iReg].pszName, szValue);
     2567                            iSameLine = 0;
     2568                        }
     2569                        else
     2570                        {
     2571                            if (*pszActualPrefix == '\0')
     2572                                rc = DBGCCmdHlpPrintf(pCmdHlp, "  %*s=%s", cchMaxSubFieldNm, paRegs[iReg].pszName, szValue);
     2573                            else
     2574                                rc = DBGCCmdHlpPrintf(pCmdHlp, "  %s%s=%s", pszActualPrefix, paRegs[iReg].pszName, szValue);
     2575                            iSameLine++;
     2576                            if (iSameLine < cMaxSameLine)
     2577                            {
     2578                                size_t cchValue = strlen(szValue);
     2579                                if (cchValue < cchMaxSubFieldValue)
     2580                                    rc = DBGCCmdHlpPrintf(pCmdHlp, "%*s", cchMaxSubFieldValue - cchValue, "");
     2581                            }
     2582                            else
     2583                            {
     2584                                rc = DBGCCmdHlpPrintf(pCmdHlp, "\n");
     2585                                iSameLine = 0;
     2586                            }
     2587                        }
     2588                    }
     2589                    else
     2590                        rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegFormatValue[Ex] failed for %s: %Rrc.\n",
     2591                                                 paRegs[iReg].pszName, rc);
     2592                }
     2593                if (iSameLine > 0)
     2594                    rc = DBGCCmdHlpPrintf(pCmdHlp, "\n");
     2595            }
     2596            else if (fAllRegs)
     2597                rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegNmQueryAll failed: %Rrc.\n",
     2598                                         pszActualPrefix, rc);
     2599            else if (rc == VERR_DBGF_REGISTER_NOT_FOUND)
     2600                rc = DBGCCmdHlpVBoxError(pCmdHlp, VERR_INVALID_PARAMETER, "Unknown register: '%s%s'.\n",
     2601                                         pszActualPrefix, pszRegBase);
     2602            else
     2603                rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegNmQueryEx failed querying '%s%s': %Rrc.\n",
     2604                                         pszActualPrefix, pszRegBase, rc);
     2605            RTStrFree(pszRegBase);
     2606            RTMemTmpFree(paRegs);
     2607        }
    24782608    }
    24792609    else
    24802610    {
     2611        /*
     2612         * We're about to modify the register.
     2613         *
     2614         * First we need to query the register type (see below).
     2615         */
     2616        DBGFREGVALTYPE  enmType;
     2617        DBGFREGVAL      Value;
     2618        rc = DBGFR3RegNmQuery(pUVM, idCpu, pszReg, &Value, &enmType);
     2619        if (RT_FAILURE(rc))
     2620        {
     2621            if (rc == VERR_DBGF_REGISTER_NOT_FOUND)
     2622                return DBGCCmdHlpVBoxError(pCmdHlp, VERR_INVALID_PARAMETER, "Unknown register: '%s%s'.\n",
     2623                                           pszActualPrefix,  pszReg);
     2624            return DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegNmQuery failed querying '%s%s': %Rrc.\n",
     2625                                       pszActualPrefix,  pszReg, rc);
     2626        }
     2627
    24812628        DBGCVAR   NewValueTmp;
    24822629        PCDBGCVAR pNewValue;
  • trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp

    r100940 r102092  
    302302    return VERR_DBGF_REGISTER_NOT_FOUND;
    303303}
     304VMMR3DECL(int) DBGFR3RegNmQueryEx(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t fFlags,
     305                                  PDBGFREGENTRYNM paRegs, size_t *pcRegs)
     306{
     307    return VERR_INTERNAL_ERROR;
     308}
     309VMMR3DECL(int) DBGFR3RegNmQueryAll(PUVM pUVM, PDBGFREGENTRYNM paRegs, size_t cRegs)
     310{
     311    return VERR_INTERNAL_ERROR;
     312}
     313VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PUVM pUVM, size_t *pcRegs)
     314{
     315    *pcRegs = 99;
     316    return VINF_SUCCESS;
     317}
    304318VMMR3DECL(int) DBGFR3RegPrintf(PUVM pUVM, VMCPUID idCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, ...)
    305319{
     
    308322VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial)
    309323{
     324    return VERR_INTERNAL_ERROR;
     325}
     326VMMDECL(ssize_t) DBGFR3RegFormatValueEx(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType,
     327                                        unsigned uBase, signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
     328{
     329    RT_NOREF(pszBuf, cbBuf, pValue, enmType, uBase, cchWidth, cchPrecision, fFlags);
    310330    return VERR_INTERNAL_ERROR;
    311331}
  • trunk/src/VBox/Main/src-client/MachineDebuggerImpl.cpp

    r98278 r102092  
    11151115                        aValues.resize(cRegs);
    11161116                        aNames.resize(cRegs);
    1117                         for (uint32_t iReg = 0; iReg < cRegs; iReg++)
     1117                        uint32_t iDst = 0;
     1118                        for (uint32_t iSrc = 0; iSrc < cRegs; iSrc++)
     1119                            if (paRegs[iSrc].pszName) /* skip padding entries */
     1120                            {
     1121                                char szHex[160];
     1122                                szHex[159] = szHex[0] = '\0';
     1123                                ssize_t cch = ptrVM.vtable()->pfnDBGFR3RegFormatValue(szHex, sizeof(szHex), &paRegs[iSrc].Val,
     1124                                                                                      paRegs[iSrc].enmType, true /*fSpecial*/);
     1125                                Assert(cch > 0); NOREF(cch);
     1126                                aNames[iDst]  = paRegs[iSrc].pszName;
     1127                                aValues[iDst] = szHex;
     1128                                iDst++;
     1129                            }
     1130
     1131                        /* If we skipped padding entries, resize the return arrays to the actual return size. */
     1132                        if (iDst < cRegs)
    11181133                        {
    1119                             char szHex[160];
    1120                             szHex[159] = szHex[0] = '\0';
    1121                             ssize_t cch = ptrVM.vtable()->pfnDBGFR3RegFormatValue(szHex, sizeof(szHex), &paRegs[iReg].Val,
    1122                                                                                   paRegs[iReg].enmType, true /*fSpecial*/);
    1123                             Assert(cch > 0); NOREF(cch);
    1124                             aNames[iReg]  = paRegs[iReg].pszName;
    1125                             aValues[iReg] = szHex;
     1134                            aValues.resize(iDst);
     1135                            aNames.resize(iDst);
    11261136                        }
    11271137                    }
  • 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
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r98103 r102092  
    13581358     * register aliases (eg AH) are not counted). */
    13591359    uint32_t                    cRegs;
     1360    /** Number of registers per CPU. */
     1361    uint16_t                    cPerCpuRegs;
     1362    /** Number of hypervisor register per CPU. */
     1363    uint8_t                     cPerCpuHyperRegs;
    13601364    /** For early initialization by . */
    13611365    bool volatile               fRegDbInitialized;
    1362     /** Alignment padding. */
    1363     bool                        afAlignment2[3];
    13641366
    13651367    /** Critical section protecting the Guest OS Digger data, the info handlers
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette