VirtualBox

Changeset 41571 in vbox


Ignore:
Timestamp:
Jun 4, 2012 7:49:03 PM (13 years ago)
Author:
vboxsync
Message:

DBGC: Fixed cpu register references without @. Some symbol/string work. Updated the docs a little bit.

Location:
trunk/src/VBox/Debugger
Files:
5 edited

Legend:

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

    r41565 r41571  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    11981198                        rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult);
    11991199                        if (RT_SUCCESS(rc))
    1200                         {
    1201                             if (InVar.enmRangeType != DBGCVAR_RANGE_NONE)
    1202                             {
    1203                                 pResult->enmRangeType = InVar.enmRangeType;
    1204                                 pResult->u64Range     = InVar.u64Range;
    1205                             }
    12061200                            return VINF_SUCCESS;
    1207                         }
    12081201                    }
    12091202                    return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
  • trunk/src/VBox/Debugger/DBGCCommands.cpp

    r41561 r41571  
    10641064                break;
    10651065
     1066            case DBGCVAR_TYPE_SYMBOL:
     1067                rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
     1068                    "Symbol, %lld bytes long: %s\n",
     1069                    paArgs[iArg].u64Range,
     1070                    paArgs[iArg].u.pszString);
     1071                break;
     1072
    10661073            case DBGCVAR_TYPE_NUMBER:
    10671074                if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
  • trunk/src/VBox/Debugger/DBGCEval.cpp

    r41561 r41571  
    7676
    7777
    78 
    79 static int dbgcEvalSubString(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pArg)
     78/**
     79 * Returns the amount of free scratch space.
     80 *
     81 * @returns Number of unallocated bytes.
     82 * @param   pDbgc               The DBGC instance.
     83 */
     84size_t dbgcGetFreeScratchSpace(PDBGC pDbgc)
    8085{
    81     Log2(("dbgcEvalSubString: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
     86    return sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
     87}
     88
     89
     90/**
     91 * Allocates a string from the scratch space.
     92 *
     93 * @returns Pointer to the allocated string buffer, NULL if out of space.
     94 * @param   pDbgc               The DBGC instance.
     95 * @param   cbRequested         The number of bytes to allocate.
     96 */
     97char *dbgcAllocStringScatch(PDBGC pDbgc, size_t cbRequested)
     98{
     99    if (cbRequested > dbgcGetFreeScratchSpace(pDbgc))
     100        return NULL;
     101    char *psz = pDbgc->pszScratch;
     102    pDbgc->pszScratch += cbRequested;
     103    return psz;
     104}
     105
     106
     107/**
     108 * Evals an expression into a string or symbol (single quotes).
     109 *
     110 * The string memory is allocated from the scratch buffer.
     111 *
     112 * @returns VBox status code.
     113 * @param   pDbgc               The DBGC instance.
     114 * @param   pachExpr            The string/symbol expression.
     115 * @param   cchExpr             The length of the expression.
     116 * @param   pArg                Where to return the string.
     117 */
     118static int dbgcEvalSubString(PDBGC pDbgc, const char *pachExpr, size_t cchExpr, PDBGCVAR pArg)
     119{
     120    Log2(("dbgcEvalSubString: cchExpr=%d pachExpr=%.*s\n", cchExpr, cchExpr, pachExpr));
     121
     122    /*
     123     * Allocate scratch space for the string.
     124     */
     125    char *pszCopy = dbgcAllocStringScatch(pDbgc, cchExpr + 1);
     126    if (!pszCopy)
     127        return VERR_DBGC_PARSE_NO_SCRATCH;
    82128
    83129    /*
    84130     * Removing any quoting and escapings.
    85131     */
    86     char ch = *pszExpr;
    87     if (ch == '"' || ch == '\'')
    88     {
    89         if (pszExpr[--cchExpr] != ch)
     132    char const chQuote = *pachExpr;
     133    if (chQuote == '"' || chQuote == '\'')
     134    {
     135        if (pachExpr[--cchExpr] != chQuote)
    90136            return VERR_DBGC_PARSE_UNBALANCED_QUOTE;
     137
    91138        cchExpr--;
    92         pszExpr++;
    93 
    94         /** @todo string unescaping. */
    95     }
    96     pszExpr[cchExpr] = '\0';
     139        pachExpr++;
     140        if (!memchr(pachExpr, chQuote, cchExpr))
     141            memcpy(pszCopy, pachExpr, cchExpr);
     142        else
     143        {
     144            size_t offSrc = 0;
     145            size_t offDst = 0;
     146            while (offSrc < cchExpr)
     147            {
     148                char const ch = pachExpr[offSrc++];
     149                if (ch == chQuote)
     150                {
     151                    if (pachExpr[offSrc] != ch)
     152                        return VERR_DBGC_PARSE_EXPECTED_BINARY_OP;
     153                    offSrc++;
     154                }
     155                pszCopy[offDst++] = ch;
     156            }
     157        }
     158    }
     159    else
     160        memcpy(pszCopy, pachExpr, cchExpr);
     161    pszCopy[cchExpr] = '\0';
    97162
    98163    /*
     
    101166    pArg->pDesc         = NULL;
    102167    pArg->pNext         = NULL;
    103     pArg->enmType       = DBGCVAR_TYPE_STRING;
    104     pArg->u.pszString   = pszExpr;
     168    pArg->enmType       = chQuote == '\'' ? DBGCVAR_TYPE_SYMBOL : DBGCVAR_TYPE_STRING;
     169    pArg->u.pszString   = pszCopy;
    105170    pArg->enmRangeType  = DBGCVAR_RANGE_BYTES;
    106171    pArg->u64Range      = cchExpr;
     
    111176
    112177
    113 static int dbgcEvalSubNum(char *pszExpr, unsigned uBase, PDBGCVAR pArg)
     178static int dbgcEvalSubNum(const char *pachExpr, size_t cchExpr, unsigned uBase, PDBGCVAR pArg)
    114179{
    115     Log2(("dbgcEvalSubNum: uBase=%d pszExpr=%s\n", uBase, pszExpr));
     180    Log2(("dbgcEvalSubNum: uBase=%d pachExpr=%.*s\n", uBase, cchExpr, pachExpr));
     181
     182    /*
     183     * Empty expressions cannot be valid numbers.
     184     */
     185    if (!cchExpr)
     186        return VERR_DBGC_PARSE_INVALID_NUMBER;
     187
    116188    /*
    117189     * Convert to number.
    118190     */
    119191    uint64_t    u64 = 0;
    120     char        ch;
    121     while ((ch = *pszExpr) != '\0')
    122     {
     192    while (cchExpr-- > 0)
     193    {
     194        char const ch = *pachExpr;
    123195        uint64_t    u64Prev = u64;
    124196        unsigned    u = ch - '0';
     
    137209
    138210        /* next */
    139         pszExpr++;
     211        pachExpr++;
    140212    }
    141213
     
    172244    /* 0x<hex digits> */
    173245    if (ch == '0' && (ch2 == 'x' || ch2 == 'X'))
    174         return dbgcEvalSubNum(pszExpr + 2, 16, pResult);
     246        return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 16, pResult);
    175247
    176248    /* <hex digits>h */
     
    178250    {
    179251        pszExpr[cchExpr] = '\0';
    180         return dbgcEvalSubNum(pszExpr, 16, pResult);
     252        return dbgcEvalSubNum(pszExpr, cchExpr - 1, 16, pResult);
    181253    }
    182254
    183255    /* 0i<decimal digits> */
    184256    if (ch == '0' && ch2 == 'i')
    185         return dbgcEvalSubNum(pszExpr + 2, 10, pResult);
     257        return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult);
    186258
    187259    /* 0t<octal digits> */
    188260    if (ch == '0' && ch2 == 't')
    189         return dbgcEvalSubNum(pszExpr + 2, 8, pResult);
     261        return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 8, pResult);
    190262
    191263    /* 0y<binary digits> */
    192264    if (ch == '0' && ch2 == 'y')
    193         return dbgcEvalSubNum(pszExpr + 2, 10, pResult);
     265        return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult);
    194266
    195267    /* Hex number? */
    196268    unsigned off = 0;
    197     while (RT_C_IS_XDIGIT(pszExpr[off]) || pszExpr[off] == '`')
     269    while (off < cchExpr && (RT_C_IS_XDIGIT(pszExpr[off]) || pszExpr[off] == '`'))
    198270        off++;
    199271    if (off == cchExpr)
    200         return dbgcEvalSubNum(pszExpr, 16, pResult);
    201 
    202     /*
    203      * Some kind of symbol?
     272        return dbgcEvalSubNum(pszExpr, cchExpr, 16, pResult);
     273
     274    /*
     275     * Some kind of symbol?  Rejected double quoted strings, only unquoted
     276     * and single quoted strings will be considered as symbols.
    204277     */
    205278    DBGCVARTYPE enmType;
     
    219292    }
    220293
    221     if (   (*pszExpr == '"' || *pszExpr == '\'')
    222         && pszExpr[cchExpr - 1] == *pszExpr)
    223     {
     294    char const chQuote = *pszExpr;
     295    if (chQuote == '"')
     296        return VERR_DBGC_PARSE_INVALID_NUMBER;
     297
     298    if (chQuote == '\'')
     299    {
     300        if (pszExpr[cchExpr - 1] != chQuote)
     301            return VERR_DBGC_PARSE_UNBALANCED_QUOTE;
    224302        pszExpr[cchExpr - 1] = '\0';
    225303        pszExpr++;
     
    262340            off++;
    263341        if (off == cchExpr)
    264             return dbgcEvalSubNum(pszExpr + 2, 16, pResult);
     342            return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 16, pResult);
    265343        return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    266344    }
     
    275353        {
    276354            pszExpr[cchExpr] = '\0';
    277             return dbgcEvalSubNum(pszExpr, 16, pResult);
     355            return dbgcEvalSubNum(pszExpr, cchExpr, 16, pResult);
    278356        }
    279357        return dbgcEvalSubString(pDbgc, pszExpr, cchExpr + 1, pResult);
    280358    }
    281359
    282     /* 0i<decimal digits> */
    283     if (ch == '0' && ch2 == 'i')
     360    /* 0n<decimal digits> or 0i<decimal digits> */
     361    if (ch == '0' && (ch2 == 'n' || ch2 == 'i'))
    284362    {
    285363        while (RT_C_IS_DIGIT(pszExpr[off]) || pszExpr[off] == '`')
    286364            off++;
    287365        if (off == cchExpr)
    288             return dbgcEvalSubNum(pszExpr + 2, 10, pResult);
     366            return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult);
    289367        return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    290368    }
     
    296374            off++;
    297375        if (off == cchExpr)
    298             return dbgcEvalSubNum(pszExpr + 2, 8, pResult);
     376            return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 8, pResult);
    299377        return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    300378    }
     
    306384            off++;
    307385        if (off == cchExpr)
    308             return dbgcEvalSubNum(pszExpr + 2, 10, pResult);
     386            return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult);
    309387        return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    310388    }
     
    316394        off++;
    317395    if (off == cchExpr)
    318         return dbgcEvalSubNum(pszExpr, 16, pResult);
     396        return dbgcEvalSubNum(pszExpr, cchExpr, 16, pResult);
    319397    return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    320398}
     
    537615        } while (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')');
    538616    }
    539 
    540 #if 0  /* why was this needed? It'll screw up strings. */
    541     /* tabs to spaces */
    542     char *psz = pszExpr;
    543     while ((psz = strchr(psz, '\t')) != NULL)
    544         *psz = ' ';
    545 #endif
    546617
    547618    /*
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r41561 r41571  
    2020 *
    2121 * The debugger console is an early attempt to make some interactive
    22  * debugging facilities for the VirtualBox VMM. It was initially only
    23  * accessible thru a telnet session on debug builds. Later it was hastily
    24  * built into the VBoxDbg module with a very simple Qt wrapper around it.
    25  *
    26  * The debugger is optional and presently not built into release builds
    27  * of VirtualBox. It is therefore necessary to enclose code related to it
    28  * in \#ifdef VBOX_WITH_DEBUGGER blocks. This is mandatory for components
    29  * that register extenral commands.
    30  *
    31  *
    32  * @section sec_dbgc_op                 Operation (intentions)
    33  *
    34  * The console will process commands in a manner similar to the OS/2 and
    35  * windows kernel debuggers. This means ';' is a command separator and
    36  * that when possible we'll use the same command names as these two uses.
     22 * debugging facilities for the VirtualBox VMM.  It was initially only
     23 * accessible thru a telnet session in debug builds.  Later it was hastily built
     24 * into the VBoxDbg module with a very simple Qt wrapper around it.
     25 *
     26 * The current state is that it's by default shipped with all standard
     27 * VirtualBox builds.  The GUI component is by default accessible in all
     28 * non-release builds, while release builds require extra data, environment or
     29 * command line options to make it visible.
     30 *
     31 * Now, even if we ship it with all standard builds we would like it to remain
     32 * an optional feature that can be omitted when building VirtualBox.  Therefore,
     33 * all external code interfacing DBGC need to be enclosed in
     34 * \#ifdef VBOX_WITH_DEBUGGER blocks. This is mandatory for components that
     35 * register external commands.
     36 *
     37 *
     38 * @section sec_dbgc_op                 Operation
     39 *
     40 * The console will process commands in a manner similar to the OS/2 and Windows
     41 * kernel debuggers.  This means ';' is a command separator and that when
     42 * possible we'll use the same command names as these two uses.  As an
     43 * alternative we intent to provide a set of gdb-like commands as well and let
     44 * the user decide which should take precedence.
    3745 *
    3846 *
     
    4250 * elsewise. Prefixes:
    4351 *      - '0x' - hexadecimal.
    44  *      - '0i' - decimal
     52 *      - '0n' - decimal
    4553 *      - '0t' - octal.
    4654 *      - '0y' - binary.
    4755 *
    48  * Some of the prefixes are a bit uncommon, the reason for this that
    49  * the typical binary prefix '0b' can also be a hexadecimal value since
    50  * no prefix or suffix is required for such values. Ditto for '0d' and
    51  * '0' for decimal and octal.
     56 * Some of the  prefixes are a bit uncommon, the reason for this that the
     57 * typical binary prefix '0b' can also be a hexadecimal value since no prefix or
     58 * suffix is required for such values. Ditto for '0n' and '0' for decimal and
     59 * octal.
     60 *
     61 * The '`' can be used in the numeric value to separate parts as the user
     62 * wishes.  Generally, though the debugger may use it in output as thousand
     63 * separator in decimal numbers and 32-bit separator in hex numbers.
     64 *
     65 * For historical reasons, a 'h' suffix is suffered on hex numbers.  Unlike most
     66 * assemblers, a leading 0 before a-f is not required with the 'h' suffix.
     67 *
     68 * The prefix '0i' can be used instead of '0n', as it was the early decimal
     69 * prefix employed by DBGC.  It's being deprecated and may be removed later.
     70 *
     71 *
     72 * @subsection sec_dbg_op_strings       Strings and Symbols
     73 *
     74 * The debugger will try to guess, convert or promote what the type of an
     75 * argument to a command, function or operator based on the input description of
     76 * the receiver.  If the user wants to make it clear to the debugger that
     77 * something is a string, put it inside double quotes.  Symbols should use
     78 * single quotes, though we're current still a bit flexible on this point.
     79 *
     80 * If you need to put a quote character inside the quoted text, you escape it by
     81 * repating it once: echo "printf(""hello world"");"
    5282 *
    5383 *
     
    6292 *
    6393 * The '%', '%%' and '#' prefixes is implemented as unary operators, while ':'
    64  * is a binary operator. Operator precedence takes care of evaluation order.
    65  *
    66  *
    67  * @subsection sec_dbg_op_evalution     Evaluation
    68  *
    69  * Most unary and binary C operators are supported, check the help text for
    70  * details. However, some of these are not yet implemented because this is
    71  * tiresome and annoying work. So, if something is missing and you need it
    72  * you implement it or complain to bird. (Ditto for missing functions.)
    73  *
    74  * Simple variable support is provided thru the 'set' and 'unset' commands and
    75  * the unary '$' operator.
    76  *
    77  * The unary '@' operator will indicate function calls. Commands and functions
    78  * are the same thing, except that functions has a return type.
     94 * is a binary operator.  Operator precedence takes care of evaluation order.
     95 *
     96 *
     97 * @subsection sec_dbg_op_c_operators   C/C++ Operators
     98 *
     99 * Most unary and binary arithmetic, comparison, logical and bitwise C/C++
     100 * operators are supported by the debugger, with the same precedence rules of
     101 * course.  There is one notable change made due to the unary '%' and '%%'
     102 * operators, and that is that the modulo (remainder) operator is called 'mod'
     103 * instead of '%'.  This saves a lot of trouble separating argument.
     104 *
     105 * There are no assignment operators.  Instead some simple global variable space
     106 * is provided thru the 'set' and 'unset' commands and the unary '$' operator.
    79107 *
    80108 *
    81109 * @subsection sec_dbg_op_registers     Registers
    82110 *
    83  * Registers are addressed using their name. Some registers which have several fields
    84  * (like gdtr) will have separate names indicating the different fields. The default
    85  * register set is the guest one. To access the hypervisor register one have to
    86  * prefix the register names with '.'.
    87  *
    88  * The registers are implemented as built-in symbols. For making gdb guys more at
    89  * home it is possible to access them with the '$' operator, i.e. as a variable.
    90  *
    91  *
    92  * @subsection sec_dbg_op_commands      Commands and Functions
    93  *
    94  * Commands and functions are the same thing, except that functions may return a
    95  * value. So, functions may be used as commands. The command/function handlers
    96  * can detect whether they are invoked as a command or function by checking whether
    97  * there is a return variable or not.
    98  *
    99  * The command/function names are all lowercase, case sensitive, and starting
    100  * with a letter. Operator characters are not permitted in the names of course.
    101  * Space is allowed, but must be flagged so the parser can check for multiple
    102  * spaces and tabs. (This feature is for 'dump xyz' and for emulating the
    103  * gdb 'info abc'.)
     111 * All registers and their sub-fields exposed by the DBGF API are accessible via
     112 * the '\@' operator.  A few CPU register are accessible directly (as symbols)
     113 * without using the '\@' operator.  Hypervisor registers are accessible by
     114 * prefixing the register name with a dot ('.').
     115 *
     116 *
     117 * @subsection sec_dbg_op_commands      Commands
     118 *
     119 * Commands names are case sensitive. By convention they are lower cased, starts
     120 * with a letter but may contain digits and underscores afterwards.  Operators
     121 * are not allowed in the name (not even part of it), as we would risk
     122 * misunderstanding it otherwise.
     123 *
     124 * Commands returns a status code.
    104125 *
    105126 * The '.' prefix indicates the set of external commands. External commands are
    106127 * command registered by VMM components.
     128 *
     129 *
     130 * @subsection sec_dbg_op_functions     Functions
     131 *
     132 * Functions are similar to commands, but return a variable and can only be used
     133 * as part of an expression making up the argument of a command, function,
     134 * operator or language statement (if we get around to implement that).
    107135 *
    108136 *
     
    114142 * (dbgcProcessLog and DBGC::fLog).
    115143 *
     144 * This feature has not materialized and probably never will.
    116145 *
    117146 *
    118147 * @section sec_dbgc_linking            Linking and API
    119148 *
    120  * The DBGC code is linked into the VBoxVMM module. (At present it is also
    121  * linked into VBoxDbg, but this is obviously very wrong.)
    122  *
    123  * A COM object will be created for the DBGC so it can be operated remotely
    124  * without using TCP. VBoxDbg is the intended audience for this usage. Some
    125  * questions about callbacks (for output) and security (you may wish to
    126  * restrict users from debugging a VM) needs to be answered first though.
     149 * The DBGC code is linked into the VBoxVMM module.
     150 *
     151 * IMachineDebugger may one day be extended with a DBGC interface so we can work
     152 * with DBGC remotely without requiring TCP.  Some questions about callbacks
     153 * (for output) and security (you may wish to restrict users from debugging a
     154 * VM) needs to be answered first though.
    127155 */
    128156
     
    218246            rc = dbgcOpRegister(pDbgc, &Var, DBGCVAR_CAT_ANY, pResult);
    219247            if (RT_SUCCESS(rc))
    220                 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, &Var, enmType, false /*fConvSyms*/, pResult);
     248                return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pResult, enmType, false /*fConvSyms*/, pResult);
    221249        }
    222250    }
  • trunk/src/VBox/Debugger/testcase/tstDBGCParser.cpp

    r41561 r41571  
    11401140    tstTry(pDbgc, "format nosuchfunction()\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND);
    11411141    tstTry(pDbgc, "format randu32()\n", VINF_SUCCESS);
     1142    tstTryEx(pDbgc, "format %0\n", VINF_SUCCESS, false, "Guest flat address: %00000000", -1);
     1143    tstTryEx(pDbgc, "format %eax\n", VINF_SUCCESS, false, "Guest flat address: %cafebabe", -1);
    11421144    tstTry(pDbgc, "sa 3 23 4 'q' \"21123123\" 'b' \n", VINF_SUCCESS);
    11431145    tstTry(pDbgc, "sa 3,23, 4,'q' ,\"21123123\" , 'b' \n", VINF_SUCCESS);
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