VirtualBox

Changeset 35628 in vbox


Ignore:
Timestamp:
Jan 19, 2011 2:58:26 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
69533
Message:

Debugger Console: Clean up, split the command evaluation code out of DBGConsole.cpp and into DBGCEval.cpp.

Location:
trunk/src/VBox/Debugger
Files:
11 edited
1 copied

Legend:

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

    r35625 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
  • trunk/src/VBox/Debugger/DBGCCmdHlp.cpp

    r35627 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2222#include <VBox/dbg.h>
    2323#include <VBox/vmm/dbgf.h>
    24 #include <VBox/vmm/vm.h>
    25 #include <VBox/vmm/vmm.h>
    26 #include <VBox/vmm/mm.h>
    2724#include <VBox/vmm/pgm.h>
    28 #include <VBox/vmm/selm.h>
    29 #include <VBox/dis.h>
    3025#include <VBox/param.h>
    3126#include <VBox/err.h>
    3227#include <VBox/log.h>
    3328
    34 #include <iprt/alloc.h>
    35 #include <iprt/alloca.h>
    36 #include <iprt/string.h>
    3729#include <iprt/assert.h>
    3830#include <iprt/ctype.h>
     31#include <iprt/mem.h>
     32#include <iprt/string.h>
    3933
    4034#include "DBGCInternal.h"
     
    655649     */
    656650    pDbgc->pszScratch = pDbgc->pszScratch + cb + 1;
    657     int rc = dbgcProcessCommand(pDbgc, pszScratch, cb, false /* fNoExecute */);
     651    int rc = dbgcEvalCommand(pDbgc, pszScratch, cb, false /* fNoExecute */);
    658652
    659653    /* Restore the scratch state. */
  • trunk/src/VBox/Debugger/DBGCCmdWorkers.cpp

    r35626 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2222#include <VBox/dbg.h>
    2323#include <VBox/vmm/dbgf.h>
    24 #include <VBox/vmm/vm.h>
    25 #include <VBox/vmm/vmm.h>
    26 #include <VBox/vmm/mm.h>
    27 #include <VBox/vmm/pgm.h>
    28 #include <VBox/vmm/selm.h>
    29 #include <VBox/dis.h>
    3024#include <VBox/param.h>
    3125#include <VBox/err.h>
     
    3327
    3428#include <iprt/alloc.h>
    35 #include <iprt/alloca.h>
    3629#include <iprt/string.h>
    3730#include <iprt/assert.h>
    38 #include <iprt/ctype.h>
    3931
    4032#include "DBGCInternal.h"
     
    383375 * @returns VERR_DBGC_BP_NOT_FOUND if the breakpoint wasn't found.
    384376 * @returns VERR_BUFFER_OVERFLOW if the is not enough space in the scratch buffer for the command.
    385  * @returns VBox status code from dbgcProcessCommand() other wise.
     377 * @returns VBox status code from dbgcEvalCommand() other wise.
    386378 * @param   pDbgc       The DBGC instance.
    387379 * @param   iBp         The breakpoint to execute.
     
    419411    /* Execute the command. */
    420412    pDbgc->pszScratch = pDbgc->pszScratch + pBp->cchCmd + 1;
    421     int rc = dbgcProcessCommand(pDbgc, pszScratch, pBp->cchCmd, false /* fNoExecute */);
     413    int rc = dbgcEvalCommand(pDbgc, pszScratch, pBp->cchCmd, false /* fNoExecute */);
    422414
    423415    /* Restore the scratch state. */
  • trunk/src/VBox/Debugger/DBGCCommands.cpp

    r35626 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2323#include <VBox/vmm/dbgf.h>
    2424#include <VBox/vmm/vm.h>
    25 #include <VBox/vmm/vmm.h>
    26 #include <VBox/vmm/mm.h>
    27 #include <VBox/vmm/pgm.h>
    28 #include <VBox/vmm/selm.h>
    29 #include <VBox/dis.h>
    3025#include <VBox/param.h>
    3126#include <VBox/err.h>
     
    734729        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "parser error\n");
    735730
     731    /** @todo Load the script here, but someone else should do the actual
     732     *        evaluation and execution of it.  */
     733
    736734    /*
    737735     * Try open the script.
     
    867865    else
    868866    {
     867/** @todo add a DBGF getter for this. */
    869868        if (paArgs[0].u.u64Number >= pVM->cCpus)
    870869            rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: idCpu %u is out of range! Highest ID is %u.\n",
     
    909908     * Dump it.
    910909     */
     910    /** @todo DBGFR3Info should do this, not we. */
    911911    int rc = VMR3ReqCallWait(pVM, pDbgc->idCpu, (PFNRT)DBGFR3Info, 4,
    912912                             pVM, paArgs[0].u.pszString, cArgs == 2 ? paArgs[1].u.pszString : NULL,
  • trunk/src/VBox/Debugger/DBGCEmulateCodeView.cpp

    r35626 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2323#include <VBox/vmm/dbgf.h>
    2424#include <VBox/vmm/pgm.h>
    25 #include <VBox/vmm/selm.h>
    2625#include <VBox/vmm/cpum.h>
    2726#include <VBox/dis.h>
     
    3130
    3231#include <iprt/asm.h>
    33 #include <iprt/alloca.h>
    3432#include <iprt/mem.h>
    3533#include <iprt/string.h>
  • trunk/src/VBox/Debugger/DBGCEval.cpp

    r35627 r35628  
    11/* $Id$ */
    22/** @file
    3  * DBGC - Debugger Console.
     3 * DBGC - Debugger Console, command evaluator.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 */
    1717
    18 
    19 /** @page pg_dbgc                       DBGC - The Debug Console
    20  *
    21  * 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.
    37  *
    38  *
    39  * @subsection sec_dbg_op_numbers       Numbers
    40  *
    41  * Numbers are hexadecimal unless specified with a prefix indicating
    42  * elsewise. Prefixes:
    43  *      - '0x' - hexadecimal.
    44  *      - '0i' - decimal
    45  *      - '0t' - octal.
    46  *      - '0y' - binary.
    47  *
    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.
    52  *
    53  *
    54  * @subsection sec_dbg_op_address       Addressing modes
    55  *
    56  *      - Default is flat. For compatibility '%' also means flat.
    57  *      - Segmented addresses are specified selector:offset.
    58  *      - Physical addresses are specified using '%%'.
    59  *      - The default target for the addressing is the guest context, the '#'
    60  *        will override this and set it to the host.
    61  *        Note that several operations won't work on host addresses.
    62  *
    63  * 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.
    79  *
    80  *
    81  * @subsection sec_dbg_op_registers     Registers
    82  *
    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'.)
    104  *
    105  * The '.' prefix indicates the set of external commands. External commands are
    106  * command registered by VMM components.
    107  *
    108  *
    109  * @section sec_dbgc_logging            Logging
    110  *
    111  * The idea is to be able to pass thru debug and release logs to the console
    112  * if the user so wishes. This feature requires some kind of hook into the
    113  * logger instance and while this was sketched it hasn't yet been implemented
    114  * (dbgcProcessLog and DBGC::fLog).
    115  *
    116  *
    117  *
    118  * @section sec_dbgc_linking            Linking and API
    119  *
    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.
    127  */
    128 
    129 
    13018/*******************************************************************************
    13119*   Header Files                                                               *
     
    13321#define LOG_GROUP LOG_GROUP_DBGC
    13422#include <VBox/dbg.h>
    135 #include <VBox/vmm/dbgf.h>
    136 #include <VBox/vmm/vm.h>
    137 #include <VBox/vmm/vmm.h>
    138 #include <VBox/vmm/mm.h>
    139 #include <VBox/vmm/pgm.h>
    140 #include <VBox/vmm/selm.h>
    141 #include <VBox/dis.h>
    142 #include <VBox/param.h>
    14323#include <VBox/err.h>
    14424#include <VBox/log.h>
    14525
    14626#include <iprt/asm.h>
    147 #include <iprt/alloca.h>
    14827#include <iprt/assert.h>
    149 #include <iprt/mem.h>
    15028#include <iprt/string.h>
    15129#include <iprt/ctype.h>
    15230
    153 #include <stdlib.h>
    154 #include <stdio.h>
    155 
    15631#include "DBGCInternal.h"
    157 #include "DBGPlugIns.h"
    15832
    15933
     
    16539
    16640
    167 /*******************************************************************************
    168 *   Internal Functions                                                         *
    169 *******************************************************************************/
    170 static int dbgcProcessLog(PDBGC pDbgc);
    171 
    172 
    17341
    17442/**
    17543 * Initializes g_bmOperatorChars.
    17644 */
    177 static void dbgcInitOpCharBitMap(void)
     45void dbgcEvalInit(void)
    17846{
    17947    memset(g_bmOperatorChars, 0, sizeof(g_bmOperatorChars));
     
    19260{
    19361    return ASMBitTest(&g_bmOperatorChars[0], (uint8_t)ch);
    194 }
    195 
    196 
    197 /**
    198  * Resolves a symbol (or tries to do so at least).
    199  *
    200  * @returns 0 on success.
    201  * @returns VBox status on failure.
    202  * @param   pDbgc       The debug console instance.
    203  * @param   pszSymbol   The symbol name.
    204  * @param   enmType     The result type.  Specifying DBGCVAR_TYPE_GC_FAR may
    205  *                      cause failure, avoid it.
    206  * @param   pResult     Where to store the result.
    207  */
    208 int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGCVAR pResult)
    209 {
    210     int rc;
    211 
    212     /*
    213      * Builtin?
    214      */
    215     PCDBGCSYM pSymDesc = dbgcLookupRegisterSymbol(pDbgc, pszSymbol);
    216     if (pSymDesc)
    217     {
    218         if (!pSymDesc->pfnGet)
    219             return VERR_PARSE_WRITEONLY_SYMBOL;
    220         return pSymDesc->pfnGet(pSymDesc, &pDbgc->CmdHlp, enmType, pResult);
    221     }
    222 
    223     /*
    224      * A typical register? (Guest only)
    225      */
    226     static const char s_szSixLetterRegisters[] =
    227         "rflags;eflags;"
    228     ;
    229     static const char s_szThreeLetterRegisters[] =
    230         "eax;rax;"     "r10;" "r8d;r8w;r8b;"  "cr0;"  "dr0;"
    231         "ebx;rbx;"     "r11;" "r9d;r9w;r8b;"          "dr1;"
    232         "ecx;rcx;"     "r12;"                 "cr2;"  "dr2;"
    233         "edx;rdx;"     "r13;"                 "cr3;"  "dr3;"
    234         "edi;rdi;dil;" "r14;"                 "cr4;"  "dr4;"
    235         "esi;rsi;sil;" "r15;"                 "cr8;"
    236         "ebp;rbp;"
    237         "esp;rsp;"                                    "dr6;"
    238         "rip;eip;"                                    "dr7;"
    239         "efl;"
    240     ;
    241     static const char s_szTwoLetterRegisters[] =
    242         "ax;al;ah;"           "r8;"
    243         "bx;bl;bh;"           "r9;"
    244         "cx;cl;ch;"    "cs;"
    245         "dx;dl;dh;"    "ds;"
    246         "di;"          "es;"
    247         "si;"          "fs;"
    248         "bp;"          "gs;"
    249         "sp;"          "ss;"
    250         "ip;"
    251     ;
    252     size_t const cchSymbol = strlen(pszSymbol);
    253     if (    (cchSymbol == 2 && strstr(s_szTwoLetterRegisters,   pszSymbol))
    254         ||  (cchSymbol == 3 && strstr(s_szThreeLetterRegisters, pszSymbol))
    255         ||  (cchSymbol == 6 && strstr(s_szSixLetterRegisters,   pszSymbol)))
    256     {
    257         if (!strchr(pszSymbol, ';'))
    258         {
    259             DBGCVAR Var;
    260             DBGCVAR_INIT_STRING(&Var, pszSymbol);
    261             rc = dbgcOpRegister(pDbgc, &Var, pResult);
    262             if (RT_SUCCESS(rc))
    263                 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, &Var, enmType, false /*fConvSyms*/, pResult);
    264         }
    265     }
    266 
    267     /*
    268      * Ask PDM.
    269      */
    270     /** @todo resolve symbols using PDM. */
    271 
    272     /*
    273      * Ask the debug info manager.
    274      */
    275     RTDBGSYMBOL Symbol;
    276     rc = DBGFR3AsSymbolByName(pDbgc->pVM, pDbgc->hDbgAs, pszSymbol, &Symbol, NULL);
    277     if (RT_SUCCESS(rc))
    278     {
    279         /*
    280          * Default return is a flat gc address.
    281          */
    282         DBGCVAR_INIT_GC_FLAT(pResult, Symbol.Value);
    283         if (Symbol.cb)
    284             DBGCVAR_SET_RANGE(pResult, DBGCVAR_RANGE_BYTES, Symbol.cb);
    285 
    286         switch (enmType)
    287         {
    288             /* nothing to do. */
    289             case DBGCVAR_TYPE_GC_FLAT:
    290             case DBGCVAR_TYPE_ANY:
    291                 return VINF_SUCCESS;
    292 
    293             /* impossible at the moment. */
    294             case DBGCVAR_TYPE_GC_FAR:
    295                 return VERR_PARSE_CONVERSION_FAILED;
    296 
    297             /* simply make it numeric. */
    298             case DBGCVAR_TYPE_NUMBER:
    299                 pResult->enmType = DBGCVAR_TYPE_NUMBER;
    300                 pResult->u.u64Number = Symbol.Value;
    301                 return VINF_SUCCESS;
    302 
    303             /* cast it. */
    304             case DBGCVAR_TYPE_GC_PHYS:
    305             case DBGCVAR_TYPE_HC_FLAT:
    306             case DBGCVAR_TYPE_HC_PHYS:
    307                 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pResult, enmType, false /*fConvSyms*/, pResult);
    308 
    309             default:
    310                 AssertMsgFailed(("Internal error enmType=%d\n", enmType));
    311                 return VERR_INVALID_PARAMETER;
    312         }
    313     }
    314 
    315     return VERR_PARSE_NOT_IMPLEMENTED;
    31662}
    31763
     
    1237983
    1238984/**
    1239  * Process one command.
     985 * Evaluate one command.
    1240986 *
    1241987 * @returns VBox status code. Any error indicates the termination of the console session.
     988 *
    1242989 * @param   pDbgc       Debugger console instance data.
    1243990 * @param   pszCmd      Pointer to the command.
    1244991 * @param   cchCmd      Length of the command.
    1245992 * @param   fNoExecute  Indicates that no commands should actually be executed.
     993 * @todo    Change pszCmd into argc/argv?
    1246994 */
    1247 int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd, bool fNoExecute)
     995int dbgcEvalCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd, bool fNoExecute)
    1248996{
    1249997    char *pszCmdInput = pszCmd;
     
    14041152}
    14051153
    1406 
    1407 /**
    1408  * Process all commands currently in the buffer.
    1409  *
    1410  * @returns VBox status code. Any error indicates the termination of the console session.
    1411  * @param   pDbgc       Debugger console instance data.
    1412  * @param   fNoExecute  Indicates that no commands should actually be executed.
    1413  */
    1414 static int dbgcProcessCommands(PDBGC pDbgc, bool fNoExecute)
    1415 {
    1416     /** @todo Replace this with a sh/ksh/csh/rexx like toplevel language that
    1417      *        allows doing function, loops, if, cases, and such. */
    1418     int rc = 0;
    1419     while (pDbgc->cInputLines)
    1420     {
    1421         /*
    1422          * Empty the log buffer if we're hooking the log.
    1423          */
    1424         if (pDbgc->fLog)
    1425         {
    1426             rc = dbgcProcessLog(pDbgc);
    1427             if (RT_FAILURE(rc))
    1428                 break;
    1429         }
    1430 
    1431         if (pDbgc->iRead == pDbgc->iWrite)
    1432         {
    1433             AssertMsgFailed(("The input buffer is empty while cInputLines=%d!\n", pDbgc->cInputLines));
    1434             pDbgc->cInputLines = 0;
    1435             return 0;
    1436         }
    1437 
    1438         /*
    1439          * Copy the command to the parse buffer.
    1440          */
    1441         char    ch;
    1442         char   *psz = &pDbgc->achInput[pDbgc->iRead];
    1443         char   *pszTrg = &pDbgc->achScratch[0];
    1444         while ((*pszTrg = ch = *psz++) != ';' && ch != '\n' )
    1445         {
    1446             if (psz == &pDbgc->achInput[sizeof(pDbgc->achInput)])
    1447                 psz = &pDbgc->achInput[0];
    1448 
    1449             if (psz == &pDbgc->achInput[pDbgc->iWrite])
    1450             {
    1451                 AssertMsgFailed(("The buffer contains no commands while cInputLines=%d!\n", pDbgc->cInputLines));
    1452                 pDbgc->cInputLines = 0;
    1453                 return 0;
    1454             }
    1455 
    1456             pszTrg++;
    1457         }
    1458         *pszTrg = '\0';
    1459 
    1460         /*
    1461          * Advance the buffer.
    1462          */
    1463         pDbgc->iRead = psz - &pDbgc->achInput[0];
    1464         if (ch == '\n')
    1465             pDbgc->cInputLines--;
    1466 
    1467         /*
    1468          * Parse and execute this command.
    1469          */
    1470         pDbgc->pszScratch = psz;
    1471         pDbgc->iArg       = 0;
    1472         rc = dbgcProcessCommand(pDbgc, &pDbgc->achScratch[0], psz - &pDbgc->achScratch[0] - 1, fNoExecute);
    1473         if (rc)
    1474             break;
    1475     }
    1476 
    1477     return rc;
    1478 }
    1479 
    1480 
    1481 /**
    1482  * Handle input buffer overflow.
    1483  *
    1484  * Will read any available input looking for a '\n' to reset the buffer on.
    1485  *
    1486  * @returns VBox status.
    1487  * @param   pDbgc   Debugger console instance data.
    1488  */
    1489 static int dbgcInputOverflow(PDBGC pDbgc)
    1490 {
    1491     /*
    1492      * Assert overflow status and reset the input buffer.
    1493      */
    1494     if (!pDbgc->fInputOverflow)
    1495     {
    1496         pDbgc->fInputOverflow = true;
    1497         pDbgc->iRead = pDbgc->iWrite = 0;
    1498         pDbgc->cInputLines = 0;
    1499         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Input overflow!!\n");
    1500     }
    1501 
    1502     /*
    1503      * Eat input till no more or there is a '\n'.
    1504      * When finding a '\n' we'll continue normal processing.
    1505      */
    1506     while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0))
    1507     {
    1508         size_t cbRead;
    1509         int rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &pDbgc->achInput[0], sizeof(pDbgc->achInput) - 1, &cbRead);
    1510         if (RT_FAILURE(rc))
    1511             return rc;
    1512         char *psz = (char *)memchr(&pDbgc->achInput[0], '\n', cbRead);
    1513         if (psz)
    1514         {
    1515             pDbgc->fInputOverflow = false;
    1516             pDbgc->iRead = psz - &pDbgc->achInput[0] + 1;
    1517             pDbgc->iWrite = (unsigned)cbRead;
    1518             pDbgc->cInputLines = 0;
    1519             break;
    1520         }
    1521     }
    1522 
    1523     return 0;
    1524 }
    1525 
    1526 
    1527 /**
    1528  * Read input and do some preprocessing.
    1529  *
    1530  * @returns VBox status.
    1531  *          In addition to the iWrite and achInput, cInputLines is maintained.
    1532  *          In case of an input overflow the fInputOverflow flag will be set.
    1533  * @param   pDbgc   Debugger console instance data.
    1534  */
    1535 static int dbgcInputRead(PDBGC pDbgc)
    1536 {
    1537     /*
    1538      * We have ready input.
    1539      * Read it till we don't have any or we have a full input buffer.
    1540      */
    1541     int     rc = 0;
    1542     do
    1543     {
    1544         /*
    1545          * More available buffer space?
    1546          */
    1547         size_t cbLeft;
    1548         if (pDbgc->iWrite > pDbgc->iRead)
    1549             cbLeft = sizeof(pDbgc->achInput) - pDbgc->iWrite - (pDbgc->iRead == 0);
    1550         else
    1551             cbLeft = pDbgc->iRead - pDbgc->iWrite - 1;
    1552         if (!cbLeft)
    1553         {
    1554             /* overflow? */
    1555             if (!pDbgc->cInputLines)
    1556                 rc = dbgcInputOverflow(pDbgc);
    1557             break;
    1558         }
    1559 
    1560         /*
    1561          * Read one char and interpret it.
    1562          */
    1563         char    achRead[128];
    1564         size_t  cbRead;
    1565         rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &achRead[0], RT_MIN(cbLeft, sizeof(achRead)), &cbRead);
    1566         if (RT_FAILURE(rc))
    1567             return rc;
    1568         char *psz = &achRead[0];
    1569         while (cbRead-- > 0)
    1570         {
    1571             char ch = *psz++;
    1572             switch (ch)
    1573             {
    1574                 /*
    1575                  * Ignore.
    1576                  */
    1577                 case '\0':
    1578                 case '\r':
    1579                 case '\a':
    1580                     break;
    1581 
    1582                 /*
    1583                  * Backspace.
    1584                  */
    1585                 case '\b':
    1586                     Log2(("DBGC: backspace\n"));
    1587                     if (pDbgc->iRead != pDbgc->iWrite)
    1588                     {
    1589                         unsigned iWriteUndo = pDbgc->iWrite;
    1590                         if (pDbgc->iWrite)
    1591                             pDbgc->iWrite--;
    1592                         else
    1593                             pDbgc->iWrite = sizeof(pDbgc->achInput) - 1;
    1594 
    1595                         if (pDbgc->achInput[pDbgc->iWrite] == '\n')
    1596                             pDbgc->iWrite = iWriteUndo;
    1597                     }
    1598                     break;
    1599 
    1600                 /*
    1601                  * Add char to buffer.
    1602                  */
    1603                 case '\t':
    1604                 case '\n':
    1605                 case ';':
    1606                     switch (ch)
    1607                     {
    1608                         case '\t': ch = ' '; break;
    1609                         case '\n': pDbgc->cInputLines++; break;
    1610                     }
    1611                 default:
    1612                     Log2(("DBGC: ch=%02x\n", (unsigned char)ch));
    1613                     pDbgc->achInput[pDbgc->iWrite] = ch;
    1614                     if (++pDbgc->iWrite >= sizeof(pDbgc->achInput))
    1615                         pDbgc->iWrite = 0;
    1616                     break;
    1617             }
    1618         }
    1619 
    1620         /* Terminate it to make it easier to read in the debugger. */
    1621         pDbgc->achInput[pDbgc->iWrite] = '\0';
    1622     } while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0));
    1623 
    1624     return rc;
    1625 }
    1626 
    1627 
    1628 /**
    1629  * Reads input, parses it and executes commands on '\n'.
    1630  *
    1631  * @returns VBox status.
    1632  * @param   pDbgc       Debugger console instance data.
    1633  * @param   fNoExecute  Indicates that no commands should actually be executed.
    1634  */
    1635 int dbgcProcessInput(PDBGC pDbgc, bool fNoExecute)
    1636 {
    1637     /*
    1638      * We know there's input ready, so let's read it first.
    1639      */
    1640     int rc = dbgcInputRead(pDbgc);
    1641     if (RT_FAILURE(rc))
    1642         return rc;
    1643 
    1644     /*
    1645      * Now execute any ready commands.
    1646      */
    1647     if (pDbgc->cInputLines)
    1648     {
    1649         pDbgc->pBack->pfnSetReady(pDbgc->pBack, false);
    1650         pDbgc->fReady = false;
    1651         rc = dbgcProcessCommands(pDbgc, fNoExecute);
    1652         if (RT_SUCCESS(rc) && rc != VWRN_DBGC_CMD_PENDING)
    1653             pDbgc->fReady = true;
    1654 
    1655         if (    RT_SUCCESS(rc)
    1656             &&  pDbgc->iRead == pDbgc->iWrite
    1657             &&  pDbgc->fReady)
    1658             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");
    1659 
    1660         if (    RT_SUCCESS(rc)
    1661             &&  pDbgc->fReady)
    1662             pDbgc->pBack->pfnSetReady(pDbgc->pBack, true);
    1663     }
    1664     else
    1665         /* Received nonsense; just skip it. */
    1666         pDbgc->iRead = pDbgc->iWrite;
    1667 
    1668     return rc;
    1669 }
    1670 
    1671 
    1672 /**
    1673  * Gets the event context identifier string.
    1674  * @returns Read only string.
    1675  * @param   enmCtx          The context.
    1676  */
    1677 static const char *dbgcGetEventCtx(DBGFEVENTCTX enmCtx)
    1678 {
    1679     switch (enmCtx)
    1680     {
    1681         case DBGFEVENTCTX_RAW:      return "raw";
    1682         case DBGFEVENTCTX_REM:      return "rem";
    1683         case DBGFEVENTCTX_HWACCL:   return "hwaccl";
    1684         case DBGFEVENTCTX_HYPER:    return "hyper";
    1685         case DBGFEVENTCTX_OTHER:    return "other";
    1686 
    1687         case DBGFEVENTCTX_INVALID:  return "!Invalid Event Ctx!";
    1688         default:
    1689             AssertMsgFailed(("enmCtx=%d\n", enmCtx));
    1690             return "!Unknown Event Ctx!";
    1691     }
    1692 }
    1693 
    1694 
    1695 /**
    1696  * Processes debugger events.
    1697  *
    1698  * @returns VBox status.
    1699  * @param   pDbgc   DBGC Instance data.
    1700  * @param   pEvent  Pointer to event data.
    1701  */
    1702 static int dbgcProcessEvent(PDBGC pDbgc, PCDBGFEVENT pEvent)
    1703 {
    1704     /*
    1705      * Flush log first.
    1706      */
    1707     if (pDbgc->fLog)
    1708     {
    1709         int rc = dbgcProcessLog(pDbgc);
    1710         if (RT_FAILURE(rc))
    1711             return rc;
    1712     }
    1713 
    1714     /*
    1715      * Process the event.
    1716      */
    1717     pDbgc->pszScratch = &pDbgc->achInput[0];
    1718     pDbgc->iArg       = 0;
    1719     bool fPrintPrompt = true;
    1720     int rc = VINF_SUCCESS;
    1721     switch (pEvent->enmType)
    1722     {
    1723         /*
    1724          * The first part is events we have initiated with commands.
    1725          */
    1726         case DBGFEVENT_HALT_DONE:
    1727         {
    1728             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: VM %p is halted! (%s)\n",
    1729                                          pDbgc->pVM, dbgcGetEventCtx(pEvent->enmCtx));
    1730             pDbgc->fRegCtxGuest = true; /* we're always in guest context when halted. */
    1731             if (RT_SUCCESS(rc))
    1732                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    1733             break;
    1734         }
    1735 
    1736 
    1737         /*
    1738          * The second part is events which can occur at any time.
    1739          */
    1740         case DBGFEVENT_FATAL_ERROR:
    1741         {
    1742             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
    1743                                          dbgcGetEventCtx(pEvent->enmCtx));
    1744             pDbgc->fRegCtxGuest = false; /* fatal errors are always in hypervisor. */
    1745             if (RT_SUCCESS(rc))
    1746                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    1747             break;
    1748         }
    1749 
    1750         case DBGFEVENT_BREAKPOINT:
    1751         case DBGFEVENT_BREAKPOINT_HYPER:
    1752         {
    1753             bool fRegCtxGuest = pDbgc->fRegCtxGuest;
    1754             pDbgc->fRegCtxGuest = pEvent->enmType == DBGFEVENT_BREAKPOINT;
    1755 
    1756             rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp);
    1757             switch (rc)
    1758             {
    1759                 case VERR_DBGC_BP_NOT_FOUND:
    1760                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
    1761                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    1762                     break;
    1763 
    1764                 case VINF_DBGC_BP_NO_COMMAND:
    1765                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
    1766                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    1767                     break;
    1768 
    1769                 case VINF_BUFFER_OVERFLOW:
    1770                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
    1771                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    1772                     break;
    1773 
    1774                 default:
    1775                     break;
    1776             }
    1777             if (RT_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pVM))
    1778                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    1779             else
    1780                 pDbgc->fRegCtxGuest = fRegCtxGuest;
    1781             break;
    1782         }
    1783 
    1784         case DBGFEVENT_STEPPED:
    1785         case DBGFEVENT_STEPPED_HYPER:
    1786         {
    1787             pDbgc->fRegCtxGuest = pEvent->enmType == DBGFEVENT_STEPPED;
    1788 
    1789             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Single step! (%s)\n", dbgcGetEventCtx(pEvent->enmCtx));
    1790             if (RT_SUCCESS(rc))
    1791                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    1792             break;
    1793         }
    1794 
    1795         case DBGFEVENT_ASSERTION_HYPER:
    1796         {
    1797             pDbgc->fRegCtxGuest = false;
    1798 
    1799             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1800                                          "\ndbgf event: Hypervisor Assertion! (%s)\n"
    1801                                          "%s"
    1802                                          "%s"
    1803                                          "\n",
    1804                                          dbgcGetEventCtx(pEvent->enmCtx),
    1805                                          pEvent->u.Assert.pszMsg1,
    1806                                          pEvent->u.Assert.pszMsg2);
    1807             if (RT_SUCCESS(rc))
    1808                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    1809             break;
    1810         }
    1811 
    1812         case DBGFEVENT_DEV_STOP:
    1813         {
    1814             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1815                                          "\n"
    1816                                          "dbgf event: DBGFSTOP (%s)\n"
    1817                                          "File:     %s\n"
    1818                                          "Line:     %d\n"
    1819                                          "Function: %s\n",
    1820                                          dbgcGetEventCtx(pEvent->enmCtx),
    1821                                          pEvent->u.Src.pszFile,
    1822                                          pEvent->u.Src.uLine,
    1823                                          pEvent->u.Src.pszFunction);
    1824             if (RT_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
    1825                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1826                                              "Message:  %s\n",
    1827                                              pEvent->u.Src.pszMessage);
    1828             if (RT_SUCCESS(rc))
    1829                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    1830             break;
    1831         }
    1832 
    1833 
    1834         case DBGFEVENT_INVALID_COMMAND:
    1835         {
    1836             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
    1837             break;
    1838         }
    1839 
    1840         case DBGFEVENT_TERMINATING:
    1841         {
    1842             pDbgc->fReady = false;
    1843             pDbgc->pBack->pfnSetReady(pDbgc->pBack, false);
    1844             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nVM is terminating!\n");
    1845             fPrintPrompt = false;
    1846             rc = VERR_GENERAL_FAILURE;
    1847             break;
    1848         }
    1849 
    1850 
    1851         default:
    1852         {
    1853             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
    1854             break;
    1855         }
    1856     }
    1857 
    1858     /*
    1859      * Prompt, anyone?
    1860      */
    1861     if (fPrintPrompt && RT_SUCCESS(rc))
    1862     {
    1863         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");
    1864         pDbgc->fReady = true;
    1865         if (RT_SUCCESS(rc))
    1866             pDbgc->pBack->pfnSetReady(pDbgc->pBack, true);
    1867     }
    1868 
    1869     return rc;
    1870 }
    1871 
    1872 
    1873 /**
    1874  * Prints any log lines from the log buffer.
    1875  *
    1876  * The caller must not call function this unless pDbgc->fLog is set.
    1877  *
    1878  * @returns VBox status. (output related)
    1879  * @param   pDbgc   Debugger console instance data.
    1880  */
    1881 static int dbgcProcessLog(PDBGC pDbgc)
    1882 {
    1883     /** @todo */
    1884     NOREF(pDbgc);
    1885     return 0;
    1886 }
    1887 
    1888 
    1889 /**
    1890  * Run the debugger console.
    1891  *
    1892  * @returns VBox status.
    1893  * @param   pDbgc   Pointer to the debugger console instance data.
    1894  */
    1895 int dbgcRun(PDBGC pDbgc)
    1896 {
    1897     /*
    1898      * We're ready for commands now.
    1899      */
    1900     pDbgc->fReady = true;
    1901     pDbgc->pBack->pfnSetReady(pDbgc->pBack, true);
    1902 
    1903     /*
    1904      * Main Debugger Loop.
    1905      *
    1906      * This loop will either block on waiting for input or on waiting on
    1907      * debug events. If we're forwarding the log we cannot wait for long
    1908      * before we must flush the log.
    1909      */
    1910     int rc = VINF_SUCCESS;
    1911     for (;;)
    1912     {
    1913         if (    pDbgc->pVM
    1914             &&  DBGFR3CanWait(pDbgc->pVM))
    1915         {
    1916             /*
    1917              * Wait for a debug event.
    1918              */
    1919             PCDBGFEVENT pEvent;
    1920             rc = DBGFR3EventWait(pDbgc->pVM, pDbgc->fLog ? 1 : 32, &pEvent);
    1921             if (RT_SUCCESS(rc))
    1922             {
    1923                 rc = dbgcProcessEvent(pDbgc, pEvent);
    1924                 if (RT_FAILURE(rc))
    1925                     break;
    1926             }
    1927             else if (rc != VERR_TIMEOUT)
    1928                 break;
    1929 
    1930             /*
    1931              * Check for input.
    1932              */
    1933             if (pDbgc->pBack->pfnInput(pDbgc->pBack, 0))
    1934             {
    1935                 rc = dbgcProcessInput(pDbgc, false /* fNoExecute */);
    1936                 if (RT_FAILURE(rc))
    1937                     break;
    1938             }
    1939         }
    1940         else
    1941         {
    1942             /*
    1943              * Wait for input. If Logging is enabled we'll only wait very briefly.
    1944              */
    1945             if (pDbgc->pBack->pfnInput(pDbgc->pBack, pDbgc->fLog ? 1 : 1000))
    1946             {
    1947                 rc = dbgcProcessInput(pDbgc, false /* fNoExecute */);
    1948                 if (RT_FAILURE(rc))
    1949                     break;
    1950             }
    1951         }
    1952 
    1953         /*
    1954          * Forward log output.
    1955          */
    1956         if (pDbgc->fLog)
    1957         {
    1958             rc = dbgcProcessLog(pDbgc);
    1959             if (RT_FAILURE(rc))
    1960                 break;
    1961         }
    1962     }
    1963 
    1964     return rc;
    1965 }
    1966 
    1967 
    1968 /**
    1969  * Creates a a new instance.
    1970  *
    1971  * @returns VBox status code.
    1972  * @param   ppDbgc      Where to store the pointer to the instance data.
    1973  * @param   pBack       Pointer to the backend.
    1974  * @param   fFlags      The flags.
    1975  */
    1976 int dbgcCreate(PDBGC *ppDbgc, PDBGCBACK pBack, unsigned fFlags)
    1977 {
    1978     /*
    1979      * Validate input.
    1980      */
    1981     AssertPtrReturn(pBack, VERR_INVALID_POINTER);
    1982     AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
    1983 
    1984     /*
    1985      * Allocate and initialize.
    1986      */
    1987     PDBGC pDbgc = (PDBGC)RTMemAllocZ(sizeof(*pDbgc));
    1988     if (!pDbgc)
    1989         return VERR_NO_MEMORY;
    1990 
    1991     dbgcInitCmdHlp(pDbgc);
    1992     pDbgc->pBack            = pBack;
    1993     pDbgc->pVM              = NULL;
    1994     pDbgc->idCpu            = NIL_VMCPUID;
    1995     pDbgc->hDbgAs           = DBGF_AS_GLOBAL;
    1996     pDbgc->pszEmulation     = "CodeView/WinDbg";
    1997     pDbgc->paEmulationCmds  = &g_aCmdsCodeView[0];
    1998     pDbgc->cEmulationCmds   = g_cCmdsCodeView;
    1999     //pDbgc->fLog             = false;
    2000     pDbgc->fRegCtxGuest     = true;
    2001     pDbgc->fRegTerse        = true;
    2002     //pDbgc->cPagingHierarchyDumps = 0;
    2003     //pDbgc->DisasmPos        = {0};
    2004     //pDbgc->SourcePos        = {0};
    2005     //pDbgc->DumpPos          = {0};
    2006     pDbgc->pLastPos          = &pDbgc->DisasmPos;
    2007     //pDbgc->cbDumpElement    = 0;
    2008     //pDbgc->cVars            = 0;
    2009     //pDbgc->paVars           = NULL;
    2010     //pDbgc->pPlugInHead      = NULL;
    2011     //pDbgc->pFirstBp         = NULL;
    2012     //pDbgc->abSearch         = {0};
    2013     //pDbgc->cbSearch         = 0;
    2014     pDbgc->cbSearchUnit       = 1;
    2015     pDbgc->cMaxSearchHits     = 1;
    2016     //pDbgc->SearchAddr       = {0};
    2017     //pDbgc->cbSearchRange    = 0;
    2018 
    2019     //pDbgc->uInputZero       = 0;
    2020     //pDbgc->iRead            = 0;
    2021     //pDbgc->iWrite           = 0;
    2022     //pDbgc->cInputLines      = 0;
    2023     //pDbgc->fInputOverflow   = false;
    2024     pDbgc->fReady           = true;
    2025     pDbgc->pszScratch       = &pDbgc->achScratch[0];
    2026     //pDbgc->iArg             = 0;
    2027     //pDbgc->rcOutput         = 0;
    2028     //pDbgc->rcCmd            = 0;
    2029 
    2030     dbgcInitOpCharBitMap();
    2031 
    2032     *ppDbgc = pDbgc;
    2033     return VINF_SUCCESS;
    2034 }
    2035 
    2036 /**
    2037  * Destroys a DBGC instance created by dbgcCreate.
    2038  *
    2039  * @param   pDbgc   Pointer to the debugger console instance data.
    2040  */
    2041 void dbgcDestroy(PDBGC pDbgc)
    2042 {
    2043     AssertPtr(pDbgc);
    2044 
    2045     /* Disable log hook. */
    2046     if (pDbgc->fLog)
    2047     {
    2048 
    2049     }
    2050 
    2051     /* Unload all plug-ins. */
    2052     dbgcPlugInUnloadAll(pDbgc);
    2053 
    2054     /* Detach from the VM. */
    2055     if (pDbgc->pVM)
    2056         DBGFR3Detach(pDbgc->pVM);
    2057 
    2058     /* finally, free the instance memory. */
    2059     RTMemFree(pDbgc);
    2060 }
    2061 
    2062 
    2063 /**
    2064  * Make a console instance.
    2065  *
    2066  * This will not return until either an 'exit' command is issued or a error code
    2067  * indicating connection loss is encountered.
    2068  *
    2069  * @returns VINF_SUCCESS if console termination caused by the 'exit' command.
    2070  * @returns The VBox status code causing the console termination.
    2071  *
    2072  * @param   pVM         VM Handle.
    2073  * @param   pBack       Pointer to the backend structure. This must contain
    2074  *                      a full set of function pointers to service the console.
    2075  * @param   fFlags      Reserved, must be zero.
    2076  * @remark  A forced termination of the console is easiest done by forcing the
    2077  *          callbacks to return fatal failures.
    2078  */
    2079 DBGDECL(int) DBGCCreate(PVM pVM, PDBGCBACK pBack, unsigned fFlags)
    2080 {
    2081     /*
    2082      * Validate input.
    2083      */
    2084     AssertPtrNullReturn(pVM, VERR_INVALID_POINTER);
    2085 
    2086     /*
    2087      * Allocate and initialize instance data
    2088      */
    2089     PDBGC pDbgc;
    2090     int rc = dbgcCreate(&pDbgc, pBack, fFlags);
    2091     if (RT_FAILURE(rc))
    2092         return rc;
    2093 
    2094     /*
    2095      * Print welcome message.
    2096      */
    2097     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    2098                                  "Welcome to the VirtualBox Debugger!\n");
    2099 
    2100     /*
    2101      * Attach to the specified VM.
    2102      */
    2103     if (RT_SUCCESS(rc) && pVM)
    2104     {
    2105         rc = DBGFR3Attach(pVM);
    2106         if (RT_SUCCESS(rc))
    2107         {
    2108             pDbgc->pVM = pVM;
    2109             pDbgc->idCpu = 0;
    2110             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    2111                                          "Current VM is %08x, CPU #%u\n" /** @todo get and print the VM name! */
    2112                                          , pDbgc->pVM, pDbgc->idCpu);
    2113         }
    2114         else
    2115             rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to attach to VM %p\n", pDbgc->pVM);
    2116     }
    2117 
    2118     /*
    2119      * Load plugins.
    2120      */
    2121     if (RT_SUCCESS(rc))
    2122     {
    2123         if (pVM)
    2124             dbgcPlugInAutoLoad(pDbgc);
    2125         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");
    2126     }
    2127     else
    2128         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nDBGCCreate error: %Rrc\n", rc);
    2129 
    2130     /*
    2131      * Run the debugger main loop.
    2132      */
    2133     if (RT_SUCCESS(rc))
    2134         rc = dbgcRun(pDbgc);
    2135 
    2136     /*
    2137      * Cleanup console debugger session.
    2138      */
    2139     dbgcDestroy(pDbgc);
    2140     return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
    2141 }
    2142 
  • trunk/src/VBox/Debugger/DBGCGdbRemoteStub.cpp

    r35346 r35628  
    55
    66/*
    7  * Copyright (C) 2010 Oracle Corporation
     7 * Copyright (C) 2010-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
  • trunk/src/VBox/Debugger/DBGCInternal.h

    r35625 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    396396int     dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress);
    397397
     398void    dbgcEvalInit(void);
    398399int     dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult);
    399 int     dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd, bool fNoExecute);
     400int     dbgcEvalCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd, bool fNoExecute);
    400401
    401402int     dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGCVAR pResult);
     
    434435
    435436#endif
     437
  • trunk/src/VBox/Debugger/DBGCOps.cpp

    r35627 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2323#include <VBox/dbg.h>
    2424#include <VBox/vmm/dbgf.h>
    25 #include <VBox/vmm/vm.h>
    26 #include <VBox/vmm/vmm.h>
    27 #include <VBox/vmm/mm.h>
    28 #include <VBox/vmm/pgm.h>
    29 #include <VBox/vmm/selm.h>
    30 #include <VBox/dis.h>
    3125#include <VBox/param.h>
    3226#include <VBox/err.h>
    3327#include <VBox/log.h>
    3428
    35 #include <iprt/alloc.h>
    36 #include <iprt/alloca.h>
     29#include <iprt/assert.h>
     30#include <iprt/mem.h>
    3731#include <iprt/string.h>
    38 #include <iprt/assert.h>
    39 #include <iprt/ctype.h>
    40 
    41 #include <stdlib.h>
    42 #include <stdio.h>
    4332
    4433#include "DBGCInternal.h"
  • trunk/src/VBox/Debugger/DBGCTcp.cpp

    r35346 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2929#include <iprt/assert.h>
    3030
    31 #include <string.h>
     31#include <iprt/string.h>
    3232
    3333
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r35627 r35628  
    55
    66/*
    7  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2006-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    134134#include <VBox/dbg.h>
    135135#include <VBox/vmm/dbgf.h>
    136 #include <VBox/vmm/vm.h>
    137 #include <VBox/vmm/vmm.h>
    138 #include <VBox/vmm/mm.h>
    139 #include <VBox/vmm/pgm.h>
    140 #include <VBox/vmm/selm.h>
    141 #include <VBox/dis.h>
    142 #include <VBox/param.h>
    143136#include <VBox/err.h>
    144137#include <VBox/log.h>
    145138
    146139#include <iprt/asm.h>
    147 #include <iprt/alloca.h>
    148140#include <iprt/assert.h>
    149141#include <iprt/mem.h>
    150142#include <iprt/string.h>
    151 #include <iprt/ctype.h>
    152 
    153 #include <stdlib.h>
    154 #include <stdio.h>
    155143
    156144#include "DBGCInternal.h"
    157145#include "DBGPlugIns.h"
    158 
    159 
    160 /*******************************************************************************
    161 *   Global Variables                                                           *
    162 *******************************************************************************/
    163 /** Bitmap where set bits indicates the characters the may start an operator name. */
    164 static uint32_t g_bmOperatorChars[256 / (4*8)];
    165146
    166147
     
    169150*******************************************************************************/
    170151static int dbgcProcessLog(PDBGC pDbgc);
    171 
    172 
    173 
    174 /**
    175  * Initializes g_bmOperatorChars.
    176  */
    177 static void dbgcInitOpCharBitMap(void)
    178 {
    179     memset(g_bmOperatorChars, 0, sizeof(g_bmOperatorChars));
    180     for (unsigned iOp = 0; iOp < g_cOps; iOp++)
    181         ASMBitSet(&g_bmOperatorChars[0], (uint8_t)g_aOps[iOp].szName[0]);
    182 }
    183 
    184 
    185 /**
    186  * Checks whether the character may be the start of an operator.
    187  *
    188  * @returns true/false.
    189  * @param   ch      The character.
    190  */
    191 DECLINLINE(bool) dbgcIsOpChar(char ch)
    192 {
    193     return ASMBitTest(&g_bmOperatorChars[0], (uint8_t)ch);
    194 }
    195152
    196153
     
    317274
    318275
    319 static int dbgcEvalSubString(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pArg)
    320 {
    321     Log2(("dbgcEvalSubString: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
    322 
    323     /*
    324      * Removing any quoting and escapings.
    325      */
    326     char ch = *pszExpr;
    327     if (ch == '"' || ch == '\'' || ch == '`')
    328     {
    329         if (pszExpr[--cchExpr] != ch)
    330             return VERR_PARSE_UNBALANCED_QUOTE;
    331         cchExpr--;
    332         pszExpr++;
    333 
    334         /** @todo string unescaping. */
    335     }
    336     pszExpr[cchExpr] = '\0';
    337 
    338     /*
    339      * Make the argument.
    340      */
    341     pArg->pDesc         = NULL;
    342     pArg->pNext         = NULL;
    343     pArg->enmType       = DBGCVAR_TYPE_STRING;
    344     pArg->u.pszString   = pszExpr;
    345     pArg->enmRangeType  = DBGCVAR_RANGE_BYTES;
    346     pArg->u64Range      = cchExpr;
    347 
    348     NOREF(pDbgc);
    349     return 0;
    350 }
    351 
    352 
    353 static int dbgcEvalSubNum(char *pszExpr, unsigned uBase, PDBGCVAR pArg)
    354 {
    355     Log2(("dbgcEvalSubNum: uBase=%d pszExpr=%s\n", uBase, pszExpr));
    356     /*
    357      * Convert to number.
    358      */
    359     uint64_t    u64 = 0;
    360     char        ch;
    361     while ((ch = *pszExpr) != '\0')
    362     {
    363         uint64_t    u64Prev = u64;
    364         unsigned    u = ch - '0';
    365         if (u < 10 && u < uBase)
    366             u64 = u64 * uBase + u;
    367         else if (ch >= 'a' && (u = ch - ('a' - 10)) < uBase)
    368             u64 = u64 * uBase + u;
    369         else if (ch >= 'A' && (u = ch - ('A' - 10)) < uBase)
    370             u64 = u64 * uBase + u;
    371         else
    372             return VERR_PARSE_INVALID_NUMBER;
    373 
    374         /* check for overflow - ARG!!! How to detect overflow correctly!?!?!? */
    375         if (u64Prev != u64 / uBase)
    376             return VERR_PARSE_NUMBER_TOO_BIG;
    377 
    378         /* next */
    379         pszExpr++;
    380     }
    381 
    382     /*
    383      * Initialize the argument.
    384      */
    385     pArg->pDesc         = NULL;
    386     pArg->pNext         = NULL;
    387     pArg->enmType       = DBGCVAR_TYPE_NUMBER;
    388     pArg->u.u64Number   = u64;
    389     pArg->enmRangeType  = DBGCVAR_RANGE_NONE;
    390     pArg->u64Range      = 0;
    391 
    392     return 0;
    393 }
    394 
    395 
    396 /**
    397  * Match variable and variable descriptor, promoting the variable if necessary.
    398  *
    399  * @returns VBox status code.
    400  * @param   pDbgc       Debug console instanace.
    401  * @param   pVar        Variable.
    402  * @param   pVarDesc    Variable descriptor.
    403  */
    404 static int dbgcEvalSubMatchVar(PDBGC pDbgc, PDBGCVAR pVar, PCDBGCVARDESC pVarDesc)
    405 {
    406     /*
    407      * (If match or promoted to match, return, else break.)
    408      */
    409     switch (pVarDesc->enmCategory)
    410     {
    411         /*
    412          * Anything goes
    413          */
    414         case DBGCVAR_CAT_ANY:
    415             return VINF_SUCCESS;
    416 
    417         /*
    418          * Pointer with and without range.
    419          * We can try resolve strings and symbols as symbols and
    420          * promote numbers to flat GC pointers.
    421          */
    422         case DBGCVAR_CAT_POINTER_NO_RANGE:
    423             if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    424                 return VERR_PARSE_NO_RANGE_ALLOWED;
    425             /* fallthru */
    426         case DBGCVAR_CAT_POINTER:
    427             switch (pVar->enmType)
    428             {
    429                 case DBGCVAR_TYPE_GC_FLAT:
    430                 case DBGCVAR_TYPE_GC_FAR:
    431                 case DBGCVAR_TYPE_GC_PHYS:
    432                 case DBGCVAR_TYPE_HC_FLAT:
    433                 case DBGCVAR_TYPE_HC_PHYS:
    434                     return VINF_SUCCESS;
    435 
    436                 case DBGCVAR_TYPE_SYMBOL:
    437                 case DBGCVAR_TYPE_STRING:
    438                 {
    439                     DBGCVAR Var;
    440                     int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_GC_FLAT, &Var);
    441                     if (RT_SUCCESS(rc))
    442                     {
    443                         /* deal with range */
    444                         if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    445                         {
    446                             Var.enmRangeType = pVar->enmRangeType;
    447                             Var.u64Range = pVar->u64Range;
    448                         }
    449                         else if (pVarDesc->enmCategory == DBGCVAR_CAT_POINTER_NO_RANGE)
    450                             Var.enmRangeType = DBGCVAR_RANGE_NONE;
    451                         *pVar = Var;
    452                         return rc;
    453                     }
    454                     break;
    455                 }
    456 
    457                 case DBGCVAR_TYPE_NUMBER:
    458                 {
    459                     RTGCPTR GCPtr = (RTGCPTR)pVar->u.u64Number;
    460                     pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
    461                     pVar->u.GCFlat = GCPtr;
    462                     return VINF_SUCCESS;
    463                 }
    464 
    465                 default:
    466                     break;
    467             }
    468             break;
    469 
    470         /*
    471          * GC pointer with and without range.
    472          * We can try resolve strings and symbols as symbols and
    473          * promote numbers to flat GC pointers.
    474          */
    475         case DBGCVAR_CAT_GC_POINTER_NO_RANGE:
    476             if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    477                 return VERR_PARSE_NO_RANGE_ALLOWED;
    478             /* fallthru */
    479         case DBGCVAR_CAT_GC_POINTER:
    480             switch (pVar->enmType)
    481             {
    482                 case DBGCVAR_TYPE_GC_FLAT:
    483                 case DBGCVAR_TYPE_GC_FAR:
    484                 case DBGCVAR_TYPE_GC_PHYS:
    485                     return VINF_SUCCESS;
    486 
    487                 case DBGCVAR_TYPE_HC_FLAT:
    488                 case DBGCVAR_TYPE_HC_PHYS:
    489                     return VERR_PARSE_CONVERSION_FAILED;
    490 
    491                 case DBGCVAR_TYPE_SYMBOL:
    492                 case DBGCVAR_TYPE_STRING:
    493                 {
    494                     DBGCVAR Var;
    495                     int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_GC_FLAT, &Var);
    496                     if (RT_SUCCESS(rc))
    497                     {
    498                         /* deal with range */
    499                         if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    500                         {
    501                             Var.enmRangeType = pVar->enmRangeType;
    502                             Var.u64Range = pVar->u64Range;
    503                         }
    504                         else if (pVarDesc->enmCategory == DBGCVAR_CAT_POINTER_NO_RANGE)
    505                             Var.enmRangeType = DBGCVAR_RANGE_NONE;
    506                         *pVar = Var;
    507                         return rc;
    508                     }
    509                     break;
    510                 }
    511 
    512                 case DBGCVAR_TYPE_NUMBER:
    513                 {
    514                     RTGCPTR GCPtr = (RTGCPTR)pVar->u.u64Number;
    515                     pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
    516                     pVar->u.GCFlat = GCPtr;
    517                     return VINF_SUCCESS;
    518                 }
    519 
    520                 default:
    521                     break;
    522             }
    523             break;
    524 
    525         /*
    526          * Number with or without a range.
    527          * Numbers can be resolved from symbols, but we cannot demote a pointer
    528          * to a number.
    529          */
    530         case DBGCVAR_CAT_NUMBER_NO_RANGE:
    531             if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    532                 return VERR_PARSE_NO_RANGE_ALLOWED;
    533             /* fallthru */
    534         case DBGCVAR_CAT_NUMBER:
    535             switch (pVar->enmType)
    536             {
    537                 case DBGCVAR_TYPE_NUMBER:
    538                     return VINF_SUCCESS;
    539 
    540                 case DBGCVAR_TYPE_SYMBOL:
    541                 case DBGCVAR_TYPE_STRING:
    542                 {
    543                     DBGCVAR Var;
    544                     int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
    545                     if (RT_SUCCESS(rc))
    546                     {
    547                         *pVar = Var;
    548                         return rc;
    549                     }
    550                     break;
    551                 }
    552                 default:
    553                     break;
    554             }
    555             break;
    556 
    557         /*
    558          * Strings can easily be made from symbols (and of course strings).
    559          * We could consider reformatting the addresses and numbers into strings later...
    560          */
    561         case DBGCVAR_CAT_STRING:
    562             switch (pVar->enmType)
    563             {
    564                 case DBGCVAR_TYPE_SYMBOL:
    565                     pVar->enmType = DBGCVAR_TYPE_STRING;
    566                     /* fallthru */
    567                 case DBGCVAR_TYPE_STRING:
    568                     return VINF_SUCCESS;
    569                 default:
    570                     break;
    571             }
    572             break;
    573 
    574         /*
    575          * Symol is pretty much the same thing as a string (at least until we actually implement it).
    576          */
    577         case DBGCVAR_CAT_SYMBOL:
    578             switch (pVar->enmType)
    579             {
    580                 case DBGCVAR_TYPE_STRING:
    581                     pVar->enmType = DBGCVAR_TYPE_SYMBOL;
    582                     /* fallthru */
    583                 case DBGCVAR_TYPE_SYMBOL:
    584                     return VINF_SUCCESS;
    585                 default:
    586                     break;
    587             }
    588             break;
    589 
    590         /*
    591          * Anything else is illegal.
    592          */
    593         default:
    594             AssertMsgFailed(("enmCategory=%d\n", pVar->enmType));
    595             break;
    596     }
    597 
    598     return VERR_PARSE_NO_ARGUMENT_MATCH;
    599 }
    600 
    601 
    602 /**
    603  * Matches a set of variables with a description set.
    604  *
    605  * This is typically used for routine arguments before a call. The effects in
    606  * addition to the validation, is that some variables might be propagated to
    607  * other types in order to match the description. The following transformations
    608  * are supported:
    609  *      - String reinterpreted as a symbol and resolved to a number or pointer.
    610  *      - Number to a pointer.
    611  *      - Pointer to a number.
    612  * @returns 0 on success with paVars.
    613  * @returns VBox error code for match errors.
    614  */
    615 static int dbgcEvalSubMatchVars(PDBGC pDbgc, unsigned cVarsMin, unsigned cVarsMax,
    616                                 PCDBGCVARDESC paVarDescs, unsigned cVarDescs,
    617                                 PDBGCVAR paVars, unsigned cVars)
    618 {
    619     /*
    620      * Just do basic min / max checks first.
    621      */
    622     if (cVars < cVarsMin)
    623         return VERR_PARSE_TOO_FEW_ARGUMENTS;
    624     if (cVars > cVarsMax)
    625         return VERR_PARSE_TOO_MANY_ARGUMENTS;
    626 
    627     /*
    628      * Match the descriptors and actual variables.
    629      */
    630     PCDBGCVARDESC   pPrevDesc = NULL;
    631     unsigned        cCurDesc = 0;
    632     unsigned        iVar = 0;
    633     unsigned        iVarDesc = 0;
    634     while (iVar < cVars)
    635     {
    636         /* walk the descriptors */
    637         if (iVarDesc >= cVarDescs)
    638             return VERR_PARSE_TOO_MANY_ARGUMENTS;
    639         if (    (    paVarDescs[iVarDesc].fFlags & DBGCVD_FLAGS_DEP_PREV
    640                 &&  &paVarDescs[iVarDesc - 1] != pPrevDesc)
    641             ||  cCurDesc >= paVarDescs[iVarDesc].cTimesMax)
    642         {
    643             iVarDesc++;
    644             if (iVarDesc >= cVarDescs)
    645                 return VERR_PARSE_TOO_MANY_ARGUMENTS;
    646             cCurDesc = 0;
    647         }
    648 
    649         /*
    650          * Skip thru optional arguments until we find something which matches
    651          * or can easily be promoted to what the descriptor want.
    652          */
    653         for (;;)
    654         {
    655             int rc = dbgcEvalSubMatchVar(pDbgc, &paVars[iVar], &paVarDescs[iVarDesc]);
    656             if (RT_SUCCESS(rc))
    657             {
    658                 paVars[iVar].pDesc = &paVarDescs[iVarDesc];
    659                 cCurDesc++;
    660                 break;
    661             }
    662 
    663             /* can we advance? */
    664             if (paVarDescs[iVarDesc].cTimesMin > cCurDesc)
    665                 return VERR_PARSE_ARGUMENT_TYPE_MISMATCH;
    666             if (++iVarDesc >= cVarDescs)
    667                 return VERR_PARSE_ARGUMENT_TYPE_MISMATCH;
    668             cCurDesc = 0;
    669         }
    670 
    671         /* next var */
    672         iVar++;
    673     }
    674 
    675     /*
    676      * Check that the rest of the descriptors are optional.
    677      */
    678     while (iVarDesc < cVarDescs)
    679     {
    680         if (paVarDescs[iVarDesc].cTimesMin > cCurDesc)
    681             return VERR_PARSE_TOO_FEW_ARGUMENTS;
    682         cCurDesc = 0;
    683 
    684         /* next */
    685         iVarDesc++;
    686     }
    687 
    688     return 0;
    689 }
    690 
    691 
    692 /**
    693  * Evaluates one argument with respect to unary operators.
    694  *
    695  * @returns 0 on success. pResult contains the result.
    696  * @returns VBox error code on parse or other evaluation error.
    697  *
    698  * @param   pDbgc       Debugger console instance data.
    699  * @param   pszExpr     The expression string.
    700  * @param   pResult     Where to store the result of the expression evaluation.
    701  */
    702 static int dbgcEvalSubUnary(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult)
    703 {
    704     Log2(("dbgcEvalSubUnary: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
    705 
    706     /*
    707      * The state of the expression is now such that it will start by zero or more
    708      * unary operators and being followed by an expression of some kind.
    709      * The expression is either plain or in parenthesis.
    710      *
    711      * Being in a lazy, recursive mode today, the parsing is done as simple as possible. :-)
    712      * ASSUME: unary operators are all of equal precedence.
    713      */
    714     int         rc = 0;
    715     PCDBGCOP    pOp = dbgcOperatorLookup(pDbgc, pszExpr, false, ' ');
    716     if (pOp)
    717     {
    718         /* binary operators means syntax error. */
    719         if (pOp->fBinary)
    720             return VERR_PARSE_UNEXPECTED_OPERATOR;
    721 
    722         /*
    723          * If the next expression (the one following the unary operator) is in a
    724          * parenthesis a full eval is needed. If not the unary eval will suffice.
    725          */
    726         /* calc and strip next expr. */
    727         char *pszExpr2 = pszExpr + pOp->cchName;
    728         while (RT_C_IS_BLANK(*pszExpr2))
    729             pszExpr2++;
    730 
    731         if (!*pszExpr2)
    732             rc = VERR_PARSE_EMPTY_ARGUMENT;
    733         else
    734         {
    735             DBGCVAR Arg;
    736             if (*pszExpr2 == '(')
    737                 rc = dbgcEvalSub(pDbgc, pszExpr2, cchExpr - (pszExpr2 - pszExpr), &Arg);
    738             else
    739                 rc = dbgcEvalSubUnary(pDbgc, pszExpr2, cchExpr - (pszExpr2 - pszExpr), &Arg);
    740             if (RT_SUCCESS(rc))
    741                 rc = pOp->pfnHandlerUnary(pDbgc, &Arg, pResult);
    742         }
    743     }
    744     else
    745     {
    746         /*
    747          * Didn't find any operators, so it we have to check if this can be an
    748          * function call before assuming numeric or string expression.
    749          *
    750          * (ASSUMPTIONS:)
    751          * A function name only contains alphanumerical chars and it can not start
    752          * with a numerical character.
    753          * Immediately following the name is a parenthesis which must over
    754          * the remaining part of the expression.
    755          */
    756         bool    fExternal = *pszExpr == '.';
    757         char   *pszFun    = fExternal ? pszExpr + 1 : pszExpr;
    758         char   *pszFunEnd = NULL;
    759         if (pszExpr[cchExpr - 1] == ')' && RT_C_IS_ALPHA(*pszFun))
    760         {
    761             pszFunEnd = pszExpr + 1;
    762             while (*pszFunEnd != '(' && RT_C_IS_ALNUM(*pszFunEnd))
    763                 pszFunEnd++;
    764             if (*pszFunEnd != '(')
    765                 pszFunEnd = NULL;
    766         }
    767 
    768         if (pszFunEnd)
    769         {
    770             /*
    771              * Ok, it's a function call.
    772              */
    773             if (fExternal)
    774                 pszExpr++, cchExpr--;
    775             PCDBGCCMD pFun = dbgcRoutineLookup(pDbgc, pszExpr, pszFunEnd - pszExpr, fExternal);
    776             if (!pFun)
    777                 return VERR_PARSE_FUNCTION_NOT_FOUND;
    778             if (!pFun->pResultDesc)
    779                 return VERR_PARSE_NOT_A_FUNCTION;
    780 
    781             /*
    782              * Parse the expression in parenthesis.
    783              */
    784             cchExpr -= pszFunEnd - pszExpr;
    785             pszExpr = pszFunEnd;
    786             /** @todo implement multiple arguments. */
    787             DBGCVAR     Arg;
    788             rc = dbgcEvalSub(pDbgc, pszExpr, cchExpr, &Arg);
    789             if (!rc)
    790             {
    791                 rc = dbgcEvalSubMatchVars(pDbgc, pFun->cArgsMin, pFun->cArgsMax, pFun->paArgDescs, pFun->cArgDescs, &Arg, 1);
    792                 if (!rc)
    793                     rc = pFun->pfnHandler(pFun, &pDbgc->CmdHlp, pDbgc->pVM, &Arg, 1, pResult);
    794             }
    795             else if (rc == VERR_PARSE_EMPTY_ARGUMENT && pFun->cArgsMin == 0)
    796                 rc = pFun->pfnHandler(pFun, &pDbgc->CmdHlp, pDbgc->pVM, NULL, 0, pResult);
    797         }
    798         else
    799         {
    800             /*
    801              * Didn't find any operators, so it must be a plain expression.
    802              * This might be numeric or a string expression.
    803              */
    804             char ch  = pszExpr[0];
    805             char ch2 = pszExpr[1];
    806             if (ch == '0' && (ch2 == 'x' || ch2 == 'X'))
    807                 rc = dbgcEvalSubNum(pszExpr + 2, 16, pResult);
    808             else if (ch == '0' && (ch2 == 'i' || ch2 == 'i'))
    809                 rc = dbgcEvalSubNum(pszExpr + 2, 10, pResult);
    810             else if (ch == '0' && (ch2 == 't' || ch2 == 'T'))
    811                 rc = dbgcEvalSubNum(pszExpr + 2, 8, pResult);
    812             /// @todo 0b doesn't work as a binary prefix, we confuse it with 0bf8:0123 and stuff.
    813             //else if (ch == '0' && (ch2 == 'b' || ch2 == 'b'))
    814             //    rc = dbgcEvalSubNum(pszExpr + 2, 2, pResult);
    815             else
    816             {
    817                 /*
    818                  * Hexadecimal number or a string?
    819                  */
    820                 char *psz = pszExpr;
    821                 while (RT_C_IS_XDIGIT(*psz))
    822                     psz++;
    823                 if (!*psz)
    824                     rc = dbgcEvalSubNum(pszExpr, 16, pResult);
    825                 else if ((*psz == 'h' || *psz == 'H') && !psz[1])
    826                 {
    827                     *psz = '\0';
    828                     rc = dbgcEvalSubNum(pszExpr, 16, pResult);
    829                 }
    830                 else
    831                     rc = dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    832             }
    833         }
    834     }
    835 
    836     return rc;
    837 }
    838 
    839 
    840 /**
    841  * Evaluates one argument.
    842  *
    843  * @returns 0 on success. pResult contains the result.
    844  * @returns VBox error code on parse or other evaluation error.
    845  *
    846  * @param   pDbgc       Debugger console instance data.
    847  * @param   pszExpr     The expression string.
    848  * @param   pResult     Where to store the result of the expression evaluation.
    849  */
    850 int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult)
    851 {
    852     Log2(("dbgcEvalSub: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
    853     /*
    854      * First we need to remove blanks in both ends.
    855      * ASSUMES: There is no quoting unless the entire expression is a string.
    856      */
    857 
    858     /* stripping. */
    859     while (cchExpr > 0 && RT_C_IS_BLANK(pszExpr[cchExpr - 1]))
    860         pszExpr[--cchExpr] = '\0';
    861     while (RT_C_IS_BLANK(*pszExpr))
    862         pszExpr++, cchExpr--;
    863     if (!*pszExpr)
    864         return VERR_PARSE_EMPTY_ARGUMENT;
    865 
    866     /* it there is any kind of quoting in the expression, it's string meat. */
    867     if (strpbrk(pszExpr, "\"'`"))
    868         return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    869 
    870     /*
    871      * Check if there are any parenthesis which needs removing.
    872      */
    873     if (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')')
    874     {
    875         do
    876         {
    877             unsigned cPar = 1;
    878             char    *psz = pszExpr + 1;
    879             char     ch;
    880             while ((ch = *psz) != '\0')
    881             {
    882                 if (ch == '(')
    883                     cPar++;
    884                 else if (ch == ')')
    885                 {
    886                     if (cPar <= 0)
    887                         return VERR_PARSE_UNBALANCED_PARENTHESIS;
    888                     cPar--;
    889                     if (cPar == 0 && psz[1]) /* If not at end, there's nothing to do. */
    890                         break;
    891                 }
    892                 /* next */
    893                 psz++;
    894             }
    895             if (ch)
    896                 break;
    897 
    898             /* remove the parenthesis. */
    899             pszExpr++;
    900             cchExpr -= 2;
    901             pszExpr[cchExpr] = '\0';
    902 
    903             /* strip blanks. */
    904             while (cchExpr > 0 && RT_C_IS_BLANK(pszExpr[cchExpr - 1]))
    905                 pszExpr[--cchExpr] = '\0';
    906             while (RT_C_IS_BLANK(*pszExpr))
    907                 pszExpr++, cchExpr--;
    908             if (!*pszExpr)
    909                 return VERR_PARSE_EMPTY_ARGUMENT;
    910         } while (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')');
    911     }
    912 
    913     /* tabs to spaces. */
    914     char *psz = pszExpr;
    915     while ((psz = strchr(psz, '\t')) != NULL)
    916         *psz = ' ';
    917 
    918     /*
    919      * Now, we need to look for the binary operator with the lowest precedence.
    920      *
    921      * If there are no operators we're left with a simple expression which we
    922      * evaluate with respect to unary operators
    923      */
    924     char       *pszOpSplit = NULL;
    925     PCDBGCOP    pOpSplit = NULL;
    926     unsigned    cBinaryOps = 0;
    927     unsigned    cPar = 0;
    928     char        ch;
    929     char        chPrev = ' ';
    930     bool        fBinary = false;
    931     psz = pszExpr;
    932 
    933     while ((ch = *psz) != '\0')
    934     {
    935         //Log2(("ch=%c cPar=%d fBinary=%d\n", ch, cPar, fBinary));
    936         /*
    937          * Parenthesis.
    938          */
    939         if (ch == '(')
    940         {
    941             cPar++;
    942             fBinary = false;
    943         }
    944         else if (ch == ')')
    945         {
    946             if (cPar <= 0)
    947                 return VERR_PARSE_UNBALANCED_PARENTHESIS;
    948             cPar--;
    949             fBinary = true;
    950         }
    951         /*
    952          * Potential operator.
    953          */
    954         else if (cPar == 0 && !RT_C_IS_BLANK(ch))
    955         {
    956             PCDBGCOP pOp = dbgcIsOpChar(ch)
    957                          ? dbgcOperatorLookup(pDbgc, psz, fBinary, chPrev)
    958                          : NULL;
    959             if (pOp)
    960             {
    961                 /* If not the right kind of operator we've got a syntax error. */
    962                 if (pOp->fBinary != fBinary)
    963                     return VERR_PARSE_UNEXPECTED_OPERATOR;
    964 
    965                 /*
    966                  * Update the parse state and skip the operator.
    967                  */
    968                 if (!pOpSplit)
    969                 {
    970                     pOpSplit = pOp;
    971                     pszOpSplit = psz;
    972                     cBinaryOps = fBinary;
    973                 }
    974                 else if (fBinary)
    975                 {
    976                     cBinaryOps++;
    977                     if (pOp->iPrecedence >= pOpSplit->iPrecedence)
    978                     {
    979                         pOpSplit = pOp;
    980                         pszOpSplit = psz;
    981                     }
    982                 }
    983 
    984                 psz += pOp->cchName - 1;
    985                 fBinary = false;
    986             }
    987             else
    988                 fBinary = true;
    989         }
    990 
    991         /* next */
    992         psz++;
    993         chPrev = ch;
    994     } /* parse loop. */
    995 
    996 
    997     /*
    998      * Either we found an operator to divide the expression by
    999      * or we didn't find any. In the first case it's divide and
    1000      * conquer. In the latter it's a single expression which
    1001      * needs dealing with its unary operators if any.
    1002      */
    1003     int rc;
    1004     if (    cBinaryOps
    1005         &&  pOpSplit->fBinary)
    1006     {
    1007         /* process 1st sub expression. */
    1008         *pszOpSplit = '\0';
    1009         DBGCVAR     Arg1;
    1010         rc = dbgcEvalSub(pDbgc, pszExpr, pszOpSplit - pszExpr, &Arg1);
    1011         if (RT_SUCCESS(rc))
    1012         {
    1013             /* process 2nd sub expression. */
    1014             char       *psz2 = pszOpSplit + pOpSplit->cchName;
    1015             DBGCVAR     Arg2;
    1016             rc = dbgcEvalSub(pDbgc, psz2, cchExpr - (psz2 - pszExpr), &Arg2);
    1017             if (RT_SUCCESS(rc))
    1018                 /* apply the operator. */
    1019                 rc = pOpSplit->pfnHandlerBinary(pDbgc, &Arg1, &Arg2, pResult);
    1020         }
    1021     }
    1022     else if (cBinaryOps)
    1023     {
    1024         /* process sub expression. */
    1025         pszOpSplit += pOpSplit->cchName;
    1026         DBGCVAR     Arg;
    1027         rc = dbgcEvalSub(pDbgc, pszOpSplit, cchExpr - (pszOpSplit - pszExpr), &Arg);
    1028         if (RT_SUCCESS(rc))
    1029             /* apply the operator. */
    1030             rc = pOpSplit->pfnHandlerUnary(pDbgc, &Arg, pResult);
    1031     }
    1032     else
    1033         /* plain expression or using unary operators perhaps with parentheses. */
    1034         rc = dbgcEvalSubUnary(pDbgc, pszExpr, cchExpr, pResult);
    1035 
    1036     return rc;
    1037 }
    1038 
    1039 
    1040 /**
    1041  * Parses the arguments of one command.
    1042  *
    1043  * @returns 0 on success.
    1044  * @returns VBox error code on parse error with *pcArg containing the argument causing trouble.
    1045  * @param   pDbgc       Debugger console instance data.
    1046  * @param   pCmd        Pointer to the command descriptor.
    1047  * @param   pszArg      Pointer to the arguments to parse.
    1048  * @param   paArgs      Where to store the parsed arguments.
    1049  * @param   cArgs       Size of the paArgs array.
    1050  * @param   pcArgs      Where to store the number of arguments.
    1051  *                      In the event of an error this is used to store the index of the offending argument.
    1052  */
    1053 static int dbgcProcessArguments(PDBGC pDbgc, PCDBGCCMD pCmd, char *pszArgs, PDBGCVAR paArgs, unsigned cArgs, unsigned *pcArgs)
    1054 {
    1055     Log2(("dbgcProcessArguments: pCmd=%s pszArgs='%s'\n", pCmd->pszCmd, pszArgs));
    1056     /*
    1057      * Check if we have any argument and if the command takes any.
    1058      */
    1059     *pcArgs = 0;
    1060     /* strip leading blanks. */
    1061     while (*pszArgs && RT_C_IS_BLANK(*pszArgs))
    1062         pszArgs++;
    1063     if (!*pszArgs)
    1064     {
    1065         if (!pCmd->cArgsMin)
    1066             return 0;
    1067         return VERR_PARSE_TOO_FEW_ARGUMENTS;
    1068     }
    1069     /** @todo fixme - foo() doesn't work. */
    1070     if (!pCmd->cArgsMax)
    1071         return VERR_PARSE_TOO_MANY_ARGUMENTS;
    1072 
    1073     /*
    1074      * This is a hack, it's "temporary" and should go away "when" the parser is
    1075      * modified to match arguments while parsing.
    1076      */
    1077     if (    pCmd->cArgsMax == 1
    1078         &&  pCmd->cArgsMin == 1
    1079         &&  pCmd->cArgDescs == 1
    1080         &&  pCmd->paArgDescs[0].enmCategory == DBGCVAR_CAT_STRING
    1081         &&  cArgs >= 1)
    1082     {
    1083         *pcArgs = 1;
    1084         RTStrStripR(pszArgs);
    1085         return dbgcEvalSubString(pDbgc, pszArgs, strlen(pszArgs), &paArgs[0]);
    1086     }
    1087 
    1088 
    1089     /*
    1090      * The parse loop.
    1091      */
    1092     PDBGCVAR        pArg0 = &paArgs[0];
    1093     PDBGCVAR        pArg = pArg0;
    1094     *pcArgs = 0;
    1095     do
    1096     {
    1097         /*
    1098          * Can we have another argument?
    1099          */
    1100         if (*pcArgs >= pCmd->cArgsMax)
    1101             return VERR_PARSE_TOO_MANY_ARGUMENTS;
    1102         if (pArg >= &paArgs[cArgs])
    1103             return VERR_PARSE_ARGUMENT_OVERFLOW;
    1104 
    1105         /*
    1106          * Find the end of the argument.
    1107          */
    1108         int     cPar    = 0;
    1109         char    chQuote = '\0';
    1110         char   *pszEnd  = NULL;
    1111         char   *psz     = pszArgs;
    1112         char    ch;
    1113         bool    fBinary = false;
    1114         for (;;)
    1115         {
    1116             /*
    1117              * Check for the end.
    1118              */
    1119             if ((ch = *psz) == '\0')
    1120             {
    1121                 if (chQuote)
    1122                     return VERR_PARSE_UNBALANCED_QUOTE;
    1123                 if (cPar)
    1124                     return VERR_PARSE_UNBALANCED_PARENTHESIS;
    1125                 pszEnd = psz;
    1126                 break;
    1127             }
    1128             /*
    1129              * When quoted we ignore everything but the quotation char.
    1130              * We use the REXX way of escaping the quotation char, i.e. double occurrence.
    1131              */
    1132             else if (ch == '\'' || ch == '"' || ch == '`')
    1133             {
    1134                 if (chQuote)
    1135                 {
    1136                     /* end quote? */
    1137                     if (ch == chQuote)
    1138                     {
    1139                         if (psz[1] == ch)
    1140                             psz++;          /* skip the escaped quote char */
    1141                         else
    1142                             chQuote = '\0'; /* end of quoted string. */
    1143                     }
    1144                 }
    1145                 else
    1146                     chQuote = ch;           /* open new quote */
    1147             }
    1148             /*
    1149              * Parenthesis can of course be nested.
    1150              */
    1151             else if (ch == '(')
    1152             {
    1153                 cPar++;
    1154                 fBinary = false;
    1155             }
    1156             else if (ch == ')')
    1157             {
    1158                 if (!cPar)
    1159                     return VERR_PARSE_UNBALANCED_PARENTHESIS;
    1160                 cPar--;
    1161                 fBinary = true;
    1162             }
    1163             else if (!chQuote && !cPar)
    1164             {
    1165                 /*
    1166                  * Encountering blanks may mean the end of it all. A binary operator
    1167                  * will force continued parsing.
    1168                  */
    1169                 if (RT_C_IS_BLANK(*psz))
    1170                 {
    1171                     pszEnd = psz++;         /* just in case. */
    1172                     while (RT_C_IS_BLANK(*psz))
    1173                         psz++;
    1174                     PCDBGCOP pOp = dbgcOperatorLookup(pDbgc, psz, fBinary, ' ');
    1175                     if (!pOp || pOp->fBinary != fBinary)
    1176                         break;              /* the end. */
    1177                     psz += pOp->cchName;
    1178                     while (RT_C_IS_BLANK(*psz))   /* skip blanks so we don't get here again */
    1179                         psz++;
    1180                     fBinary = false;
    1181                     continue;
    1182                 }
    1183 
    1184                 /*
    1185                  * Look for operators without a space up front.
    1186                  */
    1187                 if (dbgcIsOpChar(*psz))
    1188                 {
    1189                     PCDBGCOP pOp = dbgcOperatorLookup(pDbgc, psz, fBinary, ' ');
    1190                     if (pOp)
    1191                     {
    1192                         if (pOp->fBinary != fBinary)
    1193                         {
    1194                             pszEnd = psz;
    1195                             /** @todo this is a parsing error really. */
    1196                             break;              /* the end. */
    1197                         }
    1198                         psz += pOp->cchName;
    1199                         while (RT_C_IS_BLANK(*psz))   /* skip blanks so we don't get here again */
    1200                             psz++;
    1201                         fBinary = false;
    1202                         continue;
    1203                     }
    1204                 }
    1205                 fBinary = true;
    1206             }
    1207 
    1208             /* next char */
    1209             psz++;
    1210         }
    1211         *pszEnd = '\0';
    1212         /* (psz = next char to process) */
    1213 
    1214         /*
    1215          * Parse and evaluate the argument.
    1216          */
    1217         int rc = dbgcEvalSub(pDbgc, pszArgs, strlen(pszArgs), pArg);
    1218         if (RT_FAILURE(rc))
    1219             return rc;
    1220 
    1221         /*
    1222          * Next.
    1223          */
    1224         pArg++;
    1225         (*pcArgs)++;
    1226         pszArgs = psz;
    1227         while (*pszArgs && RT_C_IS_BLANK(*pszArgs))
    1228             pszArgs++;
    1229     } while (*pszArgs);
    1230 
    1231     /*
    1232      * Match the arguments.
    1233      */
    1234     return dbgcEvalSubMatchVars(pDbgc, pCmd->cArgsMin, pCmd->cArgsMax, pCmd->paArgDescs, pCmd->cArgDescs, pArg0, pArg - pArg0);
    1235 }
    1236 
    1237 
    1238 /**
    1239  * Process one command.
    1240  *
    1241  * @returns VBox status code. Any error indicates the termination of the console session.
    1242  * @param   pDbgc       Debugger console instance data.
    1243  * @param   pszCmd      Pointer to the command.
    1244  * @param   cchCmd      Length of the command.
    1245  * @param   fNoExecute  Indicates that no commands should actually be executed.
    1246  */
    1247 int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd, bool fNoExecute)
    1248 {
    1249     char *pszCmdInput = pszCmd;
    1250 
    1251     /*
    1252      * Skip blanks.
    1253      */
    1254     while (RT_C_IS_BLANK(*pszCmd))
    1255         pszCmd++, cchCmd--;
    1256 
    1257     /* external command? */
    1258     bool fExternal = *pszCmd == '.';
    1259     if (fExternal)
    1260         pszCmd++, cchCmd--;
    1261 
    1262     /*
    1263      * Find arguments.
    1264      */
    1265     char *pszArgs = pszCmd;
    1266     while (RT_C_IS_ALNUM(*pszArgs))
    1267         pszArgs++;
    1268     if (*pszArgs && (!RT_C_IS_BLANK(*pszArgs) || pszArgs == pszCmd))
    1269     {
    1270         pDbgc->rcCmd = VINF_PARSE_INVALD_COMMAND_NAME;
    1271         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Syntax error in command '%s'!\n", pszCmdInput);
    1272         return 0;
    1273     }
    1274 
    1275     /*
    1276      * Find the command.
    1277      */
    1278     PCDBGCCMD pCmd = dbgcRoutineLookup(pDbgc, pszCmd, pszArgs - pszCmd, fExternal);
    1279     if (!pCmd || (pCmd->fFlags & DBGCCMD_FLAGS_FUNCTION))
    1280     {
    1281         pDbgc->rcCmd = VINF_PARSE_COMMAND_NOT_FOUND;
    1282         return pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Unknown command '%s'!\n", pszCmdInput);
    1283     }
    1284 
    1285     /*
    1286      * Parse arguments (if any).
    1287      */
    1288     unsigned cArgs;
    1289     int rc = dbgcProcessArguments(pDbgc, pCmd, pszArgs, &pDbgc->aArgs[pDbgc->iArg], RT_ELEMENTS(pDbgc->aArgs) - pDbgc->iArg, &cArgs);
    1290 
    1291     /*
    1292      * Execute the command.
    1293      */
    1294     if (!rc)
    1295     {
    1296         if (!fNoExecute)
    1297             rc = pCmd->pfnHandler(pCmd, &pDbgc->CmdHlp, pDbgc->pVM, &pDbgc->aArgs[0], cArgs, NULL);
    1298         pDbgc->rcCmd = rc;
    1299         if (rc == VERR_DBGC_COMMAND_FAILED)
    1300             rc = VINF_SUCCESS;
    1301     }
    1302     else
    1303     {
    1304         pDbgc->rcCmd = rc;
    1305 
    1306         /* report parse / eval error. */
    1307         switch (rc)
    1308         {
    1309             case VERR_PARSE_TOO_FEW_ARGUMENTS:
    1310                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1311                     "Syntax error: Too few arguments. Minimum is %d for command '%s'.\n", pCmd->cArgsMin, pCmd->pszCmd);
    1312                 break;
    1313             case VERR_PARSE_TOO_MANY_ARGUMENTS:
    1314                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1315                     "Syntax error: Too many arguments. Maximum is %d for command '%s'.\n", pCmd->cArgsMax, pCmd->pszCmd);
    1316                 break;
    1317             case VERR_PARSE_ARGUMENT_OVERFLOW:
    1318                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1319                     "Syntax error: Too many arguments.\n");
    1320                 break;
    1321             case VERR_PARSE_UNBALANCED_QUOTE:
    1322                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1323                     "Syntax error: Unbalanced quote (argument %d).\n", cArgs);
    1324                 break;
    1325             case VERR_PARSE_UNBALANCED_PARENTHESIS:
    1326                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1327                     "Syntax error: Unbalanced parenthesis (argument %d).\n", cArgs);
    1328                 break;
    1329             case VERR_PARSE_EMPTY_ARGUMENT:
    1330                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1331                     "Syntax error: An argument or subargument contains nothing useful (argument %d).\n", cArgs);
    1332                 break;
    1333             case VERR_PARSE_UNEXPECTED_OPERATOR:
    1334                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1335                     "Syntax error: Invalid operator usage (argument %d).\n", cArgs);
    1336                 break;
    1337             case VERR_PARSE_INVALID_NUMBER:
    1338                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1339                     "Syntax error: Ivalid numeric value (argument %d). If a string was the intention, then quote it.\n", cArgs);
    1340                 break;
    1341             case VERR_PARSE_NUMBER_TOO_BIG:
    1342                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1343                     "Error: Numeric overflow (argument %d).\n", cArgs);
    1344                 break;
    1345             case VERR_PARSE_INVALID_OPERATION:
    1346                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1347                     "Error: Invalid operation attempted (argument %d).\n", cArgs);
    1348                 break;
    1349             case VERR_PARSE_FUNCTION_NOT_FOUND:
    1350                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1351                     "Error: Function not found (argument %d).\n", cArgs);
    1352                 break;
    1353             case VERR_PARSE_NOT_A_FUNCTION:
    1354                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1355                     "Error: The function specified is not a function (argument %d).\n", cArgs);
    1356                 break;
    1357             case VERR_PARSE_NO_MEMORY:
    1358                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1359                     "Error: Out memory in the regular heap! Expect odd stuff to happen...\n", cArgs);
    1360                 break;
    1361             case VERR_PARSE_INCORRECT_ARG_TYPE:
    1362                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1363                     "Error: Incorrect argument type (argument %d?).\n", cArgs);
    1364                 break;
    1365             case VERR_PARSE_VARIABLE_NOT_FOUND:
    1366                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1367                     "Error: An undefined variable was referenced (argument %d).\n", cArgs);
    1368                 break;
    1369             case VERR_PARSE_CONVERSION_FAILED:
    1370                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1371                     "Error: A conversion between two types failed (argument %d).\n", cArgs);
    1372                 break;
    1373             case VERR_PARSE_NOT_IMPLEMENTED:
    1374                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1375                     "Error: You hit a debugger feature which isn't implemented yet (argument %d).\n", cArgs);
    1376                 break;
    1377             case VERR_PARSE_BAD_RESULT_TYPE:
    1378                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1379                     "Error: Couldn't satisfy a request for a specific result type (argument %d). (Usually applies to symbols)\n", cArgs);
    1380                 break;
    1381             case VERR_PARSE_WRITEONLY_SYMBOL:
    1382                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1383                     "Error: Cannot get symbol, it's set only (argument %d).\n", cArgs);
    1384                 break;
    1385 
    1386             case VERR_DBGC_COMMAND_FAILED:
    1387                 rc = VINF_SUCCESS;
    1388                 break;
    1389 
    1390             default:
    1391                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    1392                     "Error: Unknown error %d!\n", rc);
    1393                 return rc;
    1394         }
    1395 
    1396         /*
    1397          * Parse errors are non fatal.
    1398          */
    1399         if (rc >= VERR_PARSE_FIRST && rc < VERR_PARSE_LAST)
    1400             rc = VINF_SUCCESS;
    1401     }
    1402 
    1403     return rc;
    1404 }
    1405 
    1406 
    1407276/**
    1408277 * Process all commands currently in the buffer.
     
    1470339        pDbgc->pszScratch = psz;
    1471340        pDbgc->iArg       = 0;
    1472         rc = dbgcProcessCommand(pDbgc, &pDbgc->achScratch[0], psz - &pDbgc->achScratch[0] - 1, fNoExecute);
     341        rc = dbgcEvalCommand(pDbgc, &pDbgc->achScratch[0], psz - &pDbgc->achScratch[0] - 1, fNoExecute);
    1473342        if (rc)
    1474343            break;
     
    2028897    //pDbgc->rcCmd            = 0;
    2029898
    2030     dbgcInitOpCharBitMap();
     899    dbgcEvalInit();
    2031900
    2032901    *ppDbgc = pDbgc;
  • trunk/src/VBox/Debugger/Makefile.kmk

    r35440 r35628  
    4343Debugger_SOURCES   = \
    4444        DBGConsole.cpp \
     45        DBGCEval.cpp \
    4546        DBGCBuiltInSymbols.cpp \
    4647        DBGCCmdHlp.cpp \
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