VirtualBox

Changeset 48898 in vbox


Ignore:
Timestamp:
Oct 4, 2013 8:01:01 PM (11 years ago)
Author:
vboxsync
Message:

VMM,DBGC: Implemented DBGFR3RegNmSet and made the debugger side work.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/dbgf.h

    r48694 r48898  
    12861286typedef union DBGFREGVAL
    12871287{
     1288    uint64_t    au64[2];        /**< The 64-bit array view. First because of the initializer. */
     1289    uint32_t    au32[4];        /**< The 32-bit array view. */
     1290    uint16_t    au16[8];        /**< The 16-bit array view. */
     1291    uint8_t     au8[16];        /**< The 8-bit array view. */
     1292
    12881293    uint8_t     u8;             /**< The 8-bit view. */
    12891294    uint16_t    u16;            /**< The 16-bit view. */
     
    13021307    }           dtr;
    13031308
    1304     uint8_t     au8[16];        /**< The 8-bit array view.  */
    1305     uint16_t    au16[8];        /**< The 16-bit array view.  */
    1306     uint32_t    au32[4];        /**< The 32-bit array view.  */
    1307     uint64_t    au64[2];        /**< The 64-bit array view.  */
    13081309    RTUINT128U  u;
    13091310} DBGFREGVAL;
     
    13121313/** Pointer to a const generic register value type. */
    13131314typedef DBGFREGVAL const *PCDBGFREGVAL;
     1315
     1316/** Initialize a DBGFREGVAL variable to all zeros.  */
     1317#define DBGFREGVAL_INITIALIZE_ZERO { { 0, 0 } }
     1318/** Initialize a DBGFREGVAL variable to all bits set .  */
     1319#define DBGFREGVAL_INITIALIZE_FFFF { { UINT64_MAX, UINT64_MAX } }
     1320
    13141321
    13151322VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial);
  • trunk/src/VBox/Debugger/DBGCCmdHlp.cpp

    r47564 r48898  
    723723
    724724/**
     725 * @copydoc DBGCCMDHLP::pfnParserError
     726 */
     727static DECLCALLBACK(int) dbgcHlpParserError(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine)
     728{
     729    PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
     730
     731    /*
     732     * Do the formatting and output.
     733     */
     734    pDbgc->rcOutput = VINF_SUCCESS;
     735    RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, "%s: parser error: iArg=%d iLine=%u pszExpr=%s\n",
     736                pCmd->pszCmd, iArg, iLine, pszExpr);
     737    if (RT_FAILURE(pDbgc->rcOutput))
     738        return pDbgc->rcOutput;
     739    return VERR_DBGC_COMMAND_FAILED;
     740}
     741
     742
     743/**
    725744 * @interface_method_impl{DBGCCMDHLP,pfnVarToDbgfAddr}
    726745 */
     
    13451364    pDbgc->CmdHlp.pfnFailV              = dbgcHlpFailV;
    13461365    pDbgc->CmdHlp.pfnFailRcV            = dbgcHlpFailRcV;
     1366    pDbgc->CmdHlp.pfnParserError        = dbgcHlpParserError;
    13471367    pDbgc->CmdHlp.pfnVarToDbgfAddr      = dbgcHlpVarToDbgfAddr;
    13481368    pDbgc->CmdHlp.pfnVarFromDbgfAddr    = dbgcHlpVarFromDbgfAddr;
  • trunk/src/VBox/Debugger/DBGCEmulateCodeView.cpp

    r48017 r48898  
    248248    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    249249    {  0,           1,          DBGCVAR_CAT_SYMBOL,     0,                              "register",     "Register to show or set." },
    250     {  0,           1,     DBGCVAR_CAT_NUMBER_NO_RANGE, DBGCVD_FLAGS_DEP_PREV,          "value",        "New register value." },
     250    {  0,           1,          DBGCVAR_CAT_STRING, DBGCVD_FLAGS_DEP_PREV,              "=",            "Equal sign." },
     251    {  0,           1,          DBGCVAR_CAT_NUMBER, DBGCVD_FLAGS_DEP_PREV,              "value",        "New register value." },
    251252};
    252253
     
    348349    { "ls",         0,        1,        &g_aArgListSource[0],RT_ELEMENTS(g_aArgListSource), 0,       dbgcCmdListSource,  "[addr]",               "Source." },
    349350    { "m",          1,        1,        &g_aArgMemoryInfo[0],RT_ELEMENTS(g_aArgMemoryInfo), 0,       dbgcCmdMemoryInfo,  "<addr>",               "Display information about that piece of memory." },
    350     { "r",          0,        2,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdReg,         "[reg [newval]]",       "Show or set register(s) - active reg set." },
    351     { "rg",         0,        2,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdRegGuest,    "[reg [newval]]",       "Show or set register(s) - guest reg set." },
     351    { "r",          0,        3,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdReg,         "[reg [[=] newval]]",   "Show or set register(s) - active reg set." },
     352    { "rg",         0,        3,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdRegGuest,    "[reg [[=] newval]]",   "Show or set register(s) - guest reg set." },
    352353    { "rg32",       0,        0,        NULL,               0,                              0,       dbgcCmdRegGuest,    "",                     "Show 32-bit guest registers." },
    353354    { "rg64",       0,        0,        NULL,               0,                              0,       dbgcCmdRegGuest,    "",                     "Show 64-bit guest registers." },
    354     { "rh",         0,        2,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdRegHyper,    "[reg [newval]]",       "Show or set register(s) - hypervisor reg set." },
     355    { "rh",         0,        3,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),         0,       dbgcCmdRegHyper,    "[reg [[=] newval]]",   "Show or set register(s) - hypervisor reg set." },
    355356    { "rt",         0,        0,        NULL,               0,                              0,       dbgcCmdRegTerse,    "",                     "Toggles terse / verbose register info." },
    356357    { "s",          0,       ~0U,       &g_aArgSearchMem[0], RT_ELEMENTS(g_aArgSearchMem),  0,       dbgcCmdSearchMem,   "[options] <range> <pattern>",  "Continue last search." },
     
    13311332{
    13321333    PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1333     Assert(cArgs == 1 || cArgs == 2); /* cArgs == 0 is handled by the caller  */
    1334     DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 1 || cArgs == 2);
     1334    DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 1 || cArgs == 2 || cArgs == 3);
    13351335    DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0,    paArgs[0].enmType == DBGCVAR_TYPE_STRING
    13361336                                                    || paArgs[0].enmType == DBGCVAR_TYPE_SYMBOL);
     
    13781378            rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegFormatValue failed: %Rrc.\n", rc);
    13791379    }
    1380     else if (cArgs == 2)
    1381     {
     1380    else
     1381    {
     1382        DBGCVAR   NewValueTmp;
     1383        PCDBGCVAR pNewValue;
     1384        if (cArgs == 3)
     1385        {
     1386            DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 1, paArgs[1].enmType == DBGCVAR_TYPE_STRING);
     1387            if (strcmp(paArgs[1].u.pszString, "="))
     1388                return DBGCCmdHlpFail(pCmdHlp, pCmd, "Second argument must be '='.");
     1389            pNewValue = &paArgs[2];
     1390        }
     1391        else
     1392        {
     1393            /* Not possible to convince the parser to support both codeview and
     1394               windbg syntax and make the equal sign optional.  Try help it. */
     1395            /** @todo make DBGCCmdHlpConvert do more with strings. */
     1396            rc = DBGCCmdHlpConvert(pCmdHlp, &paArgs[1], DBGCVAR_TYPE_NUMBER, true /*fConvSyms*/, &NewValueTmp);
     1397            if (RT_FAILURE(rc))
     1398                return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "The last argument must be a value or valid symbol.");
     1399            pNewValue = &NewValueTmp;
     1400        }
     1401
    13821402        /*
    13831403         * Modify the register.
    13841404         */
    1385         DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 1,    paArgs[1].enmType == DBGCVAR_TYPE_STRING
    1386                                                         || paArgs[1].enmType == DBGCVAR_TYPE_SYMBOL);
     1405        DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 1, pNewValue->enmType == DBGCVAR_TYPE_NUMBER);
    13871406        if (enmType != DBGFREGVALTYPE_DTR)
    13881407        {
    13891408            enmType = DBGFREGVALTYPE_U64;
    1390             rc = DBGCCmdHlpVarToNumber(pCmdHlp, &paArgs[1], &Value.u64);
     1409            rc = DBGCCmdHlpVarToNumber(pCmdHlp, pNewValue, &Value.u64);
    13911410        }
    13921411        else
    13931412        {
    13941413            enmType = DBGFREGVALTYPE_DTR;
    1395             rc = DBGCCmdHlpVarToNumber(pCmdHlp, &paArgs[1], &Value.dtr.u64Base);
    1396             if (RT_SUCCESS(rc) && paArgs[1].enmRangeType != DBGCVAR_RANGE_NONE)
    1397                 Value.dtr.u32Limit = (uint32_t)paArgs[1].u64Range;
     1414            rc = DBGCCmdHlpVarToNumber(pCmdHlp, pNewValue, &Value.dtr.u64Base);
     1415            if (RT_SUCCESS(rc) && pNewValue->enmRangeType != DBGCVAR_RANGE_NONE)
     1416                Value.dtr.u32Limit = (uint32_t)pNewValue->u64Range;
    13981417        }
    13991418        if (RT_SUCCESS(rc))
     
    14061425        else
    14071426            rc = DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegFormatValue failed: %Rrc.\n", rc);
    1408     }
    1409     else
    1410     {
    1411         NOREF(pCmd); NOREF(paArgs);
    1412         rc = DBGCCmdHlpPrintf(pCmdHlp, "Huh? cArgs=%d Expected 0, 1 or 2!\n", cArgs);
    14131427    }
    14141428    return rc;
  • trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp

    r46155 r48898  
    19011901
    19021902
     1903/**
     1904 * On CPU worker for the register modifications, used by DBGFR3RegNmSet.
     1905 *
     1906 * @returns VBox status code.
     1907 *
     1908 * @param   pUVM                The user mode VM handle.
     1909 * @param   pLookupRec          The register lookup record. Maybe be modified,
     1910 *                              so please pass a copy of the user's one.
     1911 * @param   pValue              The new register value.
     1912 * @param   enmType             The register value type.
     1913 */
     1914static DECLCALLBACK(int) dbgfR3RegNmSetWorkerOnCpu(PUVM pUVM, PDBGFREGLOOKUP pLookupRec,
     1915                                                   PCDBGFREGVAL pValue, PCDBGFREGVAL pMask)
     1916{
     1917    PCDBGFREGSUBFIELD pSubField = pLookupRec->pSubField;
     1918    if (pSubField && pSubField->pfnSet)
     1919        return pSubField->pfnSet(pLookupRec->pSet->uUserArg.pv, pSubField, pValue->u128, pMask->u128);
     1920    return pLookupRec->pDesc->pfnSet(pLookupRec->pSet->uUserArg.pv, pLookupRec->pDesc, pValue, pMask);
     1921}
     1922
     1923
     1924/**
     1925 * Worker for the register setting.
     1926 *
     1927 * @returns VBox status code.
     1928 * @retval  VINF_SUCCESS
     1929 * @retval  VERR_INVALID_VM_HANDLE
     1930 * @retval  VERR_INVALID_CPU_ID
     1931 * @retval  VERR_DBGF_REGISTER_NOT_FOUND
     1932 * @retval  VERR_DBGF_UNSUPPORTED_CAST
     1933 * @retval  VINF_DBGF_TRUNCATED_REGISTER
     1934 * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
     1935 *
     1936 * @param   pUVM                The user mode VM handle.
     1937 * @param   idDefCpu            The virtual CPU ID for the default CPU register
     1938 *                              set.  Can be OR'ed with DBGFREG_HYPER_VMCPUID.
     1939 * @param   pszReg              The register to query.
     1940 * @param   pValue              The value to set
     1941 * @param   enmType             How to interpret the value in @a pValue.
     1942 */
    19031943VMMR3DECL(int) DBGFR3RegNmSet(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType)
    19041944{
    1905     NOREF(pUVM); NOREF(idDefCpu); NOREF(pszReg); NOREF(pValue); NOREF(enmType);
    1906     return VERR_NOT_IMPLEMENTED;
     1945    /*
     1946     * Validate input.
     1947     */
     1948    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     1949    VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE);
     1950    AssertReturn((idDefCpu & ~DBGFREG_HYPER_VMCPUID) < pUVM->cCpus || idDefCpu == VMCPUID_ANY, VERR_INVALID_CPU_ID);
     1951    AssertPtrReturn(pszReg, VERR_INVALID_POINTER);
     1952    AssertReturn(enmType > DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
     1953    AssertPtrReturn(pValue, VERR_INVALID_PARAMETER);
     1954
     1955    /*
     1956     * Resolve the register and check that it is writable.
     1957     */
     1958    bool fGuestRegs = true;
     1959    if ((idDefCpu & DBGFREG_HYPER_VMCPUID) && idDefCpu != VMCPUID_ANY)
     1960    {
     1961        fGuestRegs = false;
     1962        idDefCpu &= ~DBGFREG_HYPER_VMCPUID;
     1963    }
     1964    PCDBGFREGLOOKUP pLookupRec = dbgfR3RegResolve(pUVM, idDefCpu, pszReg, fGuestRegs);
     1965    if (pLookupRec)
     1966    {
     1967        PCDBGFREGDESC       pDesc        = pLookupRec->pDesc;
     1968        PCDBGFREGSET        pSet         = pLookupRec->pSet;
     1969        PCDBGFREGSUBFIELD   pSubField    = pLookupRec->pSubField;
     1970
     1971        if (  !(pDesc->fFlags & DBGFREG_FLAGS_READ_ONLY)
     1972            && (pSubField
     1973                ?    !(pSubField->fFlags & DBGFREGSUBFIELD_FLAGS_READ_ONLY)
     1974                  && (pSubField->pfnSet != NULL || pDesc->pfnSet != NULL)
     1975                : pDesc->pfnSet != NULL) )
     1976        {
     1977            /*
     1978             * Calculate the modification mask and cast the input value to the
     1979             * type of the target register.
     1980             */
     1981            DBGFREGVAL Mask  = DBGFREGVAL_INITIALIZE_ZERO;
     1982            DBGFREGVAL Value = DBGFREGVAL_INITIALIZE_ZERO;
     1983            switch (enmType)
     1984            {
     1985                case DBGFREGVALTYPE_U8:
     1986                    Value.u8  = pValue->u8;
     1987                    Mask.u8   = UINT8_MAX;
     1988                    break;
     1989                case DBGFREGVALTYPE_U16:
     1990                    Value.u16 = pValue->u16;
     1991                    Mask.u16  = UINT16_MAX;
     1992                    break;
     1993                case DBGFREGVALTYPE_U32:
     1994                    Value.u32 = pValue->u32;
     1995                    Mask.u32  = UINT32_MAX;
     1996                    break;
     1997                case DBGFREGVALTYPE_U64:
     1998                    Value.u64 = pValue->u64;
     1999                    Mask.u64  = UINT64_MAX;
     2000                    break;
     2001                case DBGFREGVALTYPE_U128:
     2002                    Value.u128 = pValue->u128;
     2003                    Mask.u128.s.Lo = UINT64_MAX;
     2004                    Mask.u128.s.Hi = UINT64_MAX;
     2005                    break;
     2006                case DBGFREGVALTYPE_R80:
     2007#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
     2008                    Value.r80Ex.lrd = pValue->r80Ex.lrd;
     2009#else
     2010                    Value.r80Ex.au64[0] = pValue->r80Ex.au64[0];
     2011                    Value.r80Ex.au16[4] = pValue->r80Ex.au16[4];
     2012#endif
     2013                    Value.r80Ex.au64[0] = UINT64_MAX;
     2014                    Value.r80Ex.au16[4] = UINT16_MAX;
     2015                    break;
     2016                case DBGFREGVALTYPE_DTR:
     2017                    Value.dtr.u32Limit = pValue->dtr.u32Limit;
     2018                    Value.dtr.u64Base  = pValue->dtr.u64Base;
     2019                    Mask.dtr.u32Limit  = UINT32_MAX;
     2020                    Mask.dtr.u64Base   = UINT64_MAX;
     2021                    break;
     2022                case DBGFREGVALTYPE_32BIT_HACK:
     2023                case DBGFREGVALTYPE_END:
     2024                case DBGFREGVALTYPE_INVALID:
     2025                    AssertFailedReturn(VERR_INTERNAL_ERROR_3);
     2026            }
     2027
     2028            int rc = VINF_SUCCESS;
     2029            DBGFREGVALTYPE enmRegType = pDesc->enmType;
     2030            if (pSubField)
     2031            {
     2032                unsigned const cBits = pSubField->cBits + pSubField->cShift;
     2033                if (cBits <= 8)
     2034                    enmRegType = DBGFREGVALTYPE_U8;
     2035                else if (cBits <= 16)
     2036                    enmRegType = DBGFREGVALTYPE_U16;
     2037                else if (cBits <= 32)
     2038                    enmRegType = DBGFREGVALTYPE_U32;
     2039                else if (cBits <= 64)
     2040                    enmRegType = DBGFREGVALTYPE_U64;
     2041                else
     2042                    enmRegType = DBGFREGVALTYPE_U128;
     2043            }
     2044            else if (pLookupRec->pAlias)
     2045            {
     2046                /* Restrict the input to the size of the alias register. */
     2047                DBGFREGVALTYPE enmAliasType = pLookupRec->pAlias->enmType;
     2048                if (enmAliasType != enmType)
     2049                {
     2050                    rc = dbgfR3RegValCast(&Value, enmType, enmAliasType);
     2051                    if (RT_FAILURE(rc))
     2052                        return rc;
     2053                    dbgfR3RegValCast(&Mask, enmType, enmAliasType);
     2054                    enmType = enmAliasType;
     2055                }
     2056            }
     2057
     2058            if (enmType != enmRegType)
     2059            {
     2060                int rc2 = dbgfR3RegValCast(&Value, enmType, enmRegType);
     2061                if (RT_FAILURE(rc2))
     2062                    return rc2;
     2063                if (rc2 != VINF_SUCCESS && rc == VINF_SUCCESS)
     2064                    rc2 = VINF_SUCCESS;
     2065                dbgfR3RegValCast(&Mask, enmType, enmRegType);
     2066            }
     2067
     2068            /*
     2069             * Subfields needs some extra processing if there is no subfield
     2070             * setter, since we'll be feeding it to the normal register setter
     2071             * instead.  The mask and value must be shifted and truncated to the
     2072             * subfield position.
     2073             */
     2074            if (pSubField && !pSubField->pfnSet)
     2075            {
     2076                /* The shift factor is for displaying a subfield value
     2077                   2**cShift times larger than the stored value.  We have
     2078                   to undo this before adjusting value and mask.  */
     2079                if (pSubField->cShift)
     2080                {
     2081                    /* Warn about trunction of the lower bits that get
     2082                       shifted out below. */
     2083                    if (rc == VINF_SUCCESS)
     2084                    {
     2085                        DBGFREGVAL Value2 = Value;
     2086                        RTUInt128AssignAndNFirstBits(&Value2.u128, -pSubField->cShift);
     2087                        if (!RTUInt128BitAreAllClear(&Value2.u128))
     2088                            rc = VINF_DBGF_TRUNCATED_REGISTER;
     2089                    }
     2090                    RTUInt128AssignShiftRight(&Value.u128, pSubField->cShift);
     2091                }
     2092
     2093                DBGFREGVAL Value3 = Value;
     2094                RTUInt128AssignAndNFirstBits(&Value.u128, pSubField->cBits);
     2095                if (rc == VINF_SUCCESS && RTUInt128IsNotEqual(&Value.u128, &Value.u128))
     2096                    rc = VINF_DBGF_TRUNCATED_REGISTER;
     2097                RTUInt128AssignAndNFirstBits(&Mask.u128,  pSubField->cBits);
     2098
     2099                RTUInt128AssignShiftLeft(&Value.u128, pSubField->iFirstBit);
     2100                RTUInt128AssignShiftLeft(&Mask.u128,  pSubField->iFirstBit);
     2101            }
     2102
     2103            /*
     2104             * Do the actual work on an EMT.
     2105             */
     2106            if (pSet->enmType == DBGFREGSETTYPE_CPU)
     2107                idDefCpu = pSet->uUserArg.pVCpu->idCpu;
     2108            else if (idDefCpu != VMCPUID_ANY)
     2109                idDefCpu &= ~DBGFREG_HYPER_VMCPUID;
     2110
     2111            int rc2 = VMR3ReqPriorityCallWaitU(pUVM, idDefCpu, (PFNRT)dbgfR3RegNmSetWorkerOnCpu, 4,
     2112                                               pUVM, pLookupRec, &Value, &Mask);
     2113
     2114            if (rc == VINF_SUCCESS || RT_FAILURE(rc2))
     2115                rc = rc2;
     2116            return rc;
     2117        }
     2118        return VERR_DBGF_READ_ONLY_REGISTER;
     2119    }
     2120    return VERR_DBGF_REGISTER_NOT_FOUND;
    19072121}
    19082122
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