VirtualBox

Changeset 5669 in vbox


Ignore:
Timestamp:
Nov 11, 2007 5:05:02 AM (17 years ago)
Author:
vboxsync
Message:

Split out the codeview/windbg commands.

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

Legend:

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

    r5668 r5669  
    1515 * be useful, but WITHOUT ANY WARRANTY of any kind.
    1616 */
    17 
    18 
    19 /** @page pg_dbgc                       DBGC - The Debug Console
    20  *
    21  * The debugger console is a first attempt to make some interactive
    22  * debugging facilities for the VirtualBox backend (i.e. the VM). At a later
    23  * stage we'll make a fancy gui around this, but for the present a telnet (or
    24  * serial terminal) will have to suffice.
    25  *
    26  * The debugger is only built into the VM with debug builds or when
    27  * VBOX_WITH_DEBUGGER is defined. There might be need for \#ifdef'ing on this
    28  * define to enable special debugger hooks, but the general approach is to
    29  * make generic interfaces. The individual components also can register
    30  * external commands, and such code must be within \#ifdef.
    31  *
    32  *
    33  * @section sec_dbgc_op                 Operation (intentions)
    34  *
    35  * The console will process commands in a manner similar to the OS/2 and
    36  * windows kernel debuggers. This means ';' is a command separator and
    37  * that when possible we'll use the same command names as these two uses.
    38  *
    39  *
    40  * @subsection sec_dbg_op_numbers       Numbers
    41  *
    42  * Numbers are hexadecimal unless specified with a prefix indicating
    43  * elsewise. Prefixes:
    44  *      - '0x' - hexadecimal.
    45  *      - '0i' - decimal
    46  *      - '0t' - octal.
    47  *      - '0y' - binary.
    48  *
    49  *
    50  * @subsection sec_dbg_op_address       Addressing modes
    51  *
    52  *      - Default is flat. For compatability '%' also means flat.
    53  *      - Segmented addresses are specified selector:offset.
    54  *      - Physical addresses are specified using '%%'.
    55  *      - The default target for the addressing is the guest context, the '#'
    56  *        will override this and set it to the host.
    57  *
    58  *
    59  * @subsection sec_dbg_op_evalution     Evaluation
    60  *
    61  * As time permits support will be implemented support for a subset of the C
    62  * binary operators, starting with '+', '-', '*' and '/'. Support for variables
    63  * are provided thru commands 'set' and 'unset' and the unary operator '$'. The
    64  * unary '@' operator will indicate function calls. The debugger needs a set of
    65  * memory read functions, but we might later extend this to allow registration of
    66  * external functions too.
    67  *
    68  * A special command '?' will then be added which evalutates a given expression
    69  * and prints it in all the different formats.
    70  *
    71  *
    72  * @subsection sec_dbg_op_registers     Registers
    73  *
    74  * Registers are addressed using their name. Some registers which have several fields
    75  * (like gdtr) will have separate names indicating the different fields. The default
    76  * register set is the guest one. To access the hypervisor register one have to
    77  * prefix the register names with '.'.
    78  *
    79  *
    80  * @subsection sec_dbg_op_commands      Commands
    81  *
    82  * The commands are all lowercase, case sensitive, and starting with a letter. We will
    83  * later add some special commands ('?' for evaulation) and perhaps command classes ('.', '!')
    84  *
    85  *
    86  * @section sec_dbg_tasks               Tasks
    87  *
    88  * To implement DBGT and instrument VMM for basic state inspection and log
    89  * viewing, the follwing task must be executed:
    90  *
    91  *      -# Basic threading layer in RT.
    92  *      -# Basic tcpip server abstration in RT.
    93  *      -# Write DBGC.
    94  *      -# Write DBCTCP.
    95  *      -# Integrate with VMM and the rest.
    96  *      -# Start writing DBGF (VMM).
    97  */
    98 
    99 
    100 
    10117
    10218/*******************************************************************************
     
    13147*   Internal Functions                                                         *
    13248*******************************************************************************/
     49static DECLCALLBACK(int) dbgcCmdBrkAccess(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     50static DECLCALLBACK(int) dbgcCmdBrkClear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     51static DECLCALLBACK(int) dbgcCmdBrkDisable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     52static DECLCALLBACK(int) dbgcCmdBrkEnable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     53static DECLCALLBACK(int) dbgcCmdBrkList(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     54static DECLCALLBACK(int) dbgcCmdBrkSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    13355static DECLCALLBACK(int) dbgcCmdBrkREM(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    134 static DECLCALLBACK(int) dbgcCmdHelp(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    135 static DECLCALLBACK(int) dbgcCmdQuit(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    136 static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    137 static DECLCALLBACK(int) dbgcCmdStack(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     56static DECLCALLBACK(int) dbgcCmdDumpMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    13857static DECLCALLBACK(int) dbgcCmdDumpDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    13958static DECLCALLBACK(int) dbgcCmdDumpIDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     
    14362static DECLCALLBACK(int) dbgcCmdDumpPageTableBoth(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    14463static DECLCALLBACK(int) dbgcCmdDumpTSS(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    145 static DECLCALLBACK(int) dbgcCmdInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    146 static DECLCALLBACK(int) dbgcCmdLog(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    147 static DECLCALLBACK(int) dbgcCmdLogDest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    148 static DECLCALLBACK(int) dbgcCmdLogFlags(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    149 static DECLCALLBACK(int) dbgcCmdMemoryInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    150 static DECLCALLBACK(int) dbgcCmdFormat(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    151 static DECLCALLBACK(int) dbgcCmdLoadSyms(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    152 static DECLCALLBACK(int) dbgcCmdSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    153 static DECLCALLBACK(int) dbgcCmdUnset(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    154 static DECLCALLBACK(int) dbgcCmdLoadVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    155 static DECLCALLBACK(int) dbgcCmdShowVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    156 static DECLCALLBACK(int) dbgcCmdHarakiri(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    157 static DECLCALLBACK(int) dbgcCmdEcho(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    158 static DECLCALLBACK(int) dbgcCmdRunScript(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    159 
    160 static DECLCALLBACK(int) dbgcCmdBrkAccess(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    161 static DECLCALLBACK(int) dbgcCmdBrkClear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    162 static DECLCALLBACK(int) dbgcCmdBrkDisable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    163 static DECLCALLBACK(int) dbgcCmdBrkEnable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    164 static DECLCALLBACK(int) dbgcCmdBrkList(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    165 static DECLCALLBACK(int) dbgcCmdBrkSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    166 static DECLCALLBACK(int) dbgcCmdDumpMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    16764static DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    16865static DECLCALLBACK(int) dbgcCmdListSource(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    16966static DECLCALLBACK(int) dbgcCmdListNear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     67static DECLCALLBACK(int) dbgcCmdMemoryInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    17068static DECLCALLBACK(int) dbgcCmdReg(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    17169static DECLCALLBACK(int) dbgcCmdRegGuest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     
    17371static DECLCALLBACK(int) dbgcCmdRegTerse(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    17472static DECLCALLBACK(int) dbgcCmdSearchMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     73static DECLCALLBACK(int) dbgcCmdStack(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    17574static DECLCALLBACK(int) dbgcCmdTrace(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    17675static DECLCALLBACK(int) dbgcCmdUnassemble(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    177 
    178 static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    179 static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    180 static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    181 static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    182 static DECLCALLBACK(int) dbgcOpAddrFlat(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    183 static DECLCALLBACK(int) dbgcOpAddrPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    184 static DECLCALLBACK(int) dbgcOpAddrHost(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    185 static DECLCALLBACK(int) dbgcOpAddrHostPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    186 static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
    187 
    188 static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    189 static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    190 static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    191 static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    192 static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    193 static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    194 static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    195 static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    196 static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    197 static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    198 static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    199 static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    200 static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    201 static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    202 static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    203 static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
    204 
    205 static DECLCALLBACK(int) dbgcSymGetReg(PCDBGCSYM pSymDesc, PDBGCCMDHLP pCmdHlp, DBGCVARTYPE enmType, PDBGCVAR pResult);
    206 static DECLCALLBACK(int) dbgcSymSetReg(PCDBGCSYM pSymDesc, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pValue);
    207 
    208 static void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat);
    209 static void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb);
    210 static void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2);
    211 static void dbgcVarSetNoRange(PDBGCVAR pVar);
    212 static void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb);
    213 static int dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress);
    214 
    215 static int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
    216 static int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
    217 static int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp);
    218 static PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp);
    219 static int dbgcBpExec(PDBGC pDbgc, RTUINT iBp);
    220 
    221 static PCDBGCSYM dbgcLookupRegisterSymbol(PDBGC pDbgc, const char *pszSymbol);
    222 static int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGCVAR pResult);
    223 static int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult);
    224 static int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd);
    22576
    22677
     
    22879*   Global Variables                                                           *
    22980*******************************************************************************/
    230 /**
    231  * Pointer to head of the list of external commands.
    232  */
    233 static PDBGCEXTCMDS     g_pExtCmdsHead;     /** @todo rw protect g_pExtCmdsHead! */
    234 /** Locks the g_pExtCmdsHead list for reading. */
    235 #define DBGCEXTCMDS_LOCK_RD()       do { } while (0)
    236 /** Locks the g_pExtCmdsHead list for writing. */
    237 #define DBGCEXTCMDS_LOCK_WR()       do { } while (0)
    238 /** UnLocks the g_pExtCmdsHead list after reading. */
    239 #define DBGCEXTCMDS_UNLOCK_RD()     do { } while (0)
    240 /** UnLocks the g_pExtCmdsHead list after writing. */
    241 #define DBGCEXTCMDS_UNLOCK_WR()     do { } while (0)
    242 
    243 
    244 /** One argument of any kind. */
    245 static const DBGCVARDESC    g_aArgAny[] =
    246 {
    247     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    248     {  0,           1,          DBGCVAR_CAT_ANY,        0,                              "var",          "Any type of argument." },
    249 };
    250 
    251 /** Multiple string arguments (min 1). */
    252 static const DBGCVARDESC    g_aArgMultiStr[] =
    253 {
    254     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    255     {  1,           ~0,         DBGCVAR_CAT_STRING,     0,                              "strings",      "One or more strings." },
    256 };
    257 
    258 /** Filename string. */
    259 static const DBGCVARDESC    g_aArgFilename[] =
    260 {
    261     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    262     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "path",         "Filename string." },
    263 };
    264 
    265 
    266 /** 'br' arguments. */
    267 static const DBGCVARDESC    g_aArgBrkREM[] =
    268 {
    269     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    270     {  1,           1,          DBGCVAR_CAT_GC_POINTER, 0,                              "address",      "The address." },
    271     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "passes",       "The number of passes before we trigger the breakpoint. (0 is default)" },
    272     {  0,           1,          DBGCVAR_CAT_NUMBER,     DBGCVD_FLAGS_DEP_PREV,          "max passes",   "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
    273     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "cmds",         "String of commands to be executed when the breakpoint is hit. Quote it!" },
    274 };
    275 
    276 
    277 /** 'dg', 'dga', 'dl', 'dla' arguments. */
    278 static const DBGCVARDESC    g_aArgDumpDT[] =
    279 {
    280     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    281     {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "sel",          "Selector or selector range." },
    282     {  0,           ~0,         DBGCVAR_CAT_POINTER,    0,                              "address",      "Far address which selector should be dumped." },
    283 };
    284 
    285 
    286 /** 'di', 'dia' arguments. */
    287 static const DBGCVARDESC    g_aArgDumpIDT[] =
    288 {
    289     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    290     {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "int",          "The interrupt vector or interrupt vector range." },
    291 };
    292 
    293 
    294 /** 'dpd*' arguments. */
    295 static const DBGCVARDESC    g_aArgDumpPD[] =
    296 {
    297     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    298     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "index",        "Index into the page directory." },
    299     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address which page directory entry to start dumping from. Range is applied to the page directory." },
    300 };
    301 
    302 
    303 /** 'dpda' arguments. */
    304 static const DBGCVARDESC    g_aArgDumpPDAddr[] =
    305 {
    306     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    307     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address of the page directory entry to start dumping from." },
    308 };
    309 
    310 
    311 /** 'dpt?' arguments. */
    312 static const DBGCVARDESC    g_aArgDumpPT[] =
    313 {
    314     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    315     {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address which page directory entry to start dumping from." },
    316 };
    317 
    318 
    319 /** 'dpta' arguments. */
    320 static const DBGCVARDESC    g_aArgDumpPTAddr[] =
    321 {
    322     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    323     {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address of the page table entry to start dumping from." },
    324 };
    325 
    326 
    327 /** 'dt' arguments. */
    328 static const DBGCVARDESC    g_aArgDumpTSS[] =
    329 {
    330     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    331     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "tss",          "TSS selector number." },
    332     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "tss:ign|addr", "TSS address. If the selector is a TSS selector, the offset will be ignored." }
    333 };
    334 
    335 
    336 /** 'help' arguments. */
    337 static const DBGCVARDESC    g_aArgHelp[] =
    338 {
    339     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    340     {  0,           ~0,         DBGCVAR_CAT_STRING,     0,                              "cmd/op",       "Zero or more command or operator names." },
    341 };
    342 
    343 
    344 /** 'info' arguments. */
    345 static const DBGCVARDESC    g_aArgInfo[] =
    346 {
    347     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    348     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "info",         "The name of the info to display." },
    349     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "args",         "String arguments to the handler." },
    350 };
    351 
    352 
    353 /** loadsyms arguments. */
    354 static const DBGCVARDESC    g_aArgLoadSyms[] =
    355 {
    356     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    357     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "path",         "Filename string." },
    358     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "delta",        "Delta to add to the loaded symbols. (optional)" },
    359     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "module name",  "Module name." },
    360     {  0,           1,          DBGCVAR_CAT_POINTER,    DBGCVD_FLAGS_DEP_PREV,          "module address", "Module address." },
    361     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "module size",  "The module size. (optional)" },
    362 };
    363 
    364 
    365 /** log arguments. */
    366 static const DBGCVARDESC    g_aArgLog[] =
    367 {
    368     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    369     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "groups",       "Group modifier string (quote it!)." }
    370 };
    371 
    372 
    373 /** logdest arguments. */
    374 static const DBGCVARDESC    g_aArgLogDest[] =
    375 {
    376     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    377     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "dests",        "Destination modifier string (quote it!)." }
    378 };
    379 
    380 
    381 /** logflags arguments. */
    382 static const DBGCVARDESC    g_aArgLogFlags[] =
    383 {
    384     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    385     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "flags",        "Flag modifier string (quote it!)." }
    386 };
    387 
    388 
    389 /** 'set' arguments */
    390 static const DBGCVARDESC    g_aArgSet[] =
    391 {
    392     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    393     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "var",          "Variable name." },
    394     {  1,           1,          DBGCVAR_CAT_ANY,        0,                              "value",        "Value to assign to the variable." },
    395 };
    396 
    397 
    398 
    399 
    400 
    401 /** Command descriptors for the basic commands. */
    402 static const DBGCCMD    g_aCmds[] =
    403 {
    404     /* pszCmd,      cArgsMin, cArgsMax, paArgDescs,         cArgDescs,                  pResultDesc,        fFlags,     pfnHandler          pszSyntax,          ....pszDescription */
    405     { "br",         1,        4,        &g_aArgBrkREM[0],   ELEMENTS(g_aArgBrkREM),     NULL,               0,          dbgcCmdBrkREM,      "<address> [passes [max passes]] [cmds]",
    406                                                                                                                                                                     "Sets a recompiler specific breakpoint." },
    407     { "bye",        0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
    408     { "dg",         0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the global descriptor table (GDT)." },
    409     { "dga",        0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the global descriptor table (GDT) including not-present entries." },
    410     { "di",         0,       ~0,        &g_aArgDumpIDT[0],  ELEMENTS(g_aArgDumpIDT),    NULL,               0,          dbgcCmdDumpIDT,     "[int [..]]",           "Dump the interrupt descriptor table (IDT)." },
    411     { "dia",        0,       ~0,        &g_aArgDumpIDT[0],  ELEMENTS(g_aArgDumpIDT),    NULL,               0,          dbgcCmdDumpIDT,     "[int [..]]",           "Dump the interrupt descriptor table (IDT) including not-present entries." },
    412     { "dl",         0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the local descriptor table (LDT)." },
    413     { "dla",        0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the local descriptor table (LDT) including not-present entries." },
    414     { "dpd",        0,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the default context." },
    415     { "dpda",       0,        1,        &g_aArgDumpPDAddr[0],ELEMENTS(g_aArgDumpPDAddr),NULL,               0,          dbgcCmdDumpPageDir, "[addr]",               "Dumps specified page directory." },
    416     { "dpdb",       1,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDirBoth, "[addr] [index]",   "Dumps page directory entries of the guest and the hypervisor. " },
    417     { "dpdg",       0,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the guest." },
    418     { "dpdh",       0,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the hypervisor. " },
    419     { "dpt",        1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the default context." },
    420     { "dpta",       1,        1,        &g_aArgDumpPTAddr[0],ELEMENTS(g_aArgDumpPTAddr), NULL,              0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps specified page table." },
    421     { "dptb",       1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTableBoth,"<addr>",          "Dumps page table entries of the guest and the hypervisor." },
    422     { "dptg",       1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the guest." },
    423     { "dpth",       1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the hypervisor." },
    424     { "dt",         0,        1,        &g_aArgDumpTSS[0],  ELEMENTS(g_aArgDumpTSS),    NULL,               0,          dbgcCmdDumpTSS,     "[tss|tss:ign|addr]",   "Dump the task state segment (TSS)." },
    425     { "echo",       1,        ~0,       &g_aArgMultiStr[0], ELEMENTS(g_aArgMultiStr),   NULL,               0,          dbgcCmdEcho,        "<str1> [str2..[strN]]", "Displays the strings separated by one blank space and the last one followed by a newline." },
    426     { "exit",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
    427     { "format",     1,        1,        &g_aArgAny[0],      ELEMENTS(g_aArgAny),        NULL,               0,          dbgcCmdFormat,      "",                     "Evaluates an expression and formats it." },
    428     { "harakiri",   0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdHarakiri,    "",                     "Kills debugger process." },
    429     { "help",       0,        ~0,       &g_aArgHelp[0],     ELEMENTS(g_aArgHelp),       NULL,               0,          dbgcCmdHelp,        "[cmd/op [..]]",        "Display help. For help about info items try 'info help'." },
    430     { "info",       1,        2,        &g_aArgInfo[0],     ELEMENTS(g_aArgInfo),       NULL,               0,          dbgcCmdInfo,        "<info> [args]",        "Display info register in the DBGF. For a list of info items try 'info help'." },
    431     { "loadsyms",   1,        5,        &g_aArgLoadSyms[0], ELEMENTS(g_aArgLoadSyms),   NULL,               0,          dbgcCmdLoadSyms,    "<filename> [delta] [module] [module address]", "Loads symbols from a text file. Optionally giving a delta and a module." },
    432     { "loadvars",   1,        1,        &g_aArgFilename[0], ELEMENTS(g_aArgFilename),   NULL,               0,          dbgcCmdLoadVars,    "<filename>",           "Load variables from file. One per line, same as the args to the set command." },
    433     { "log",        1,        1,        &g_aArgLog[0],      ELEMENTS(g_aArgLog),        NULL,               0,          dbgcCmdLog,         "<group string>",       "Modifies the logging group settings (VBOX_LOG)" },
    434     { "logdest",    1,        1,        &g_aArgLogDest[0],  ELEMENTS(g_aArgLogDest),    NULL,               0,          dbgcCmdLogDest,     "<dest string>",        "Modifies the logging destination (VBOX_LOG_DEST)." },
    435     { "logflags",   1,        1,        &g_aArgLogFlags[0], ELEMENTS(g_aArgLogFlags),   NULL,               0,          dbgcCmdLogFlags,    "<flags string>",       "Modifies the logging flags (VBOX_LOG_FLAGS)." },
    436     { "quit",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
    437     { "runscript",  1,        1,        &g_aArgFilename[0], ELEMENTS(g_aArgFilename),   NULL,               0,          dbgcCmdRunScript,   "<filename>",           "Runs the command listed in the script. Lines starting with '#' (after removing blanks) are comment. blank lines are ignored. Stops on failure." },
    438     { "set",        2,        2,        &g_aArgSet[0],      ELEMENTS(g_aArgSet),        NULL,               0,          dbgcCmdSet,         "<var> <value>",        "Sets a global variable." },
    439     { "showvars",   0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdShowVars,    "",                     "List all the defined variables." },
    440     { "stop",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdStop,        "",                     "Stop execution." },
    441     { "unset",      1,        ~0,       &g_aArgMultiStr[0], ELEMENTS(g_aArgMultiStr),   NULL,               0,          dbgcCmdUnset,       "<var1> [var1..[varN]]", "Unsets (delete) one or more global variables." },
    442 };
    443 
    444 
    44581/** 'ba' arguments. */
    44682static const DBGCVARDESC    g_aArgBrkAcc[] =
     
    476112
    477113
     114/** 'br' arguments. */
     115static const DBGCVARDESC    g_aArgBrkREM[] =
     116{
     117    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     118    {  1,           1,          DBGCVAR_CAT_GC_POINTER, 0,                              "address",      "The address." },
     119    {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "passes",       "The number of passes before we trigger the breakpoint. (0 is default)" },
     120    {  0,           1,          DBGCVAR_CAT_NUMBER,     DBGCVD_FLAGS_DEP_PREV,          "max passes",   "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
     121    {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "cmds",         "String of commands to be executed when the breakpoint is hit. Quote it!" },
     122};
     123
     124
    478125/** 'd?' arguments. */
    479126static const DBGCVARDESC    g_aArgDumpMem[] =
     
    481128    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    482129    {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address where to start dumping memory." },
     130};
     131
     132
     133/** 'dg', 'dga', 'dl', 'dla' arguments. */
     134static const DBGCVARDESC    g_aArgDumpDT[] =
     135{
     136    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     137    {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "sel",          "Selector or selector range." },
     138    {  0,           ~0,         DBGCVAR_CAT_POINTER,    0,                              "address",      "Far address which selector should be dumped." },
     139};
     140
     141
     142/** 'di', 'dia' arguments. */
     143static const DBGCVARDESC    g_aArgDumpIDT[] =
     144{
     145    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     146    {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "int",          "The interrupt vector or interrupt vector range." },
     147};
     148
     149
     150/** 'dpd*' arguments. */
     151static const DBGCVARDESC    g_aArgDumpPD[] =
     152{
     153    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     154    {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "index",        "Index into the page directory." },
     155    {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address which page directory entry to start dumping from. Range is applied to the page directory." },
     156};
     157
     158
     159/** 'dpda' arguments. */
     160static const DBGCVARDESC    g_aArgDumpPDAddr[] =
     161{
     162    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     163    {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address of the page directory entry to start dumping from." },
     164};
     165
     166
     167/** 'dpt?' arguments. */
     168static const DBGCVARDESC    g_aArgDumpPT[] =
     169{
     170    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     171    {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address which page directory entry to start dumping from." },
     172};
     173
     174
     175/** 'dpta' arguments. */
     176static const DBGCVARDESC    g_aArgDumpPTAddr[] =
     177{
     178    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     179    {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address of the page table entry to start dumping from." },
     180};
     181
     182
     183/** 'dt' arguments. */
     184static const DBGCVARDESC    g_aArgDumpTSS[] =
     185{
     186    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     187    {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "tss",          "TSS selector number." },
     188    {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "tss:ign|addr", "TSS address. If the selector is a TSS selector, the offset will be ignored." }
    483189};
    484190
     
    544250 * The emulation isn't attempting to be identical, only somewhat similar.
    545251 */
    546 static const DBGCCMD    g_aCmdsCodeView[] =
     252const DBGCCMD    g_aCmdsCodeView[] =
    547253{
    548254    /* pszCmd,      cArgsMin, cArgsMax, paArgDescs,         cArgDescs,                     pResultDesc,        fFlags,  pfnHandler          pszSyntax,          ....pszDescription */
     
    554260    { "bl",         0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdBrkList,     "",                     "Lists all the breakpoints." },
    555261    { "bp",         1,        4,        &g_aArgBrkSet[0],   RT_ELEMENTS(g_aArgBrkSet),     NULL,               0,       dbgcCmdBrkSet,      "<address> [passes [max passes]] [cmds]",
    556                                                                                                                                                                  "Sets a breakpoint (int 3)." },
     262                                                                                                                                                                    "Sets a breakpoint (int 3)." },
     263    { "br",         1,        4,        &g_aArgBrkREM[0],   RT_ELEMENTS(g_aArgBrkREM),     NULL,               0,       dbgcCmdBrkREM,      "<address> [passes [max passes]] [cmds]",
     264                                                                                                                                                                    "Sets a recompiler specific breakpoint." },
    557265    { "d",          0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory using last element size." },
    558266    { "da",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory as ascii string." },
    559267    { "db",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in bytes." },
    560268    { "dd",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in double words." },
     269    { "dg",         0,       ~0,        &g_aArgDumpDT[0],   RT_ELEMENTS(g_aArgDumpDT),     NULL,               0,       dbgcCmdDumpDT,      "[sel [..]]",           "Dump the global descriptor table (GDT)." },
     270    { "dga",        0,       ~0,        &g_aArgDumpDT[0],   RT_ELEMENTS(g_aArgDumpDT),     NULL,               0,       dbgcCmdDumpDT,      "[sel [..]]",           "Dump the global descriptor table (GDT) including not-present entries." },
     271    { "di",         0,       ~0,        &g_aArgDumpIDT[0],  RT_ELEMENTS(g_aArgDumpIDT),    NULL,               0,       dbgcCmdDumpIDT,     "[int [..]]",           "Dump the interrupt descriptor table (IDT)." },
     272    { "dia",        0,       ~0,        &g_aArgDumpIDT[0],  RT_ELEMENTS(g_aArgDumpIDT),    NULL,               0,       dbgcCmdDumpIDT,     "[int [..]]",           "Dump the interrupt descriptor table (IDT) including not-present entries." },
     273    { "dl",         0,       ~0,        &g_aArgDumpDT[0],   RT_ELEMENTS(g_aArgDumpDT),     NULL,               0,       dbgcCmdDumpDT,      "[sel [..]]",           "Dump the local descriptor table (LDT)." },
     274    { "dla",        0,       ~0,        &g_aArgDumpDT[0],   RT_ELEMENTS(g_aArgDumpDT),     NULL,               0,       dbgcCmdDumpDT,      "[sel [..]]",           "Dump the local descriptor table (LDT) including not-present entries." },
     275    { "dpd",        0,        1,        &g_aArgDumpPD[0],   RT_ELEMENTS(g_aArgDumpPD),     NULL,               0,       dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the default context." },
     276    { "dpda",       0,        1,        &g_aArgDumpPDAddr[0],RT_ELEMENTS(g_aArgDumpPDAddr),NULL,               0,       dbgcCmdDumpPageDir, "[addr]",               "Dumps specified page directory." },
     277    { "dpdb",       1,        1,        &g_aArgDumpPD[0],   RT_ELEMENTS(g_aArgDumpPD),     NULL,               0,       dbgcCmdDumpPageDirBoth, "[addr] [index]",   "Dumps page directory entries of the guest and the hypervisor. " },
     278    { "dpdg",       0,        1,        &g_aArgDumpPD[0],   RT_ELEMENTS(g_aArgDumpPD),     NULL,               0,       dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the guest." },
     279    { "dpdh",       0,        1,        &g_aArgDumpPD[0],   RT_ELEMENTS(g_aArgDumpPD),     NULL,               0,       dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the hypervisor. " },
     280    { "dpt",        1,        1,        &g_aArgDumpPT[0],   RT_ELEMENTS(g_aArgDumpPT),     NULL,               0,       dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the default context." },
     281    { "dpta",       1,        1,        &g_aArgDumpPTAddr[0],RT_ELEMENTS(g_aArgDumpPTAddr), NULL,              0,       dbgcCmdDumpPageTable,"<addr>",              "Dumps specified page table." },
     282    { "dptb",       1,        1,        &g_aArgDumpPT[0],   RT_ELEMENTS(g_aArgDumpPT),     NULL,               0,       dbgcCmdDumpPageTableBoth,"<addr>",          "Dumps page table entries of the guest and the hypervisor." },
     283    { "dptg",       1,        1,        &g_aArgDumpPT[0],   RT_ELEMENTS(g_aArgDumpPT),     NULL,               0,       dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the guest." },
     284    { "dpth",       1,        1,        &g_aArgDumpPT[0],   RT_ELEMENTS(g_aArgDumpPT),     NULL,               0,       dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the hypervisor." },
    561285    { "dq",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in quad words." },
     286    { "dt",         0,        1,        &g_aArgDumpTSS[0],  RT_ELEMENTS(g_aArgDumpTSS),    NULL,               0,       dbgcCmdDumpTSS,     "[tss|tss:ign|addr]",   "Dump the task state segment (TSS)." },
    562287    { "dw",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in words." },
    563288    { "g",          0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdGo,          "",                     "Continue execution." },
     
    583308};
    584309
    585 
    586 /** Operators. */
    587 static const DBGCOP g_aOps[] =
    588 {
    589     /* szName is initialized as a 4 char array because of M$C elsewise optimizing it away in /Ox mode (the 'const char' vs 'char' problem). */
    590     /* szName,          cchName, fBinary,    iPrecedence,    pfnHandlerUnary,    pfnHandlerBitwise  */
    591     { {'-'},            1,       false,      1,              dbgcOpMinus,        NULL,                       "Unary minus." },
    592     { {'+'},            1,       false,      1,              dbgcOpPluss,        NULL,                       "Unary pluss." },
    593     { {'!'},            1,       false,      1,              dbgcOpBooleanNot,   NULL,                       "Boolean not." },
    594     { {'~'},            1,       false,      1,              dbgcOpBitwiseNot,   NULL,                       "Bitwise complement." },
    595     { {':'},            1,       true,       2,              NULL,               dbgcOpAddrFar,              "Far pointer." },
    596     { {'%'},            1,       false,      3,              dbgcOpAddrFlat,     NULL,                       "Flat address." },
    597     { {'%','%'},        2,       false,      3,              dbgcOpAddrPhys,     NULL,                       "Physical address." },
    598     { {'#'},            1,       false,      3,              dbgcOpAddrHost,     NULL,                       "Flat host address." },
    599     { {'#','%','%'},    3,       false,      3,              dbgcOpAddrHostPhys, NULL,                       "Physical host address." },
    600     { {'$'},            1,       false,      3,              dbgcOpVar,          NULL,                       "Reference a variable." },
    601     { {'*'},            1,       true,       10,             NULL,               dbgcOpMult,                 "Multiplication." },
    602     { {'/'},            1,       true,       11,             NULL,               dbgcOpDiv,                  "Division." },
    603     { {'%'},            1,       true,       12,             NULL,               dbgcOpMod,                  "Modulus." },
    604     { {'+'},            1,       true,       13,             NULL,               dbgcOpAdd,                  "Addition." },
    605     { {'-'},            1,       true,       14,             NULL,               dbgcOpSub,                  "Subtraction." },
    606     { {'<','<'},        2,       true,       15,             NULL,               dbgcOpBitwiseShiftLeft,     "Bitwise left shift." },
    607     { {'>','>'},        2,       true,       16,             NULL,               dbgcOpBitwiseShiftRight,    "Bitwise right shift." },
    608     { {'&'},            1,       true,       17,             NULL,               dbgcOpBitwiseAnd,           "Bitwise and." },
    609     { {'^'},            1,       true,       18,             NULL,               dbgcOpBitwiseXor,           "Bitwise exclusiv or." },
    610     { {'|'},            1,       true,       19,             NULL,               dbgcOpBitwiseOr,            "Bitwise inclusive or." },
    611     { {'&','&'},        2,       true,       20,             NULL,               dbgcOpBooleanAnd,           "Boolean and." },
    612     { {'|','|'},        2,       true,       21,             NULL,               dbgcOpBooleanOr,            "Boolean or." },
    613     { {'L'},            1,       true,       22,             NULL,               dbgcOpRangeLength,          "Range elements." },
    614     { {'L','B'},        2,       true,       23,             NULL,               dbgcOpRangeLengthBytes,     "Range bytes." },
    615     { {'T'},            1,       true,       24,             NULL,               dbgcOpRangeTo,              "Range to." }
    616 };
    617 
    618 /** Bitmap where set bits indicates the characters the may start an operator name. */
    619 static uint32_t g_bmOperatorChars[256 / (4*8)];
    620 
    621 /** Register symbol uUser value.
    622  * @{
    623  */
    624 /** If set the register set is the hypervisor and not the guest one. */
    625 #define SYMREG_FLAGS_HYPER      RT_BIT(20)
    626 /** If set a far conversion of the value will use the high 16 bit for the selector.
    627  * If clear the low 16 bit will be used. */
    628 #define SYMREG_FLAGS_HIGH_SEL   RT_BIT(21)
    629 /** The shift value to calc the size of a register symbol from the uUser value. */
    630 #define SYMREG_SIZE_SHIFT       (24)
    631 /** Get the offset */
    632 #define SYMREG_OFFSET(uUser)    (uUser & ((1 << 20) - 1))
    633 /** Get the size. */
    634 #define SYMREG_SIZE(uUser)      ((uUser >> SYMREG_SIZE_SHIFT) & 0xff)
    635 /** 1 byte. */
    636 #define SYMREG_SIZE_1           ( 1 << SYMREG_SIZE_SHIFT)
    637 /** 2 byte. */
    638 #define SYMREG_SIZE_2           ( 2 << SYMREG_SIZE_SHIFT)
    639 /** 4 byte. */
    640 #define SYMREG_SIZE_4           ( 4 << SYMREG_SIZE_SHIFT)
    641 /** 6 byte. */
    642 #define SYMREG_SIZE_6           ( 6 << SYMREG_SIZE_SHIFT)
    643 /** 8 byte. */
    644 #define SYMREG_SIZE_8           ( 8 << SYMREG_SIZE_SHIFT)
    645 /** 12 byte. */
    646 #define SYMREG_SIZE_12          (12 << SYMREG_SIZE_SHIFT)
    647 /** 16 byte. */
    648 #define SYMREG_SIZE_16          (16 << SYMREG_SIZE_SHIFT)
    649 /** @} */
    650 
    651 /** Builtin Symbols.
    652  * ASSUMES little endian register representation!
    653  */
    654 static const DBGCSYM    g_aSyms[] =
    655 {
    656     { "eax",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax)      | SYMREG_SIZE_4 },
    657     { "ax",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax)      | SYMREG_SIZE_2 },
    658     { "al",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax)      | SYMREG_SIZE_1 },
    659     { "ah",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax) + 1  | SYMREG_SIZE_1 },
    660 
    661     { "ebx",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx)      | SYMREG_SIZE_4 },
    662     { "bx",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx)      | SYMREG_SIZE_2 },
    663     { "bl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx)      | SYMREG_SIZE_1 },
    664     { "bh",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx) + 1  | SYMREG_SIZE_1 },
    665 
    666     { "ecx",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx)      | SYMREG_SIZE_4 },
    667     { "cx",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx)      | SYMREG_SIZE_2 },
    668     { "cl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx)      | SYMREG_SIZE_1 },
    669     { "ch",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx) + 1  | SYMREG_SIZE_1 },
    670 
    671     { "edx",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx)      | SYMREG_SIZE_4 },
    672     { "dx",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx)      | SYMREG_SIZE_2 },
    673     { "dl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx)      | SYMREG_SIZE_1 },
    674     { "dh",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx) + 1  | SYMREG_SIZE_1 },
    675 
    676     { "edi",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edi)      | SYMREG_SIZE_4 },
    677     { "di",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edi)      | SYMREG_SIZE_2 },
    678 
    679     { "esi",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esi)      | SYMREG_SIZE_4 },
    680     { "si",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esi)      | SYMREG_SIZE_2 },
    681 
    682     { "ebp",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebp)      | SYMREG_SIZE_4 },
    683     { "bp",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebp)      | SYMREG_SIZE_2 },
    684 
    685     { "esp",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esp)      | SYMREG_SIZE_4 },
    686     { "sp",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esp)      | SYMREG_SIZE_2 },
    687 
    688     { "eip",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eip)      | SYMREG_SIZE_4 },
    689     { "ip",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eip)      | SYMREG_SIZE_2 },
    690 
    691     { "efl",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_4 },
    692     { "eflags", dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_4 },
    693     { "fl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_2 },
    694     { "flags",  dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_2 },
    695 
    696     { "cs",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cs)       | SYMREG_SIZE_2 },
    697     { "ds",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ds)       | SYMREG_SIZE_2 },
    698     { "es",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, es)       | SYMREG_SIZE_2 },
    699     { "fs",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, fs)       | SYMREG_SIZE_2 },
    700     { "gs",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, gs)       | SYMREG_SIZE_2 },
    701     { "ss",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ss)       | SYMREG_SIZE_2 },
    702 
    703     { "cr0",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr0)      | SYMREG_SIZE_4 },
    704     { "cr2",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr2)      | SYMREG_SIZE_4 },
    705     { "cr3",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr3)      | SYMREG_SIZE_4 },
    706     { "cr4",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr4)      | SYMREG_SIZE_4 },
    707 
    708     { "tr",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, tr)       | SYMREG_SIZE_2 },
    709     { "ldtr",   dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ldtr)     | SYMREG_SIZE_2 },
    710 
    711     { "gdtr",   dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, gdtr)     | SYMREG_SIZE_6 },
    712     { "gdtr.limit", dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, gdtr.cbGdt)| SYMREG_SIZE_2 },
    713     { "gdtr.base",  dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, gdtr.pGdt)| SYMREG_SIZE_4 },
    714 
    715     { "idtr",   dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, idtr)     | SYMREG_SIZE_6 },
    716     { "idtr.limit", dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, idtr.cbIdt)| SYMREG_SIZE_2 },
    717     { "idtr.base",  dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, idtr.pIdt)| SYMREG_SIZE_4 },
    718 
    719     /* hypervisor */
    720 
    721     {".eax",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    722     {".ax",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    723     {".al",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax)      | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    724     {".ah",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eax) + 1  | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    725 
    726     {".ebx",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    727     {".bx",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    728     {".bl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx)      | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    729     {".bh",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebx) + 1  | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    730 
    731     {".ecx",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    732     {".cx",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    733     {".cl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx)      | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    734     {".ch",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ecx) + 1  | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    735 
    736     {".edx",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    737     {".dx",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    738     {".dl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx)      | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    739     {".dh",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edx) + 1  | SYMREG_SIZE_1 | SYMREG_FLAGS_HYPER },
    740 
    741     {".edi",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edi)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    742     {".di",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, edi)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    743 
    744     {".esi",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esi)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    745     {".si",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esi)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    746 
    747     {".ebp",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebp)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    748     {".bp",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ebp)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    749 
    750     {".esp",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esp)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    751     {".sp",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, esp)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    752 
    753     {".eip",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eip)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    754     {".ip",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eip)      | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    755 
    756     {".efl",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    757     {".eflags", dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    758     {".fl",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    759     {".flags",  dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, eflags)   | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    760 
    761     {".cs",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cs)       | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    762     {".ds",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ds)       | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    763     {".es",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, es)       | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    764     {".fs",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, fs)       | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    765     {".gs",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, gs)       | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    766     {".ss",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ss)       | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    767 
    768     {".cr0",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr0)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    769     {".cr2",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr2)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    770     {".cr3",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr3)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    771     {".cr4",    dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, cr4)      | SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    772 
    773     {".tr",     dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, tr)       | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    774     {".ldtr",   dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, ldtr)     | SYMREG_SIZE_2 | SYMREG_FLAGS_HYPER },
    775 
    776     {".gdtr",   dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, gdtr)     | SYMREG_SIZE_6 | SYMREG_FLAGS_HYPER },
    777     {".gdtr.limit", dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, gdtr.cbGdt)| SYMREG_SIZE_2| SYMREG_FLAGS_HYPER },
    778     {".gdtr.base",  dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, gdtr.pGdt)| SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    779 
    780     {".idtr",   dbgcSymGetReg,          dbgcSymSetReg,      offsetof(CPUMCTX, idtr)     | SYMREG_SIZE_6 | SYMREG_FLAGS_HYPER },
    781     {".idtr.limit", dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, idtr.cbIdt)| SYMREG_SIZE_2| SYMREG_FLAGS_HYPER },
    782     {".idtr.base",  dbgcSymGetReg,      dbgcSymSetReg,      offsetof(CPUMCTX, idtr.pIdt)| SYMREG_SIZE_4 | SYMREG_FLAGS_HYPER },
    783 
    784 };
    785 
    786 
    787 /**
    788  * Prints full command help.
    789  */
    790 static int dbgcPrintHelp(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, bool fExternal)
    791 {
    792     int rc;
    793 
    794     /* the command */
    795     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    796                             "%s%-*s %-30s %s",
    797                             fExternal ? "." : "",
    798                             fExternal ? 10 : 11,
    799                             pCmd->pszCmd,
    800                             pCmd->pszSyntax,
    801                             pCmd->pszDescription);
    802     if (!pCmd->cArgsMin && pCmd->cArgsMin == pCmd->cArgsMax)
    803         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <no args>\n");
    804     else if (pCmd->cArgsMin == pCmd->cArgsMax)
    805         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u args>\n", pCmd->cArgsMin);
    806     else if (pCmd->cArgsMax == ~0U)
    807         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u+ args>\n", pCmd->cArgsMin);
    808     else
    809         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u to %u args>\n", pCmd->cArgsMin, pCmd->cArgsMax);
    810 
    811     /* argument descriptions. */
    812     for (unsigned i = 0; i < pCmd->cArgDescs; i++)
    813     {
    814         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    815                                 "    %-12s %s",
    816                                 pCmd->paArgDescs[i].pszName,
    817                                 pCmd->paArgDescs[i].pszDescription);
    818         if (!pCmd->paArgDescs[i].cTimesMin)
    819         {
    820             if (pCmd->paArgDescs[i].cTimesMax == ~0U)
    821                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <optional+>\n");
    822             else
    823                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <optional-%u>\n", pCmd->paArgDescs[i].cTimesMax);
    824         }
    825         else
    826         {
    827             if (pCmd->paArgDescs[i].cTimesMax == ~0U)
    828                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u+>\n", pCmd->paArgDescs[i].cTimesMin);
    829             else
    830                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u-%u>\n", pCmd->paArgDescs[i].cTimesMin, pCmd->paArgDescs[i].cTimesMax);
    831         }
    832     }
    833     return rc;
    834 }
    835 
    836 
    837 /**
    838  * The 'help' command.
     310/** The number of commands in the CodeView/WinDbg emulation. */
     311const unsigned g_cCmdsCodeView = RT_ELEMENTS(g_aCmdsCodeView);
     312
     313
     314
     315/**
     316 * The 'go' command.
    839317 *
    840318 * @returns VBox status.
     
    845323 * @param   cArgs       Number of arguments in the array.
    846324 */
    847 static DECLCALLBACK(int) dbgcCmdHelp(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    848 {
    849     PDBGC       pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    850     int         rc = VINF_SUCCESS;
    851     unsigned    i;
    852 
    853     if (!cArgs)
    854     {
    855         /*
    856          * All the stuff.
    857          */
    858         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    859                                 "VirtualBox Debugger\n"
    860                                 "-------------------\n"
    861                                 "\n"
    862                                 "Commands and Functions:\n");
    863         for (i = 0; i < ELEMENTS(g_aCmds); i++)
    864             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    865                                     "%-11s %-30s %s\n",
    866                                     g_aCmds[i].pszCmd,
    867                                     g_aCmds[i].pszSyntax,
    868                                     g_aCmds[i].pszDescription);
    869         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    870                                 "\n"
    871                                 "Emulation: %s\n", pDbgc->pszEmulation);
    872         PCDBGCCMD pCmd = pDbgc->paEmulationCmds;
    873         for (i = 0; i < pDbgc->cEmulationCmds; i++, pCmd++)
    874             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    875                                     "%-11s %-30s %s\n",
    876                                     pCmd->pszCmd,
    877                                     pCmd->pszSyntax,
    878                                     pCmd->pszDescription);
    879 
    880         if (g_pExtCmdsHead)
    881         {
    882             DBGCEXTCMDS_LOCK_RD();
    883             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    884                                     "\n"
    885                                     "External Commands and Functions:\n");
    886             for (PDBGCEXTCMDS pExtCmd = g_pExtCmdsHead; pExtCmd; pExtCmd = pExtCmd->pNext)
    887                 for (i = 0; i < pExtCmd->cCmds; i++)
    888                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    889                                             ".%-10s %-30s %s\n",
    890                                             pExtCmd->paCmds[i].pszCmd,
    891                                             pExtCmd->paCmds[i].pszSyntax,
    892                                             pExtCmd->paCmds[i].pszDescription);
    893             DBGCEXTCMDS_UNLOCK_RD();
    894         }
    895 
    896         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    897                                 "\n"
    898                                 "Operators:\n");
    899         unsigned iPrecedence = 0;
    900         unsigned cLeft = ELEMENTS(g_aOps);
    901         while (cLeft > 0)
    902         {
    903             for (i = 0; i < ELEMENTS(g_aOps); i++)
    904                 if (g_aOps[i].iPrecedence == iPrecedence)
    905                 {
    906                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    907                                             "%-10s  %s  %s\n",
    908                                             g_aOps[i].szName,
    909                                             g_aOps[i].fBinary ? "Binary" : "Unary ",
    910                                             g_aOps[i].pszDescription);
    911                     cLeft--;
    912                 }
    913             iPrecedence++;
    914         }
    915     }
    916     else
    917     {
    918         /*
    919          * Search for the arguments (strings).
    920          */
    921         for (unsigned iArg = 0; iArg < cArgs; iArg++)
    922         {
    923             Assert(paArgs[iArg].enmType == DBGCVAR_TYPE_STRING);
    924             bool fFound = false;
    925 
    926             /* lookup in the emulation command list first */
    927             for (i = 0; i < pDbgc->cEmulationCmds; i++)
    928                 if (!strcmp(pDbgc->paEmulationCmds[i].pszCmd, paArgs[iArg].u.pszString))
    929                 {
    930                     rc = dbgcPrintHelp(pCmdHlp, &pDbgc->paEmulationCmds[i], false);
    931                     fFound = true;
    932                     break;
    933                 }
    934 
    935             /* lookup in the command list (even when found in the emulation) */
    936             for (i = 0; i < ELEMENTS(g_aCmds); i++)
    937                 if (!strcmp(g_aCmds[i].pszCmd, paArgs[iArg].u.pszString))
    938                 {
    939                     rc = dbgcPrintHelp(pCmdHlp, &g_aCmds[i], false);
    940                     fFound = true;
    941                     break;
    942                 }
    943 
    944            /* external commands */
    945            if (     !fFound
    946                &&   g_pExtCmdsHead
    947                &&   paArgs[iArg].u.pszString[0] == '.')
    948            {
    949                DBGCEXTCMDS_LOCK_RD();
    950                for (PDBGCEXTCMDS pExtCmd = g_pExtCmdsHead; pExtCmd; pExtCmd = pExtCmd->pNext)
    951                    for (i = 0; i < pExtCmd->cCmds; i++)
    952                        if (!strcmp(pExtCmd->paCmds[i].pszCmd, paArgs[iArg].u.pszString + 1))
    953                        {
    954                            rc = dbgcPrintHelp(pCmdHlp, &g_aCmds[i], true);
    955                            fFound = true;
    956                            break;
    957                        }
    958                DBGCEXTCMDS_UNLOCK_RD();
    959            }
    960 
    961            /* operators */
    962            if (!fFound && strlen(paArgs[iArg].u.pszString) < sizeof(g_aOps[i].szName))
    963            {
    964                for (i = 0; i < ELEMENTS(g_aOps); i++)
    965                    if (!strcmp(g_aOps[i].szName, paArgs[iArg].u.pszString))
    966                    {
    967                        rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    968                                                "%-10s  %s  %s\n",
    969                                                g_aOps[i].szName,
    970                                                g_aOps[i].fBinary ? "Binary" : "Unary ",
    971                                                g_aOps[i].pszDescription);
    972                        fFound = true;
    973                        break;
    974                    }
    975            }
    976 
    977            /* found? */
    978            if (!fFound)
    979                rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    980                                        "error: '%s' was not found!\n",
    981                                        paArgs[iArg].u.pszString);
    982         } /* foreach argument */
    983     }
    984 
    985     NOREF(pCmd);
    986     NOREF(pVM);
    987     NOREF(pResult);
    988     return rc;
    989 }
    990 
    991 
    992 /**
    993  * The 'quit', 'exit' and 'bye' commands.
    994  *
    995  * @returns VBox status.
    996  * @param   pCmd        Pointer to the command descriptor (as registered).
    997  * @param   pCmdHlp     Pointer to command helper functions.
    998  * @param   pVM         Pointer to the current VM (if any).
    999  * @param   paArgs      Pointer to (readonly) array of arguments.
    1000  * @param   cArgs       Number of arguments in the array.
    1001  */
    1002 static DECLCALLBACK(int) dbgcCmdQuit(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1003 {
    1004     pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Quitting console...\n");
    1005     NOREF(pCmd);
    1006     NOREF(pVM);
    1007     NOREF(paArgs);
    1008     NOREF(cArgs);
    1009     NOREF(pResult);
    1010     return VERR_DBGC_QUIT;
    1011 }
    1012 
    1013 
    1014 /**
    1015  * The 'go' command.
    1016  *
    1017  * @returns VBox status.
    1018  * @param   pCmd        Pointer to the command descriptor (as registered).
    1019  * @param   pCmdHlp     Pointer to command helper functions.
    1020  * @param   pVM         Pointer to the current VM (if any).
    1021  * @param   paArgs      Pointer to (readonly) array of arguments.
    1022  * @param   cArgs       Number of arguments in the array.
    1023  */
    1024325static DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1025326{
     
    1041342    NOREF(pResult);
    1042343    return 0;
    1043 }
    1044 
    1045 /**
    1046  * The 'stop' command.
    1047  *
    1048  * @returns VBox status.
    1049  * @param   pCmd        Pointer to the command descriptor (as registered).
    1050  * @param   pCmdHlp     Pointer to command helper functions.
    1051  * @param   pVM         Pointer to the current VM (if any).
    1052  * @param   paArgs      Pointer to (readonly) array of arguments.
    1053  * @param   cArgs       Number of arguments in the array.
    1054  */
    1055 static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1056 {
    1057     /*
    1058      * Check if the VM is halted or not before trying to halt it.
    1059      */
    1060     int rc;
    1061     if (DBGFR3IsHalted(pVM))
    1062         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "warning: The VM is already halted...\n");
    1063     else
    1064     {
    1065         rc = DBGFR3Halt(pVM);
    1066         if (VBOX_SUCCESS(rc))
    1067             rc = VWRN_DBGC_CMD_PENDING;
    1068         else
    1069             rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Executing DBGFR3Halt().");
    1070     }
    1071 
    1072     NOREF(pCmd); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    1073     return rc;
    1074344}
    1075345
     
    35422812
    35432813/**
    3544  * The 'echo' command.
     2814 * The 's' command.
    35452815 *
    35462816 * @returns VBox status.
     
    35512821 * @param   cArgs       Number of arguments in the array.
    35522822 */
    3553 static DECLCALLBACK(int) dbgcCmdEcho(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3554 {
    3555     /*
    3556      * Loop thru the arguments and print them with one space between.
    3557      */
    3558     int rc = 0;
    3559     for (unsigned i = 0; i < cArgs; i++)
    3560     {
    3561         if (paArgs[i].enmType == DBGCVAR_TYPE_STRING)
    3562             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, i ? " %s" : "%s", paArgs[i].u.pszString);
    3563         else
    3564             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, i ? " <parser error>" : "<parser error>");
    3565         if (VBOX_FAILURE(rc))
    3566             return rc;
    3567     }
    3568     NOREF(pCmd); NOREF(pResult); NOREF(pVM);
    3569     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\n");
    3570 }
    3571 
    3572 
    3573 /**
    3574  * The 'runscript' command.
    3575  *
    3576  * @returns VBox status.
    3577  * @param   pCmd        Pointer to the command descriptor (as registered).
    3578  * @param   pCmdHlp     Pointer to command helper functions.
    3579  * @param   pVM         Pointer to the current VM (if any).
    3580  * @param   paArgs      Pointer to (readonly) array of arguments.
    3581  * @param   cArgs       Number of arguments in the array.
    3582  */
    3583 static DECLCALLBACK(int) dbgcCmdRunScript(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3584 {
    3585     /* check that the parser did what it's supposed to do. */
    3586     if (    cArgs != 1
    3587         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    3588         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "parser error\n");
    3589 
    3590     /*
    3591      * Try open the script.
    3592      */
    3593     const char *pszFilename = paArgs[0].u.pszString;
    3594     FILE *pFile = fopen(pszFilename, "r");
    3595     if (!pFile)
    3596         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Failed to open '%s'.\n", pszFilename);
    3597 
    3598     /*
    3599      * Execute it line by line.
    3600      */
    3601     int rc = 0;
    3602     unsigned iLine = 0;
    3603     char szLine[8192];
    3604     while (fgets(szLine, sizeof(szLine), pFile))
    3605     {
    3606         /* check that the line isn't too long. */
    3607         char *pszEnd = strchr(szLine, '\0');
    3608         if (pszEnd == &szLine[sizeof(szLine) - 1])
    3609         {
    3610             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "runscript error: Line #%u is too long\n", iLine);
    3611             break;
    3612         }
    3613         iLine++;
    3614 
    3615         /* strip leading blanks and check for comment / blank line. */
    3616         char *psz = RTStrStripL(szLine);
    3617         if (    *psz == '\0'
    3618             ||  *psz == '\n'
    3619             ||  *psz == '#')
    3620             continue;
    3621 
    3622         /* strip trailing blanks and check for empty line (\r case). */
    3623         while (     pszEnd > psz
    3624                &&   isspace(pszEnd[-1])) /* isspace includes \n and \r normally. */
    3625             *--pszEnd = '\0';
    3626 
    3627         /** @todo check for Control-C / Cancel at this point... */
    3628 
    3629         /*
    3630          * Execute the command.
    3631          *
    3632          * This is a bit wasteful with scratch space btw., can fix it later.
    3633          * The whole return code crap should be fixed too, so that it's possible
    3634          * to know whether a command succeeded (VBOX_SUCCESS()) or failed, and
    3635          * more importantly why it failed.
    3636          */
    3637         rc = pCmdHlp->pfnExec(pCmdHlp, "%s", psz);
    3638         if (VBOX_FAILURE(rc))
    3639         {
    3640             if (rc == VERR_BUFFER_OVERFLOW)
    3641                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "runscript error: Line #%u is too long (exec overflowed)\n", iLine);
    3642             break;
    3643         }
    3644         if (rc == VWRN_DBGC_CMD_PENDING)
    3645         {
    3646             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "runscript error: VWRN_DBGC_CMD_PENDING on line #%u, script terminated\n", iLine);
    3647             break;
    3648         }
    3649     }
    3650 
    3651     fclose(pFile);
    3652 
    3653     NOREF(pCmd); NOREF(pResult); NOREF(pVM);
    3654     return rc;
    3655 }
    3656 
    3657 
    3658 /**
    3659  * The 's' command.
    3660  *
    3661  * @returns VBox status.
    3662  * @param   pCmd        Pointer to the command descriptor (as registered).
    3663  * @param   pCmdHlp     Pointer to command helper functions.
    3664  * @param   pVM         Pointer to the current VM (if any).
    3665  * @param   paArgs      Pointer to (readonly) array of arguments.
    3666  * @param   cArgs       Number of arguments in the array.
    3667  */
    36682823static DECLCALLBACK(int) dbgcCmdSearchMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    36692824{
     
    36732828        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "parser error\n");
    36742829    return -1;
    3675 }
    3676 
    3677 
    3678 
    3679 /**
    3680  * Print formatted string.
    3681  *
    3682  * @param   pHlp        Pointer to this structure.
    3683  * @param   pszFormat   The format string.
    3684  * @param   ...         Arguments.
    3685  */
    3686 static DECLCALLBACK(void) dbgcCmdInfo_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
    3687 {
    3688     PDBGCCMDHLP pCmdHlp = *(PDBGCCMDHLP *)(pHlp + 1);
    3689     va_list args;
    3690     va_start(args,  pszFormat);
    3691     pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
    3692     va_end(args);
    3693 }
    3694 
    3695 
    3696 /**
    3697  * Print formatted string.
    3698  *
    3699  * @param   pHlp        Pointer to this structure.
    3700  * @param   pszFormat   The format string.
    3701  * @param   args        Argument list.
    3702  */
    3703 static DECLCALLBACK(void) dbgcCmdInfo_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
    3704 {
    3705     PDBGCCMDHLP pCmdHlp = *(PDBGCCMDHLP *)(pHlp + 1);
    3706     pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
    3707 }
    3708 
    3709 
    3710 /**
    3711  * The 'info' command.
    3712  *
    3713  * @returns VBox status.
    3714  * @param   pCmd        Pointer to the command descriptor (as registered).
    3715  * @param   pCmdHlp     Pointer to command helper functions.
    3716  * @param   pVM         Pointer to the current VM (if any).
    3717  * @param   paArgs      Pointer to (readonly) array of arguments.
    3718  * @param   cArgs       Number of arguments in the array.
    3719  */
    3720 static DECLCALLBACK(int) dbgcCmdInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3721 {
    3722     /*
    3723      * Validate input.
    3724      */
    3725     if (    cArgs < 1
    3726         ||  cArgs > 2
    3727         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING
    3728         ||  paArgs[cArgs - 1].enmType != DBGCVAR_TYPE_STRING)
    3729         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: The parser doesn't do its job properly yet.. quote the string.\n");
    3730     if (!pVM)
    3731         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    3732 
    3733     /*
    3734      * Dump it.
    3735      */
    3736     struct
    3737     {
    3738         DBGFINFOHLP Hlp;
    3739         PDBGCCMDHLP pCmdHlp;
    3740     } Hlp = { { dbgcCmdInfo_Printf, dbgcCmdInfo_PrintfV }, pCmdHlp };
    3741     int rc = DBGFR3Info(pVM, paArgs[0].u.pszString, cArgs == 2 ? paArgs[1].u.pszString : NULL, &Hlp.Hlp);
    3742     if (VBOX_FAILURE(rc))
    3743         return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3Info()\n");
    3744 
    3745     NOREF(pCmd); NOREF(pResult);
    3746     return 0;
    3747 }
    3748 
    3749 
    3750 /**
    3751  * The 'log' command.
    3752  *
    3753  * @returns VBox status.
    3754  * @param   pCmd        Pointer to the command descriptor (as registered).
    3755  * @param   pCmdHlp     Pointer to command helper functions.
    3756  * @param   pVM         Pointer to the current VM (if any).
    3757  * @param   paArgs      Pointer to (readonly) array of arguments.
    3758  * @param   cArgs       Number of arguments in the array.
    3759  */
    3760 static DECLCALLBACK(int) dbgcCmdLog(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3761 {
    3762     int rc = DBGFR3LogModifyGroups(pVM, paArgs[0].u.pszString);
    3763     if (VBOX_SUCCESS(rc))
    3764         return VINF_SUCCESS;
    3765     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    3766     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3LogModifyGroups(%p,'%s')\n", pVM, paArgs[0].u.pszString);
    3767 }
    3768 
    3769 
    3770 /**
    3771  * The 'logdest' command.
    3772  *
    3773  * @returns VBox status.
    3774  * @param   pCmd        Pointer to the command descriptor (as registered).
    3775  * @param   pCmdHlp     Pointer to command helper functions.
    3776  * @param   pVM         Pointer to the current VM (if any).
    3777  * @param   paArgs      Pointer to (readonly) array of arguments.
    3778  * @param   cArgs       Number of arguments in the array.
    3779  */
    3780 static DECLCALLBACK(int) dbgcCmdLogDest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3781 {
    3782     int rc = DBGFR3LogModifyDestinations(pVM, paArgs[0].u.pszString);
    3783     if (VBOX_SUCCESS(rc))
    3784         return VINF_SUCCESS;
    3785     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    3786     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3LogModifyDestinations(%p,'%s')\n", pVM, paArgs[0].u.pszString);
    3787 }
    3788 
    3789 
    3790 /**
    3791  * The 'logflags' command.
    3792  *
    3793  * @returns VBox status.
    3794  * @param   pCmd        Pointer to the command descriptor (as registered).
    3795  * @param   pCmdHlp     Pointer to command helper functions.
    3796  * @param   pVM         Pointer to the current VM (if any).
    3797  * @param   paArgs      Pointer to (readonly) array of arguments.
    3798  * @param   cArgs       Number of arguments in the array.
    3799  */
    3800 static DECLCALLBACK(int) dbgcCmdLogFlags(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3801 {
    3802     int rc = DBGFR3LogModifyFlags(pVM, paArgs[0].u.pszString);
    3803     if (VBOX_SUCCESS(rc))
    3804         return VINF_SUCCESS;
    3805     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    3806     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3LogModifyFlags(%p,'%s')\n", pVM, paArgs[0].u.pszString);
    3807 }
    3808 
    3809 
    3810 /**
    3811  * The 'format' command.
    3812  *
    3813  * @returns VBox status.
    3814  * @param   pCmd        Pointer to the command descriptor (as registered).
    3815  * @param   pCmdHlp     Pointer to command helper functions.
    3816  * @param   pVM         Pointer to the current VM (if any).
    3817  * @param   paArgs      Pointer to (readonly) array of arguments.
    3818  * @param   cArgs       Number of arguments in the array.
    3819  */
    3820 static DECLCALLBACK(int) dbgcCmdFormat(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3821 {
    3822     LogFlow(("dbgcCmdFormat\n"));
    3823     static const char *apszRangeDesc[] =
    3824     {
    3825         "none", "bytes", "elements"
    3826     };
    3827     int rc;
    3828 
    3829     for (unsigned iArg = 0; iArg < cArgs; iArg++)
    3830     {
    3831         switch (paArgs[iArg].enmType)
    3832         {
    3833             case DBGCVAR_TYPE_UNKNOWN:
    3834                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3835                     "Unknown variable type!\n");
    3836                 break;
    3837             case DBGCVAR_TYPE_GC_FLAT:
    3838                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    3839                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3840                         "Guest flat address: %%%08x range %lld %s\n",
    3841                         paArgs[iArg].u.GCFlat,
    3842                         paArgs[iArg].u64Range,
    3843                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    3844                 else
    3845                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3846                         "Guest flat address: %%%08x\n",
    3847                         paArgs[iArg].u.GCFlat);
    3848                 break;
    3849             case DBGCVAR_TYPE_GC_FAR:
    3850                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    3851                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3852                         "Guest far address: %04x:%08x range %lld %s\n",
    3853                         paArgs[iArg].u.GCFar.sel,
    3854                         paArgs[iArg].u.GCFar.off,
    3855                         paArgs[iArg].u64Range,
    3856                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    3857                 else
    3858                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3859                         "Guest far address: %04x:%08x\n",
    3860                         paArgs[iArg].u.GCFar.sel,
    3861                         paArgs[iArg].u.GCFar.off);
    3862                 break;
    3863             case DBGCVAR_TYPE_GC_PHYS:
    3864                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    3865                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3866                         "Guest physical address: %%%%%08x range %lld %s\n",
    3867                         paArgs[iArg].u.GCPhys,
    3868                         paArgs[iArg].u64Range,
    3869                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    3870                 else
    3871                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3872                         "Guest physical address: %%%%%08x\n",
    3873                         paArgs[iArg].u.GCPhys);
    3874                 break;
    3875             case DBGCVAR_TYPE_HC_FLAT:
    3876                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    3877                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3878                         "Host flat address: %%%08x range %lld %s\n",
    3879                         paArgs[iArg].u.pvHCFlat,
    3880                         paArgs[iArg].u64Range,
    3881                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    3882                 else
    3883                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3884                         "Host flat address: %%%08x\n",
    3885                         paArgs[iArg].u.pvHCFlat);
    3886                 break;
    3887             case DBGCVAR_TYPE_HC_FAR:
    3888                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    3889                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3890                         "Host far address: %04x:%08x range %lld %s\n",
    3891                         paArgs[iArg].u.HCFar.sel,
    3892                         paArgs[iArg].u.HCFar.off,
    3893                         paArgs[iArg].u64Range,
    3894                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    3895                 else
    3896                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3897                         "Host far address: %04x:%08x\n",
    3898                         paArgs[iArg].u.HCFar.sel,
    3899                         paArgs[iArg].u.HCFar.off);
    3900                 break;
    3901             case DBGCVAR_TYPE_HC_PHYS:
    3902                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    3903                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3904                         "Host physical address: %VHp range %lld %s\n",
    3905                         paArgs[iArg].u.HCPhys,
    3906                         paArgs[iArg].u64Range,
    3907                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    3908                 else
    3909                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3910                         "Host physical address: %VHp\n",
    3911                         paArgs[iArg].u.HCPhys);
    3912                 break;
    3913 
    3914             case DBGCVAR_TYPE_STRING:
    3915                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3916                     "String, %lld bytes long: %s\n",
    3917                     paArgs[iArg].u64Range,
    3918                     paArgs[iArg].u.pszString);
    3919                 break;
    3920 
    3921             case DBGCVAR_TYPE_NUMBER:
    3922                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    3923                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3924                         "Number: hex %llx  dec 0i%lld  oct 0t%llo  range %lld %s\n",
    3925                         paArgs[iArg].u.u64Number,
    3926                         paArgs[iArg].u.u64Number,
    3927                         paArgs[iArg].u.u64Number,
    3928                         paArgs[iArg].u64Range,
    3929                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    3930                 else
    3931                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3932                         "Number: hex %llx  dec 0i%lld  oct 0t%llo\n",
    3933                         paArgs[iArg].u.u64Number,
    3934                         paArgs[iArg].u.u64Number,
    3935                         paArgs[iArg].u.u64Number);
    3936                 break;
    3937 
    3938             default:
    3939                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3940                     "Invalid argument type %d\n",
    3941                     paArgs[iArg].enmType);
    3942                 break;
    3943         }
    3944     } /* arg loop */
    3945 
    3946     NOREF(pCmd); NOREF(pVM); NOREF(pResult);
    3947     return 0;
    39482830}
    39492831
     
    40532935}
    40542936
    4055 
    4056 /**
    4057  * The 'loadsyms' command.
    4058  *
    4059  * @returns VBox status.
    4060  * @param   pCmd        Pointer to the command descriptor (as registered).
    4061  * @param   pCmdHlp     Pointer to command helper functions.
    4062  * @param   pVM         Pointer to the current VM (if any).
    4063  * @param   paArgs      Pointer to (readonly) array of arguments.
    4064  * @param   cArgs       Number of arguments in the array.
    4065  */
    4066 static DECLCALLBACK(int) dbgcCmdLoadSyms(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    4067 {
    4068     /*
    4069      * Validate the parsing and make sense of the input.
    4070      * This is a mess as usual because we don't trust the parser yet.
    4071      */
    4072     if (    cArgs < 1
    4073         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    4074     {
    4075         AssertMsgFailed(("Parse error, first argument required to be string!\n"));
    4076         return VERR_PARSE_INCORRECT_ARG_TYPE;
    4077     }
    4078     DBGCVAR     AddrVar;
    4079     RTGCUINTPTR Delta = 0;
    4080     const char *pszModule = NULL;
    4081     RTGCUINTPTR ModuleAddress = 0;
    4082     unsigned    cbModule = 0;
    4083     if (cArgs > 1)
    4084     {
    4085         unsigned iArg = 1;
    4086         if (paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    4087         {
    4088             Delta = (RTGCUINTPTR)paArgs[iArg].u.u64Number;
    4089             iArg++;
    4090         }
    4091         if (iArg < cArgs)
    4092         {
    4093             if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
    4094             {
    4095                 AssertMsgFailed(("Parse error, module argument required to be string!\n"));
    4096                 return VERR_PARSE_INCORRECT_ARG_TYPE;
    4097             }
    4098             pszModule = paArgs[iArg].u.pszString;
    4099             iArg++;
    4100             if (iArg < cArgs)
    4101             {
    4102                 if (DBGCVAR_ISPOINTER(paArgs[iArg].enmType))
    4103                 {
    4104                     AssertMsgFailed(("Parse error, module argument required to be GC pointer!\n"));
    4105                     return VERR_PARSE_INCORRECT_ARG_TYPE;
    4106                 }
    4107                 int rc = pCmdHlp->pfnEval(pCmdHlp, &AddrVar, "%%(%Dv)", &paArgs[iArg]);
    4108                 if (VBOX_FAILURE(rc))
    4109                     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Module address cast %%(%Dv) failed.", &paArgs[iArg]);
    4110                 ModuleAddress = paArgs[iArg].u.GCFlat;
    4111                 iArg++;
    4112                 if (iArg < cArgs)
    4113                 {
    4114                     if (paArgs[iArg].enmType != DBGCVAR_TYPE_NUMBER)
    4115                     {
    4116                         AssertMsgFailed(("Parse error, module argument required to be an interger!\n"));
    4117                         return VERR_PARSE_INCORRECT_ARG_TYPE;
    4118                     }
    4119                     cbModule = (unsigned)paArgs[iArg].u.u64Number;
    4120                     iArg++;
    4121                     if (iArg < cArgs)
    4122                     {
    4123                         AssertMsgFailed(("Parse error, too many arguments!\n"));
    4124                         return VERR_PARSE_TOO_MANY_ARGUMENTS;
    4125                     }
    4126                 }
    4127             }
    4128         }
    4129     }
    4130 
    4131     /*
    4132      * Call the debug info manager about this loading...
    4133      */
    4134     int rc = DBGFR3ModuleLoad(pVM, paArgs[0].u.pszString, Delta, pszModule, ModuleAddress, cbModule);
    4135     if (VBOX_FAILURE(rc))
    4136         return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGInfoSymbolLoad(, '%s', %VGv, '%s', %VGv, 0)\n",
    4137                                      paArgs[0].u.pszString, Delta, pszModule, ModuleAddress);
    4138 
    4139     NOREF(pCmd); NOREF(pResult);
    4140     return VINF_SUCCESS;
    4141 }
    4142 
    4143 
    4144 /**
    4145  * The 'set' command.
    4146  *
    4147  * @returns VBox status.
    4148  * @param   pCmd        Pointer to the command descriptor (as registered).
    4149  * @param   pCmdHlp     Pointer to command helper functions.
    4150  * @param   pVM         Pointer to the current VM (if any).
    4151  * @param   paArgs      Pointer to (readonly) array of arguments.
    4152  * @param   cArgs       Number of arguments in the array.
    4153  */
    4154 static DECLCALLBACK(int) dbgcCmdSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    4155 {
    4156     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    4157 
    4158     /* parse sanity check. */
    4159     AssertMsg(paArgs[0].enmType == DBGCVAR_TYPE_STRING, ("expected string not %d as first arg!\n", paArgs[0].enmType));
    4160     if (paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    4161         return VERR_PARSE_INCORRECT_ARG_TYPE;
    4162 
    4163 
    4164     /*
    4165      * A variable must start with an alpha chars and only contain alpha numerical chars.
    4166      */
    4167     const char *pszVar = paArgs[0].u.pszString;
    4168     if (!isalpha(*pszVar) || *pszVar == '_')
    4169         return pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    4170             "syntax error: Invalid variable name '%s'. Variable names must match regex '[_a-zA-Z][_a-zA-Z0-9*'!", paArgs[0].u.pszString);
    4171 
    4172     while (isalnum(*pszVar) || *pszVar == '_')
    4173         *pszVar++;
    4174     if (*pszVar)
    4175         return pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    4176             "syntax error: Invalid variable name '%s'. Variable names must match regex '[_a-zA-Z][_a-zA-Z0-9*]'!", paArgs[0].u.pszString);
    4177 
    4178 
    4179     /*
    4180      * Calc variable size.
    4181      */
    4182     size_t  cbVar = (size_t)paArgs[0].u64Range + sizeof(DBGCNAMEDVAR);
    4183     if (paArgs[1].enmType == DBGCVAR_TYPE_STRING)
    4184         cbVar += 1 + (size_t)paArgs[1].u64Range;
    4185 
    4186     /*
    4187      * Look for existing one.
    4188      */
    4189     pszVar = paArgs[0].u.pszString;
    4190     for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
    4191     {
    4192         if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
    4193         {
    4194             /*
    4195              * Update existing variable.
    4196              */
    4197             void *pv = RTMemRealloc(pDbgc->papVars[iVar], cbVar);
    4198             if (!pv)
    4199                 return VERR_PARSE_NO_MEMORY;
    4200             PDBGCNAMEDVAR pVar = pDbgc->papVars[iVar] = (PDBGCNAMEDVAR)pv;
    4201 
    4202             pVar->Var = paArgs[1];
    4203             memcpy(pVar->szName, paArgs[0].u.pszString, (size_t)paArgs[0].u64Range + 1);
    4204             if (paArgs[1].enmType == DBGCVAR_TYPE_STRING)
    4205                 pVar->Var.u.pszString = (char *)memcpy(&pVar->szName[paArgs[0].u64Range + 1], paArgs[1].u.pszString, (size_t)paArgs[1].u64Range + 1);
    4206             return 0;
    4207         }
    4208     }
    4209 
    4210     /*
    4211      * Allocate another.
    4212      */
    4213     PDBGCNAMEDVAR pVar = (PDBGCNAMEDVAR)RTMemAlloc(cbVar);
    4214 
    4215     pVar->Var = paArgs[1];
    4216     memcpy(pVar->szName, pszVar, (size_t)paArgs[0].u64Range + 1);
    4217     if (paArgs[1].enmType == DBGCVAR_TYPE_STRING)
    4218         pVar->Var.u.pszString = (char *)memcpy(&pVar->szName[paArgs[0].u64Range + 1], paArgs[1].u.pszString, (size_t)paArgs[1].u64Range + 1);
    4219 
    4220     /* need to reallocate the pointer array too? */
    4221     if (!(pDbgc->cVars % 0x20))
    4222     {
    4223         void *pv = RTMemRealloc(pDbgc->papVars, (pDbgc->cVars + 0x20) * sizeof(pDbgc->papVars[0]));
    4224         if (!pv)
    4225         {
    4226             RTMemFree(pVar);
    4227             return VERR_PARSE_NO_MEMORY;
    4228         }
    4229         pDbgc->papVars = (PDBGCNAMEDVAR *)pv;
    4230     }
    4231     pDbgc->papVars[pDbgc->cVars++] = pVar;
    4232 
    4233     NOREF(pCmd); NOREF(pVM); NOREF(cArgs); NOREF(pResult);
    4234     return 0;
    4235 }
    4236 
    4237 
    4238 /**
    4239  * The 'unset' command.
    4240  *
    4241  * @returns VBox status.
    4242  * @param   pCmd        Pointer to the command descriptor (as registered).
    4243  * @param   pCmdHlp     Pointer to command helper functions.
    4244  * @param   pVM         Pointer to the current VM (if any).
    4245  * @param   paArgs      Pointer to (readonly) array of arguments.
    4246  * @param   cArgs       Number of arguments in the array.
    4247  */
    4248 static DECLCALLBACK(int) dbgcCmdUnset(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    4249 {
    4250     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    4251 
    4252     /*
    4253      * Don't trust the parser.
    4254      */
    4255     for (unsigned  i = 0; i < cArgs; i++)
    4256         if (paArgs[i].enmType != DBGCVAR_TYPE_STRING)
    4257         {
    4258             AssertMsgFailed(("expected strings only. (arg=%d)!\n", i));
    4259             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4260         }
    4261 
    4262     /*
    4263      * Iterate the variables and unset them.
    4264      */
    4265     for (unsigned iArg = 0; iArg < cArgs; iArg++)
    4266     {
    4267         const char *pszVar = paArgs[iArg].u.pszString;
    4268 
    4269         /*
    4270          * Look up the variable.
    4271          */
    4272         for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
    4273         {
    4274             if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
    4275             {
    4276                 /*
    4277                  * Shuffle the array removing this entry.
    4278                  */
    4279                 void *pvFree = pDbgc->papVars[iVar];
    4280                 if (iVar + 1 < pDbgc->cVars)
    4281                     memmove(&pDbgc->papVars[iVar],
    4282                             &pDbgc->papVars[iVar + 1],
    4283                             (pDbgc->cVars - iVar - 1) * sizeof(pDbgc->papVars[0]));
    4284                 pDbgc->papVars[--pDbgc->cVars] = NULL;
    4285 
    4286                 RTMemFree(pvFree);
    4287             }
    4288         } /* lookup */
    4289     } /* arg loop */
    4290 
    4291     NOREF(pCmd); NOREF(pVM); NOREF(pResult);
    4292     return 0;
    4293 }
    4294 
    4295 
    4296 /**
    4297  * The 'loadvars' command.
    4298  *
    4299  * @returns VBox status.
    4300  * @param   pCmd        Pointer to the command descriptor (as registered).
    4301  * @param   pCmdHlp     Pointer to command helper functions.
    4302  * @param   pVM         Pointer to the current VM (if any).
    4303  * @param   paArgs      Pointer to (readonly) array of arguments.
    4304  * @param   cArgs       Number of arguments in the array.
    4305  */
    4306 static DECLCALLBACK(int) dbgcCmdLoadVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    4307 {
    4308     /*
    4309      * Don't trust the parser.
    4310      */
    4311     if (    cArgs != 1
    4312         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    4313     {
    4314         AssertMsgFailed(("Expected one string exactly!\n"));
    4315         return VERR_PARSE_INCORRECT_ARG_TYPE;
    4316     }
    4317 
    4318     /*
    4319      * Iterate the variables and unset them.
    4320      */
    4321     FILE *pFile = fopen(paArgs[0].u.pszString, "r");
    4322     if (pFile)
    4323     {
    4324         char szLine[4096];
    4325         while (fgets(szLine, sizeof(szLine), pFile))
    4326         {
    4327             /* Strip it. */
    4328             char *psz = szLine;
    4329             while (isblank(*psz))
    4330                 psz++;
    4331             int i = (int)strlen(psz) - 1;
    4332             while (i >= 0 && isspace(psz[i]))
    4333                 psz[i--] ='\0';
    4334             /* Execute it if not comment or empty line. */
    4335             if (    *psz != '\0'
    4336                 &&  *psz != '#'
    4337                 &&  *psz != ';')
    4338             {
    4339                 pCmdHlp->pfnPrintf(pCmdHlp, NULL, "dbg: set %s", psz);
    4340                 pCmdHlp->pfnExec(pCmdHlp, "set %s", psz);
    4341             }
    4342         }
    4343         fclose(pFile);
    4344     }
    4345     else
    4346         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Failed to open file '%s'.\n", paArgs[0].u.pszString);
    4347 
    4348     NOREF(pCmd); NOREF(pVM); NOREF(pResult);
    4349     return 0;
    4350 }
    4351 
    4352 
    4353 /**
    4354  * The 'showvars' command.
    4355  *
    4356  * @returns VBox status.
    4357  * @param   pCmd        Pointer to the command descriptor (as registered).
    4358  * @param   pCmdHlp     Pointer to command helper functions.
    4359  * @param   pVM         Pointer to the current VM (if any).
    4360  * @param   paArgs      Pointer to (readonly) array of arguments.
    4361  * @param   cArgs       Number of arguments in the array.
    4362  */
    4363 static DECLCALLBACK(int) dbgcCmdShowVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    4364 {
    4365     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    4366 
    4367     for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
    4368     {
    4369         int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%-20s ", &pDbgc->papVars[iVar]->szName);
    4370         if (!rc)
    4371             rc = dbgcCmdFormat(pCmd, pCmdHlp, pVM, &pDbgc->papVars[iVar]->Var, 1, NULL);
    4372         if (rc)
    4373             return rc;
    4374     }
    4375 
    4376     NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    4377     return 0;
    4378 }
    4379 
    4380 
    4381 /**
    4382  * The 'harakiri' command.
    4383  *
    4384  * @returns VBox status.
    4385  * @param   pCmd        Pointer to the command descriptor (as registered).
    4386  * @param   pCmdHlp     Pointer to command helper functions.
    4387  * @param   pVM         Pointer to the current VM (if any).
    4388  * @param   paArgs      Pointer to (readonly) array of arguments.
    4389  * @param   cArgs       Number of arguments in the array.
    4390  */
    4391 static DECLCALLBACK(int) dbgcCmdHarakiri(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    4392 {
    4393     Log(("dbgcCmdHarakiri\n"));
    4394     for (;;)
    4395         exit(126);
    4396     NOREF(pCmd); NOREF(pCmdHlp); NOREF(pVM); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    4397 }
    4398 
    4399 
    4400 
    4401 
    4402 
    4403 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    4404 //
    4405 //
    4406 //      B u l t i n   S y m b o l s
    4407 //
    4408 //
    4409 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    4410 
    4411 
    4412 
    4413 /**
    4414  * Get builtin register symbol.
    4415  *
    4416  * The uUser is special for these symbol descriptors. See the SYMREG_* \#defines.
    4417  *
    4418  * @returns 0 on success.
    4419  * @returns VBox evaluation / parsing error code on failure.
    4420  *          The caller does the bitching.
    4421  * @param   pSymDesc    Pointer to the symbol descriptor.
    4422  * @param   pCmdHlp     Pointer to the command callback structure.
    4423  * @param   enmType     The result type.
    4424  * @param   pResult     Where to store the result.
    4425  */
    4426 static DECLCALLBACK(int) dbgcSymGetReg(PCDBGCSYM pSymDesc, PDBGCCMDHLP pCmdHlp, DBGCVARTYPE enmType, PDBGCVAR pResult)
    4427 {
    4428     LogFlow(("dbgcSymSetReg: pSymDesc->pszName=%d\n", pSymDesc->pszName));
    4429 
    4430     /*
    4431      * pVM is required.
    4432      */
    4433     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    4434     Assert(pDbgc->pVM);
    4435 
    4436     /*
    4437      * Get the right CPU context.
    4438      */
    4439     PCPUMCTX    pCtx;
    4440     int         rc;
    4441     if (!(pSymDesc->uUser & SYMREG_FLAGS_HYPER))
    4442         rc = CPUMQueryGuestCtxPtr(pDbgc->pVM, &pCtx);
    4443     else
    4444         rc = CPUMQueryHyperCtxPtr(pDbgc->pVM, &pCtx);
    4445     if (VBOX_FAILURE(rc))
    4446         return rc;
    4447 
    4448     /*
    4449      * Get the value.
    4450      */
    4451     void       *pvValue = (char *)pCtx + SYMREG_OFFSET(pSymDesc->uUser);
    4452     uint64_t    u64;
    4453     switch (SYMREG_SIZE(pSymDesc->uUser))
    4454     {
    4455         case 1: u64 = *(uint8_t *)pvValue; break;
    4456         case 2: u64 = *(uint16_t *)pvValue; break;
    4457         case 4: u64 = *(uint32_t *)pvValue; break;
    4458         case 6: u64 = *(uint32_t *)pvValue | ((uint64_t)*(uint16_t *)((char *)pvValue + sizeof(uint32_t)) << 32); break;
    4459         case 8: u64 = *(uint64_t *)pvValue; break;
    4460         default:
    4461             return VERR_PARSE_NOT_IMPLEMENTED;
    4462     }
    4463 
    4464     /*
    4465      * Construct the desired result.
    4466      */
    4467     if (enmType == DBGCVAR_TYPE_ANY)
    4468         enmType = DBGCVAR_TYPE_NUMBER;
    4469     pResult->pDesc          = NULL;
    4470     pResult->pNext          = NULL;
    4471     pResult->enmType        = enmType;
    4472     pResult->enmRangeType   = DBGCVAR_RANGE_NONE;
    4473     pResult->u64Range       = 0;
    4474 
    4475     switch (enmType)
    4476     {
    4477         case DBGCVAR_TYPE_GC_FLAT:
    4478             pResult->u.GCFlat = (RTGCPTR)u64;
    4479             break;
    4480 
    4481         case DBGCVAR_TYPE_GC_FAR:
    4482             switch (SYMREG_SIZE(pSymDesc->uUser))
    4483             {
    4484                 case 4:
    4485                     if (!(pSymDesc->uUser & SYMREG_FLAGS_HIGH_SEL))
    4486                     {
    4487                         pResult->u.GCFar.off = (uint16_t)u64;
    4488                         pResult->u.GCFar.sel = (uint16_t)(u64 >> 16);
    4489                     }
    4490                     else
    4491                     {
    4492                         pResult->u.GCFar.sel = (uint16_t)u64;
    4493                         pResult->u.GCFar.off = (uint16_t)(u64 >> 16);
    4494                     }
    4495                     break;
    4496                 case 6:
    4497                     if (!(pSymDesc->uUser & SYMREG_FLAGS_HIGH_SEL))
    4498                     {
    4499                         pResult->u.GCFar.off = (uint32_t)u64;
    4500                         pResult->u.GCFar.sel = (uint16_t)(u64 >> 32);
    4501                     }
    4502                     else
    4503                     {
    4504                         pResult->u.GCFar.sel = (uint32_t)u64;
    4505                         pResult->u.GCFar.off = (uint16_t)(u64 >> 32);
    4506                     }
    4507                     break;
    4508 
    4509                 default:
    4510                     return VERR_PARSE_BAD_RESULT_TYPE;
    4511             }
    4512             break;
    4513 
    4514         case DBGCVAR_TYPE_GC_PHYS:
    4515             pResult->u.GCPhys = (RTGCPHYS)u64;
    4516             break;
    4517 
    4518         case DBGCVAR_TYPE_HC_FLAT:
    4519             pResult->u.pvHCFlat = (void *)(uintptr_t)u64;
    4520             break;
    4521 
    4522         case DBGCVAR_TYPE_HC_FAR:
    4523             switch (SYMREG_SIZE(pSymDesc->uUser))
    4524             {
    4525                 case 4:
    4526                     if (!(pSymDesc->uUser & SYMREG_FLAGS_HIGH_SEL))
    4527                     {
    4528                         pResult->u.HCFar.off = (uint16_t)u64;
    4529                         pResult->u.HCFar.sel = (uint16_t)(u64 >> 16);
    4530                     }
    4531                     else
    4532                     {
    4533                         pResult->u.HCFar.sel = (uint16_t)u64;
    4534                         pResult->u.HCFar.off = (uint16_t)(u64 >> 16);
    4535                     }
    4536                     break;
    4537                 case 6:
    4538                     if (!(pSymDesc->uUser & SYMREG_FLAGS_HIGH_SEL))
    4539                     {
    4540                         pResult->u.HCFar.off = (uint32_t)u64;
    4541                         pResult->u.HCFar.sel = (uint16_t)(u64 >> 32);
    4542                     }
    4543                     else
    4544                     {
    4545                         pResult->u.HCFar.sel = (uint32_t)u64;
    4546                         pResult->u.HCFar.off = (uint16_t)(u64 >> 32);
    4547                     }
    4548                     break;
    4549 
    4550                 default:
    4551                     return VERR_PARSE_BAD_RESULT_TYPE;
    4552             }
    4553             break;
    4554 
    4555         case DBGCVAR_TYPE_HC_PHYS:
    4556             pResult->u.GCPhys = (RTGCPHYS)u64;
    4557             break;
    4558 
    4559         case DBGCVAR_TYPE_NUMBER:
    4560             pResult->u.u64Number = u64;
    4561             break;
    4562 
    4563         case DBGCVAR_TYPE_STRING:
    4564         case DBGCVAR_TYPE_UNKNOWN:
    4565         default:
    4566             return VERR_PARSE_BAD_RESULT_TYPE;
    4567 
    4568     }
    4569 
    4570     return 0;
    4571 }
    4572 
    4573 
    4574 /**
    4575  * Set builtin register symbol.
    4576  *
    4577  * The uUser is special for these symbol descriptors. See the SYMREG_* #defines.
    4578  *
    4579  * @returns 0 on success.
    4580  * @returns VBox evaluation / parsing error code on failure.
    4581  *          The caller does the bitching.
    4582  * @param   pSymDesc    Pointer to the symbol descriptor.
    4583  * @param   pCmdHlp     Pointer to the command callback structure.
    4584  * @param   pValue      The value to assign the symbol.
    4585  */
    4586 static DECLCALLBACK(int) dbgcSymSetReg(PCDBGCSYM pSymDesc, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pValue)
    4587 {
    4588     LogFlow(("dbgcSymSetReg: pSymDesc->pszName=%d\n", pSymDesc->pszName));
    4589 
    4590     /*
    4591      * pVM is required.
    4592      */
    4593     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    4594     Assert(pDbgc->pVM);
    4595 
    4596     /*
    4597      * Get the right CPU context.
    4598      */
    4599     PCPUMCTX    pCtx;
    4600     int         rc;
    4601     if (!(pSymDesc->uUser & SYMREG_FLAGS_HYPER))
    4602         rc = CPUMQueryGuestCtxPtr(pDbgc->pVM, &pCtx);
    4603     else
    4604         rc = CPUMQueryHyperCtxPtr(pDbgc->pVM, &pCtx);
    4605     if (VBOX_FAILURE(rc))
    4606         return rc;
    4607 
    4608     /*
    4609      * Check the new value.
    4610      */
    4611     if (pValue->enmType != DBGCVAR_TYPE_NUMBER)
    4612         return VERR_PARSE_ARGUMENT_TYPE_MISMATCH;
    4613 
    4614     /*
    4615      * Set the value.
    4616      */
    4617     void       *pvValue = (char *)pCtx + SYMREG_OFFSET(pSymDesc->uUser);
    4618     switch (SYMREG_SIZE(pSymDesc->uUser))
    4619     {
    4620         case 1:
    4621             *(uint8_t *)pvValue  = (uint8_t)pValue->u.u64Number;
    4622             break;
    4623         case 2:
    4624             *(uint16_t *)pvValue = (uint16_t)pValue->u.u64Number;
    4625             break;
    4626         case 4:
    4627             *(uint32_t *)pvValue = (uint32_t)pValue->u.u64Number;
    4628             break;
    4629         case 6:
    4630             *(uint32_t *)pvValue = (uint32_t)pValue->u.u64Number;
    4631             ((uint16_t *)pvValue)[3] = (uint16_t)(pValue->u.u64Number >> 32);
    4632             break;
    4633         case 8:
    4634             *(uint64_t *)pvValue = pValue->u.u64Number;
    4635             break;
    4636         default:
    4637             return VERR_PARSE_NOT_IMPLEMENTED;
    4638     }
    4639 
    4640     return VINF_SUCCESS;
    4641 }
    4642 
    4643 
    4644 
    4645 
    4646 
    4647 
    4648 
    4649 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    4650 //
    4651 //
    4652 //      O p e r a t o r s
    4653 //
    4654 //
    4655 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    4656 
    4657 
    4658 /**
    4659  * Minus (unary).
    4660  *
    4661  * @returns 0 on success.
    4662  * @returns VBox evaluation / parsing error code on failure.
    4663  *          The caller does the bitching.
    4664  * @param   pDbgc       Debugger console instance data.
    4665  * @param   pArg        The argument.
    4666  * @param   pResult     Where to store the result.
    4667  */
    4668 static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    4669 {
    4670 //    LogFlow(("dbgcOpMinus\n"));
    4671     *pResult = *pArg;
    4672     switch (pArg->enmType)
    4673     {
    4674         case DBGCVAR_TYPE_GC_FLAT:
    4675             pResult->u.GCFlat       = -(RTGCINTPTR)pResult->u.GCFlat;
    4676             break;
    4677         case DBGCVAR_TYPE_GC_FAR:
    4678             pResult->u.GCFar.off    = -(int32_t)pResult->u.GCFar.off;
    4679             break;
    4680         case DBGCVAR_TYPE_GC_PHYS:
    4681             pResult->u.GCPhys       = (RTGCPHYS) -(int64_t)pResult->u.GCPhys;
    4682             break;
    4683         case DBGCVAR_TYPE_HC_FLAT:
    4684             pResult->u.pvHCFlat     = (void *) -(intptr_t)pResult->u.pvHCFlat;
    4685             break;
    4686         case DBGCVAR_TYPE_HC_FAR:
    4687             pResult->u.HCFar.off    = -(int32_t)pResult->u.HCFar.off;
    4688             break;
    4689         case DBGCVAR_TYPE_HC_PHYS:
    4690             pResult->u.HCPhys       = (RTHCPHYS) -(int64_t)pResult->u.HCPhys;
    4691             break;
    4692         case DBGCVAR_TYPE_NUMBER:
    4693             pResult->u.u64Number    = -(int64_t)pResult->u.u64Number;
    4694             break;
    4695 
    4696         case DBGCVAR_TYPE_UNKNOWN:
    4697         case DBGCVAR_TYPE_STRING:
    4698         default:
    4699             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4700     }
    4701     NOREF(pDbgc);
    4702     return 0;
    4703 }
    4704 
    4705 
    4706 /**
    4707  * Pluss (unary).
    4708  *
    4709  * @returns 0 on success.
    4710  * @returns VBox evaluation / parsing error code on failure.
    4711  *          The caller does the bitching.
    4712  * @param   pDbgc       Debugger console instance data.
    4713  * @param   pArg        The argument.
    4714  * @param   pResult     Where to store the result.
    4715  */
    4716 static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    4717 {
    4718 //    LogFlow(("dbgcOpPluss\n"));
    4719     *pResult = *pArg;
    4720     switch (pArg->enmType)
    4721     {
    4722         case DBGCVAR_TYPE_GC_FLAT:
    4723         case DBGCVAR_TYPE_GC_FAR:
    4724         case DBGCVAR_TYPE_GC_PHYS:
    4725         case DBGCVAR_TYPE_HC_FLAT:
    4726         case DBGCVAR_TYPE_HC_FAR:
    4727         case DBGCVAR_TYPE_HC_PHYS:
    4728         case DBGCVAR_TYPE_NUMBER:
    4729             break;
    4730 
    4731         case DBGCVAR_TYPE_UNKNOWN:
    4732         case DBGCVAR_TYPE_STRING:
    4733         default:
    4734             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4735     }
    4736     NOREF(pDbgc);
    4737     return 0;
    4738 }
    4739 
    4740 
    4741 /**
    4742  * Boolean not (unary).
    4743  *
    4744  * @returns 0 on success.
    4745  * @returns VBox evaluation / parsing error code on failure.
    4746  *          The caller does the bitching.
    4747  * @param   pDbgc       Debugger console instance data.
    4748  * @param   pArg        The argument.
    4749  * @param   pResult     Where to store the result.
    4750  */
    4751 static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    4752 {
    4753 //    LogFlow(("dbgcOpBooleanNot\n"));
    4754     *pResult = *pArg;
    4755     switch (pArg->enmType)
    4756     {
    4757         case DBGCVAR_TYPE_GC_FLAT:
    4758             pResult->u.u64Number    = !pResult->u.GCFlat;
    4759             break;
    4760         case DBGCVAR_TYPE_GC_FAR:
    4761             pResult->u.u64Number    = !pResult->u.GCFar.off && pResult->u.GCFar.sel <= 3;
    4762             break;
    4763         case DBGCVAR_TYPE_GC_PHYS:
    4764             pResult->u.u64Number    = !pResult->u.GCPhys;
    4765             break;
    4766         case DBGCVAR_TYPE_HC_FLAT:
    4767             pResult->u.u64Number    = !pResult->u.pvHCFlat;
    4768             break;
    4769         case DBGCVAR_TYPE_HC_FAR:
    4770             pResult->u.u64Number    = !pResult->u.HCFar.off && pResult->u.HCFar.sel <= 3;
    4771             break;
    4772         case DBGCVAR_TYPE_HC_PHYS:
    4773             pResult->u.u64Number    = !pResult->u.HCPhys;
    4774             break;
    4775         case DBGCVAR_TYPE_NUMBER:
    4776             pResult->u.u64Number    = !pResult->u.u64Number;
    4777             break;
    4778         case DBGCVAR_TYPE_STRING:
    4779             pResult->u.u64Number    = !pResult->u64Range;
    4780             break;
    4781 
    4782         case DBGCVAR_TYPE_UNKNOWN:
    4783         default:
    4784             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4785     }
    4786     pResult->enmType = DBGCVAR_TYPE_NUMBER;
    4787     NOREF(pDbgc);
    4788     return 0;
    4789 }
    4790 
    4791 
    4792 /**
    4793  * Bitwise not (unary).
    4794  *
    4795  * @returns 0 on success.
    4796  * @returns VBox evaluation / parsing error code on failure.
    4797  *          The caller does the bitching.
    4798  * @param   pDbgc       Debugger console instance data.
    4799  * @param   pArg        The argument.
    4800  * @param   pResult     Where to store the result.
    4801  */
    4802 static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    4803 {
    4804 //    LogFlow(("dbgcOpBitwiseNot\n"));
    4805     *pResult = *pArg;
    4806     switch (pArg->enmType)
    4807     {
    4808         case DBGCVAR_TYPE_GC_FLAT:
    4809             pResult->u.GCFlat       = ~pResult->u.GCFlat;
    4810             break;
    4811         case DBGCVAR_TYPE_GC_FAR:
    4812             pResult->u.GCFar.off    = ~pResult->u.GCFar.off;
    4813             break;
    4814         case DBGCVAR_TYPE_GC_PHYS:
    4815             pResult->u.GCPhys       = ~pResult->u.GCPhys;
    4816             break;
    4817         case DBGCVAR_TYPE_HC_FLAT:
    4818             pResult->u.pvHCFlat     = (void *)~(uintptr_t)pResult->u.pvHCFlat;
    4819             break;
    4820         case DBGCVAR_TYPE_HC_FAR:
    4821             pResult->u.HCFar.off= ~pResult->u.HCFar.off;
    4822             break;
    4823         case DBGCVAR_TYPE_HC_PHYS:
    4824             pResult->u.HCPhys       = ~pResult->u.HCPhys;
    4825             break;
    4826         case DBGCVAR_TYPE_NUMBER:
    4827             pResult->u.u64Number    = ~pResult->u.u64Number;
    4828             break;
    4829 
    4830         case DBGCVAR_TYPE_UNKNOWN:
    4831         case DBGCVAR_TYPE_STRING:
    4832         default:
    4833             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4834     }
    4835     NOREF(pDbgc);
    4836     return 0;
    4837 }
    4838 
    4839 
    4840 /**
    4841  * Reference variable (unary).
    4842  *
    4843  * @returns 0 on success.
    4844  * @returns VBox evaluation / parsing error code on failure.
    4845  *          The caller does the bitching.
    4846  * @param   pDbgc       Debugger console instance data.
    4847  * @param   pArg        The argument.
    4848  * @param   pResult     Where to store the result.
    4849  */
    4850 static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    4851 {
    4852 //    LogFlow(("dbgcOpVar: %s\n", pArg->u.pszString));
    4853     /*
    4854      * Parse sanity.
    4855      */
    4856     if (pArg->enmType != DBGCVAR_TYPE_STRING)
    4857         return VERR_PARSE_INCORRECT_ARG_TYPE;
    4858 
    4859     /*
    4860      * Lookup the variable.
    4861      */
    4862     const char *pszVar = pArg->u.pszString;
    4863     for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
    4864     {
    4865         if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
    4866         {
    4867             *pResult = pDbgc->papVars[iVar]->Var;
    4868             return 0;
    4869         }
    4870     }
    4871 
    4872     return VERR_PARSE_VARIABLE_NOT_FOUND;
    4873 }
    4874 
    4875 
    4876 /**
    4877  * Flat address (unary).
    4878  *
    4879  * @returns VINF_SUCCESS on success.
    4880  * @returns VBox evaluation / parsing error code on failure.
    4881  *          The caller does the bitching.
    4882  * @param   pDbgc       Debugger console instance data.
    4883  * @param   pArg        The argument.
    4884  * @param   pResult     Where to store the result.
    4885  */
    4886 static DECLCALLBACK(int) dbgcOpAddrFlat(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    4887 {
    4888 //    LogFlow(("dbgcOpAddrFlat\n"));
    4889     int     rc;
    4890     *pResult = *pArg;
    4891 
    4892     switch (pArg->enmType)
    4893     {
    4894         case DBGCVAR_TYPE_GC_FLAT:
    4895             return VINF_SUCCESS;
    4896 
    4897         case DBGCVAR_TYPE_GC_FAR:
    4898         {
    4899             Assert(pDbgc->pVM);
    4900             DBGFADDRESS Address;
    4901             rc = DBGFR3AddrFromSelOff(pDbgc->pVM, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
    4902             if (VBOX_SUCCESS(rc))
    4903             {
    4904                 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
    4905                 pResult->u.GCFlat = Address.FlatPtr;
    4906                 return VINF_SUCCESS;
    4907             }
    4908             return VERR_PARSE_CONVERSION_FAILED;
    4909         }
    4910 
    4911         case DBGCVAR_TYPE_GC_PHYS:
    4912             //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
    4913             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4914 
    4915         case DBGCVAR_TYPE_HC_FLAT:
    4916             return VINF_SUCCESS;
    4917 
    4918         case DBGCVAR_TYPE_HC_FAR:
    4919             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4920 
    4921         case DBGCVAR_TYPE_HC_PHYS:
    4922             Assert(pDbgc->pVM);
    4923             pResult->enmType        = DBGCVAR_TYPE_HC_FLAT;
    4924             rc = MMR3HCPhys2HCVirt(pDbgc->pVM, pResult->u.HCPhys, &pResult->u.pvHCFlat);
    4925             if (VBOX_SUCCESS(rc))
    4926                 return VINF_SUCCESS;
    4927             return VERR_PARSE_CONVERSION_FAILED;
    4928 
    4929         case DBGCVAR_TYPE_NUMBER:
    4930             pResult->enmType    = DBGCVAR_TYPE_GC_FLAT;
    4931             pResult->u.GCFlat   = (RTGCPTR)pResult->u.u64Number;
    4932             return VINF_SUCCESS;
    4933 
    4934         case DBGCVAR_TYPE_STRING:
    4935             return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_FLAT, pResult);
    4936 
    4937         case DBGCVAR_TYPE_UNKNOWN:
    4938         default:
    4939             return VERR_PARSE_INCORRECT_ARG_TYPE;
    4940     }
    4941 }
    4942 
    4943 
    4944 /**
    4945  * Physical address (unary).
    4946  *
    4947  * @returns 0 on success.
    4948  * @returns VBox evaluation / parsing error code on failure.
    4949  *          The caller does the bitching.
    4950  * @param   pDbgc       Debugger console instance data.
    4951  * @param   pArg        The argument.
    4952  * @param   pResult     Where to store the result.
    4953  */
    4954 static DECLCALLBACK(int) dbgcOpAddrPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    4955 {
    4956 //    LogFlow(("dbgcOpAddrPhys\n"));
    4957     int     rc;
    4958 
    4959     *pResult = *pArg;
    4960     switch (pArg->enmType)
    4961     {
    4962         case DBGCVAR_TYPE_GC_FLAT:
    4963             Assert(pDbgc->pVM);
    4964             pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
    4965             rc = PGMPhysGCPtr2GCPhys(pDbgc->pVM, pArg->u.GCFlat, &pResult->u.GCPhys);
    4966             if (VBOX_SUCCESS(rc))
    4967                 return 0;
    4968             /** @todo more memory types! */
    4969             return VERR_PARSE_CONVERSION_FAILED;
    4970 
    4971         case DBGCVAR_TYPE_GC_FAR:
    4972         {
    4973             Assert(pDbgc->pVM);
    4974             DBGFADDRESS Address;
    4975             rc = DBGFR3AddrFromSelOff(pDbgc->pVM, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
    4976             if (VBOX_SUCCESS(rc))
    4977             {
    4978                 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
    4979                 rc = PGMPhysGCPtr2GCPhys(pDbgc->pVM, Address.FlatPtr, &pResult->u.GCPhys);
    4980                 if (VBOX_SUCCESS(rc))
    4981                     return 0;
    4982                 /** @todo more memory types! */
    4983             }
    4984             return VERR_PARSE_CONVERSION_FAILED;
    4985         }
    4986 
    4987         case DBGCVAR_TYPE_GC_PHYS:
    4988             return 0;
    4989 
    4990         case DBGCVAR_TYPE_HC_FLAT:
    4991             Assert(pDbgc->pVM);
    4992             pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
    4993             rc = PGMR3DbgHCPtr2GCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
    4994             if (VBOX_SUCCESS(rc))
    4995                 return 0;
    4996             /** @todo more memory types! */
    4997             return VERR_PARSE_CONVERSION_FAILED;
    4998 
    4999         case DBGCVAR_TYPE_HC_FAR:
    5000             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5001 
    5002         case DBGCVAR_TYPE_HC_PHYS:
    5003             return 0;
    5004 
    5005         case DBGCVAR_TYPE_NUMBER:
    5006             pResult->enmType    = DBGCVAR_TYPE_GC_PHYS;
    5007             pResult->u.GCPhys   = (RTGCPHYS)pResult->u.u64Number;
    5008             return 0;
    5009 
    5010         case DBGCVAR_TYPE_STRING:
    5011             return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_PHYS, pResult);
    5012 
    5013         case DBGCVAR_TYPE_UNKNOWN:
    5014         default:
    5015             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5016     }
    5017     return 0;
    5018 }
    5019 
    5020 
    5021 /**
    5022  * Physical host address (unary).
    5023  *
    5024  * @returns 0 on success.
    5025  * @returns VBox evaluation / parsing error code on failure.
    5026  *          The caller does the bitching.
    5027  * @param   pDbgc       Debugger console instance data.
    5028  * @param   pArg        The argument.
    5029  * @param   pResult     Where to store the result.
    5030  */
    5031 static DECLCALLBACK(int) dbgcOpAddrHostPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    5032 {
    5033 //    LogFlow(("dbgcOpAddrPhys\n"));
    5034     int     rc;
    5035 
    5036     *pResult = *pArg;
    5037     switch (pArg->enmType)
    5038     {
    5039         case DBGCVAR_TYPE_GC_FLAT:
    5040             Assert(pDbgc->pVM);
    5041             pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
    5042             rc = PGMPhysGCPtr2HCPhys(pDbgc->pVM, pArg->u.GCFlat, &pResult->u.HCPhys);
    5043             if (VBOX_SUCCESS(rc))
    5044                 return 0;
    5045             /** @todo more memory types. */
    5046             return VERR_PARSE_CONVERSION_FAILED;
    5047 
    5048         case DBGCVAR_TYPE_GC_FAR:
    5049         {
    5050             Assert(pDbgc->pVM);
    5051             DBGFADDRESS Address;
    5052             rc = DBGFR3AddrFromSelOff(pDbgc->pVM, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
    5053             if (VBOX_SUCCESS(rc))
    5054             {
    5055                 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
    5056                 rc = PGMPhysGCPtr2HCPhys(pDbgc->pVM, Address.FlatPtr, &pResult->u.HCPhys);
    5057                 if (VBOX_SUCCESS(rc))
    5058                     return 0;
    5059                 /** @todo more memory types. */
    5060             }
    5061             return VERR_PARSE_CONVERSION_FAILED;
    5062         }
    5063 
    5064         case DBGCVAR_TYPE_GC_PHYS:
    5065             Assert(pDbgc->pVM);
    5066             pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
    5067             rc = PGMPhysGCPhys2HCPhys(pDbgc->pVM, pArg->u.GCFlat, &pResult->u.HCPhys);
    5068             if (VBOX_SUCCESS(rc))
    5069                 return 0;
    5070             return VERR_PARSE_CONVERSION_FAILED;
    5071 
    5072         case DBGCVAR_TYPE_HC_FLAT:
    5073             Assert(pDbgc->pVM);
    5074             pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
    5075             rc = PGMR3DbgHCPtr2HCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
    5076             if (VBOX_SUCCESS(rc))
    5077                 return 0;
    5078             /** @todo more memory types! */
    5079             return VERR_PARSE_CONVERSION_FAILED;
    5080 
    5081         case DBGCVAR_TYPE_HC_FAR:
    5082             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5083 
    5084         case DBGCVAR_TYPE_HC_PHYS:
    5085             return 0;
    5086 
    5087         case DBGCVAR_TYPE_NUMBER:
    5088             pResult->enmType    = DBGCVAR_TYPE_HC_PHYS;
    5089             pResult->u.HCPhys   = (RTGCPHYS)pResult->u.u64Number;
    5090             return 0;
    5091 
    5092         case DBGCVAR_TYPE_STRING:
    5093             return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_PHYS, pResult);
    5094 
    5095         case DBGCVAR_TYPE_UNKNOWN:
    5096         default:
    5097             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5098     }
    5099     return 0;
    5100 }
    5101 
    5102 
    5103 /**
    5104  * Host address (unary).
    5105  *
    5106  * @returns 0 on success.
    5107  * @returns VBox evaluation / parsing error code on failure.
    5108  *          The caller does the bitching.
    5109  * @param   pDbgc       Debugger console instance data.
    5110  * @param   pArg        The argument.
    5111  * @param   pResult     Where to store the result.
    5112  */
    5113 static DECLCALLBACK(int) dbgcOpAddrHost(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
    5114 {
    5115 //    LogFlow(("dbgcOpAddrHost\n"));
    5116     int     rc;
    5117 
    5118     *pResult = *pArg;
    5119     switch (pArg->enmType)
    5120     {
    5121         case DBGCVAR_TYPE_GC_FLAT:
    5122             Assert(pDbgc->pVM);
    5123             pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
    5124             rc = PGMPhysGCPtr2HCPtr(pDbgc->pVM, pArg->u.GCFlat, &pResult->u.pvHCFlat);
    5125             if (VBOX_SUCCESS(rc))
    5126                 return 0;
    5127             /** @todo more memory types. */
    5128             return VERR_PARSE_CONVERSION_FAILED;
    5129 
    5130         case DBGCVAR_TYPE_GC_FAR:
    5131         {
    5132             Assert(pDbgc->pVM);
    5133             DBGFADDRESS Address;
    5134             rc = DBGFR3AddrFromSelOff(pDbgc->pVM, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
    5135             if (VBOX_SUCCESS(rc))
    5136             {
    5137                 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
    5138                 rc = PGMPhysGCPtr2HCPtr(pDbgc->pVM, Address.FlatPtr, &pResult->u.pvHCFlat);
    5139                 if (VBOX_SUCCESS(rc))
    5140                     return 0;
    5141                 /** @todo more memory types. */
    5142             }
    5143             return VERR_PARSE_CONVERSION_FAILED;
    5144         }
    5145 
    5146         case DBGCVAR_TYPE_GC_PHYS:
    5147             Assert(pDbgc->pVM);
    5148             pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
    5149             rc = PGMPhysGCPhys2HCPtr(pDbgc->pVM, pArg->u.GCPhys, 1, &pResult->u.pvHCFlat);
    5150             if (VBOX_SUCCESS(rc))
    5151                 return 0;
    5152             return VERR_PARSE_CONVERSION_FAILED;
    5153 
    5154         case DBGCVAR_TYPE_HC_FLAT:
    5155             return 0;
    5156 
    5157         case DBGCVAR_TYPE_HC_FAR:
    5158         case DBGCVAR_TYPE_HC_PHYS:
    5159             /** @todo !*/
    5160             return VERR_PARSE_CONVERSION_FAILED;
    5161 
    5162         case DBGCVAR_TYPE_NUMBER:
    5163             pResult->enmType    = DBGCVAR_TYPE_HC_FLAT;
    5164             pResult->u.pvHCFlat = (void *)(uintptr_t)pResult->u.u64Number;
    5165             return 0;
    5166 
    5167         case DBGCVAR_TYPE_STRING:
    5168             return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_FLAT, pResult);
    5169 
    5170         case DBGCVAR_TYPE_UNKNOWN:
    5171         default:
    5172             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5173     }
    5174 }
    5175 
    5176 /**
    5177  * Bitwise not (unary).
    5178  *
    5179  * @returns 0 on success.
    5180  * @returns VBox evaluation / parsing error code on failure.
    5181  *          The caller does the bitching.
    5182  * @param   pDbgc       Debugger console instance data.
    5183  * @param   pArg        The argument.
    5184  * @param   pResult     Where to store the result.
    5185  */
    5186 static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5187 {
    5188 //    LogFlow(("dbgcOpAddrFar\n"));
    5189     int     rc;
    5190 
    5191     switch (pArg1->enmType)
    5192     {
    5193         case DBGCVAR_TYPE_STRING:
    5194             rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
    5195             if (VBOX_FAILURE(rc))
    5196                 return rc;
    5197             break;
    5198         case DBGCVAR_TYPE_NUMBER:
    5199             *pResult = *pArg1;
    5200             break;
    5201 
    5202         case DBGCVAR_TYPE_GC_FLAT:
    5203         case DBGCVAR_TYPE_GC_FAR:
    5204         case DBGCVAR_TYPE_GC_PHYS:
    5205         case DBGCVAR_TYPE_HC_FLAT:
    5206         case DBGCVAR_TYPE_HC_FAR:
    5207         case DBGCVAR_TYPE_HC_PHYS:
    5208         case DBGCVAR_TYPE_UNKNOWN:
    5209         default:
    5210             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5211     }
    5212     pResult->u.GCFar.sel = (RTSEL)pResult->u.u64Number;
    5213 
    5214     /* common code for the two types we support. */
    5215     switch (pArg2->enmType)
    5216     {
    5217         case DBGCVAR_TYPE_GC_FLAT:
    5218             pResult->u.GCFar.off = pArg2->u.GCFlat;
    5219             pResult->enmType    = DBGCVAR_TYPE_GC_FAR;
    5220             break;
    5221 
    5222         case DBGCVAR_TYPE_HC_FLAT:
    5223             pResult->u.HCFar.off = pArg2->u.GCFlat;
    5224             pResult->enmType    = DBGCVAR_TYPE_GC_FAR;
    5225             break;
    5226 
    5227         case DBGCVAR_TYPE_NUMBER:
    5228             pResult->u.GCFar.off = (RTGCPTR)pArg2->u.u64Number;
    5229             pResult->enmType    = DBGCVAR_TYPE_GC_FAR;
    5230             break;
    5231 
    5232         case DBGCVAR_TYPE_STRING:
    5233         {
    5234             DBGCVAR Var;
    5235             rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
    5236             if (VBOX_FAILURE(rc))
    5237                 return rc;
    5238             pResult->u.GCFar.off = (RTGCPTR)Var.u.u64Number;
    5239             pResult->enmType    = DBGCVAR_TYPE_GC_FAR;
    5240             break;
    5241         }
    5242 
    5243         case DBGCVAR_TYPE_GC_FAR:
    5244         case DBGCVAR_TYPE_GC_PHYS:
    5245         case DBGCVAR_TYPE_HC_FAR:
    5246         case DBGCVAR_TYPE_HC_PHYS:
    5247         case DBGCVAR_TYPE_UNKNOWN:
    5248         default:
    5249             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5250     }
    5251     return 0;
    5252 
    5253 }
    5254 
    5255 
    5256 /**
    5257  * Multiplication operator (binary).
    5258  *
    5259  * @returns 0 on success.
    5260  * @returns VBox evaluation / parsing error code on failure.
    5261  *          The caller does the bitching.
    5262  * @param   pDbgc       Debugger console instance data.
    5263  * @param   pArg1       The first argument.
    5264  * @param   pArg2       The 2nd argument.
    5265  * @param   pResult     Where to store the result.
    5266  */
    5267 static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5268 {
    5269 //    LogFlow(("dbgcOpMult\n"));
    5270     int     rc;
    5271 
    5272     /*
    5273      * Switch the factors so we preserve pointers, far pointers are considered more
    5274      * important that physical and flat pointers.
    5275      */
    5276     if (    DBGCVAR_ISPOINTER(pArg2->enmType)
    5277         &&  (   !DBGCVAR_ISPOINTER(pArg1->enmType)
    5278              || (   DBGCVAR_IS_FAR_PTR(pArg2->enmType)
    5279                  && !DBGCVAR_IS_FAR_PTR(pArg1->enmType))))
    5280     {
    5281         PCDBGCVAR pTmp = pArg1;
    5282         pArg2 = pArg1;
    5283         pArg1 = pTmp;
    5284     }
    5285 
    5286     /*
    5287      * Convert the 2nd number into a number we use multiply the first with.
    5288      */
    5289     DBGCVAR Factor2 = *pArg2;
    5290     if (    Factor2.enmType == DBGCVAR_TYPE_STRING
    5291         ||  Factor2.enmType == DBGCVAR_TYPE_SYMBOL)
    5292     {
    5293         rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Factor2);
    5294         if (VBOX_FAILURE(rc))
    5295             return rc;
    5296     }
    5297     uint64_t u64Factor;
    5298     switch (Factor2.enmType)
    5299     {
    5300         case DBGCVAR_TYPE_GC_FLAT:  u64Factor = Factor2.u.GCFlat; break;
    5301         case DBGCVAR_TYPE_GC_FAR:   u64Factor = Factor2.u.GCFar.off; break;
    5302         case DBGCVAR_TYPE_GC_PHYS:  u64Factor = Factor2.u.GCPhys; break;
    5303         case DBGCVAR_TYPE_HC_FLAT:  u64Factor = (uintptr_t)Factor2.u.pvHCFlat; break;
    5304         case DBGCVAR_TYPE_HC_FAR:   u64Factor = Factor2.u.HCFar.off; break;
    5305         case DBGCVAR_TYPE_HC_PHYS:  u64Factor = Factor2.u.HCPhys; break;
    5306         case DBGCVAR_TYPE_NUMBER:   u64Factor = Factor2.u.u64Number; break;
    5307         default:
    5308             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5309     }
    5310 
    5311     /*
    5312      * Fix symbols in the 1st factor.
    5313      */
    5314     *pResult = *pArg1;
    5315     if (    pResult->enmType == DBGCVAR_TYPE_STRING
    5316         ||  pResult->enmType == DBGCVAR_TYPE_SYMBOL)
    5317     {
    5318         rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
    5319         if (VBOX_FAILURE(rc))
    5320             return rc;
    5321     }
    5322 
    5323     /*
    5324      * Do the multiplication.
    5325      */
    5326     switch (pArg1->enmType)
    5327     {
    5328         case DBGCVAR_TYPE_GC_FLAT:  pResult->u.GCFlat *= u64Factor; break;
    5329         case DBGCVAR_TYPE_GC_FAR:   pResult->u.GCFar.off *= u64Factor; break;
    5330         case DBGCVAR_TYPE_GC_PHYS:  pResult->u.GCPhys *= u64Factor; break;
    5331         case DBGCVAR_TYPE_HC_FLAT:
    5332             pResult->u.pvHCFlat = (void *)(uintptr_t)((uintptr_t)pResult->u.pvHCFlat * u64Factor);
    5333             break;
    5334         case DBGCVAR_TYPE_HC_FAR:   pResult->u.HCFar.off *= u64Factor; break;
    5335         case DBGCVAR_TYPE_HC_PHYS:  pResult->u.HCPhys *= u64Factor; break;
    5336         case DBGCVAR_TYPE_NUMBER:   pResult->u.u64Number *= u64Factor; break;
    5337         default:
    5338             return VERR_PARSE_INCORRECT_ARG_TYPE;
    5339     }
    5340     return 0;
    5341 }
    5342 
    5343 
    5344 /**
    5345  * Division operator (binary).
    5346  *
    5347  * @returns 0 on success.
    5348  * @returns VBox evaluation / parsing error code on failure.
    5349  *          The caller does the bitching.
    5350  * @param   pDbgc       Debugger console instance data.
    5351  * @param   pArg1       The first argument.
    5352  * @param   pArg2       The 2nd argument.
    5353  * @param   pResult     Where to store the result.
    5354  */
    5355 static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5356 {
    5357     LogFlow(("dbgcOpDiv\n"));
    5358     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5359     return -1;
    5360 }
    5361 
    5362 
    5363 /**
    5364  * Modulus operator (binary).
    5365  *
    5366  * @returns 0 on success.
    5367  * @returns VBox evaluation / parsing error code on failure.
    5368  *          The caller does the bitching.
    5369  * @param   pDbgc       Debugger console instance data.
    5370  * @param   pArg1       The first argument.
    5371  * @param   pArg2       The 2nd argument.
    5372  * @param   pResult     Where to store the result.
    5373  */
    5374 static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5375 {
    5376     LogFlow(("dbgcOpMod\n"));
    5377     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5378     return -1;
    5379 }
    5380 
    5381 
    5382 /**
    5383  * Addition operator (binary).
    5384  *
    5385  * @returns 0 on success.
    5386  * @returns VBox evaluation / parsing error code on failure.
    5387  *          The caller does the bitching.
    5388  * @param   pDbgc       Debugger console instance data.
    5389  * @param   pArg1       The first argument.
    5390  * @param   pArg2       The 2nd argument.
    5391  * @param   pResult     Where to store the result.
    5392  */
    5393 static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5394 {
    5395 //    LogFlow(("dbgcOpAdd\n"));
    5396 
    5397     /*
    5398      * An addition operation will return (when possible) the left side type in the
    5399      * expression. We make an omission for numbers, where we'll take the right side
    5400      * type instead. An expression where only the left hand side is a string we'll
    5401      * use the right hand type assuming that the string is a symbol.
    5402      */
    5403     if (    (pArg1->enmType == DBGCVAR_TYPE_NUMBER && pArg2->enmType != DBGCVAR_TYPE_STRING)
    5404         ||  (pArg1->enmType == DBGCVAR_TYPE_STRING && pArg2->enmType != DBGCVAR_TYPE_STRING))
    5405     {
    5406         PCDBGCVAR pTmp = pArg2;
    5407         pArg2 = pArg1;
    5408         pArg1 = pTmp;
    5409     }
    5410     DBGCVAR     Sym1, Sym2;
    5411     if (pArg1->enmType == DBGCVAR_TYPE_STRING)
    5412     {
    5413         int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
    5414         if (VBOX_FAILURE(rc))
    5415             return rc;
    5416         pArg1 = &Sym1;
    5417 
    5418         rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
    5419         if (VBOX_FAILURE(rc))
    5420             return rc;
    5421         pArg2 = &Sym2;
    5422     }
    5423 
    5424     int         rc;
    5425     DBGCVAR     Var;
    5426     DBGCVAR     Var2;
    5427     switch (pArg1->enmType)
    5428     {
    5429         /*
    5430          * GC Flat
    5431          */
    5432         case DBGCVAR_TYPE_GC_FLAT:
    5433             switch (pArg2->enmType)
    5434             {
    5435                 case DBGCVAR_TYPE_HC_FLAT:
    5436                 case DBGCVAR_TYPE_HC_FAR:
    5437                 case DBGCVAR_TYPE_HC_PHYS:
    5438                     return VERR_PARSE_INVALID_OPERATION;
    5439                 default:
    5440                     *pResult = *pArg1;
    5441                     rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
    5442                     if (VBOX_FAILURE(rc))
    5443                         return rc;
    5444                     pResult->u.GCFlat += pArg2->u.GCFlat;
    5445                     break;
    5446             }
    5447             break;
    5448 
    5449         /*
    5450          * GC Far
    5451          */
    5452         case DBGCVAR_TYPE_GC_FAR:
    5453             switch (pArg2->enmType)
    5454             {
    5455                 case DBGCVAR_TYPE_HC_FLAT:
    5456                 case DBGCVAR_TYPE_HC_FAR:
    5457                 case DBGCVAR_TYPE_HC_PHYS:
    5458                     return VERR_PARSE_INVALID_OPERATION;
    5459                 case DBGCVAR_TYPE_NUMBER:
    5460                     *pResult = *pArg1;
    5461                     pResult->u.GCFar.off += (RTGCPTR)pArg2->u.u64Number;
    5462                     break;
    5463                 default:
    5464                     rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
    5465                     if (VBOX_FAILURE(rc))
    5466                         return rc;
    5467                     rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
    5468                     if (VBOX_FAILURE(rc))
    5469                         return rc;
    5470                     pResult->u.GCFlat += pArg2->u.GCFlat;
    5471                     break;
    5472             }
    5473             break;
    5474 
    5475         /*
    5476          * GC Phys
    5477          */
    5478         case DBGCVAR_TYPE_GC_PHYS:
    5479             switch (pArg2->enmType)
    5480             {
    5481                 case DBGCVAR_TYPE_HC_FLAT:
    5482                 case DBGCVAR_TYPE_HC_FAR:
    5483                 case DBGCVAR_TYPE_HC_PHYS:
    5484                     return VERR_PARSE_INVALID_OPERATION;
    5485                 default:
    5486                     *pResult = *pArg1;
    5487                     rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
    5488                     if (VBOX_FAILURE(rc))
    5489                         return rc;
    5490                     if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
    5491                         return VERR_PARSE_INVALID_OPERATION;
    5492                     pResult->u.GCPhys += Var.u.GCPhys;
    5493                     break;
    5494             }
    5495             break;
    5496 
    5497         /*
    5498          * HC Flat
    5499          */
    5500         case DBGCVAR_TYPE_HC_FLAT:
    5501             *pResult = *pArg1;
    5502             rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
    5503             if (VBOX_FAILURE(rc))
    5504                 return rc;
    5505             rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
    5506             if (VBOX_FAILURE(rc))
    5507                 return rc;
    5508             pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
    5509             break;
    5510 
    5511         /*
    5512          * HC Far
    5513          */
    5514         case DBGCVAR_TYPE_HC_FAR:
    5515             switch (pArg2->enmType)
    5516             {
    5517                 case DBGCVAR_TYPE_NUMBER:
    5518                     *pResult = *pArg1;
    5519                     pResult->u.HCFar.off += (uintptr_t)pArg2->u.u64Number;
    5520                     break;
    5521 
    5522                 default:
    5523                     rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
    5524                     if (VBOX_FAILURE(rc))
    5525                         return rc;
    5526                     rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
    5527                     if (VBOX_FAILURE(rc))
    5528                         return rc;
    5529                     rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
    5530                     if (VBOX_FAILURE(rc))
    5531                         return rc;
    5532                     pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
    5533                     break;
    5534             }
    5535             break;
    5536 
    5537         /*
    5538          * HC Phys
    5539          */
    5540         case DBGCVAR_TYPE_HC_PHYS:
    5541             *pResult = *pArg1;
    5542             rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
    5543             if (VBOX_FAILURE(rc))
    5544                 return rc;
    5545             pResult->u.HCPhys += Var.u.HCPhys;
    5546             break;
    5547 
    5548         /*
    5549          * Numbers (see start of function)
    5550          */
    5551         case DBGCVAR_TYPE_NUMBER:
    5552             *pResult = *pArg1;
    5553             switch (pArg2->enmType)
    5554             {
    5555                 case DBGCVAR_TYPE_SYMBOL:
    5556                 case DBGCVAR_TYPE_STRING:
    5557                     rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
    5558                     if (VBOX_FAILURE(rc))
    5559                         return rc;
    5560                 case DBGCVAR_TYPE_NUMBER:
    5561                     pResult->u.u64Number += pArg2->u.u64Number;
    5562                     break;
    5563                 default:
    5564                     return VERR_PARSE_INVALID_OPERATION;
    5565             }
    5566             break;
    5567 
    5568         default:
    5569             return VERR_PARSE_INVALID_OPERATION;
    5570 
    5571     }
    5572     return 0;
    5573 }
    5574 
    5575 
    5576 /**
    5577  * Subtration operator (binary).
    5578  *
    5579  * @returns 0 on success.
    5580  * @returns VBox evaluation / parsing error code on failure.
    5581  *          The caller does the bitching.
    5582  * @param   pDbgc       Debugger console instance data.
    5583  * @param   pArg1       The first argument.
    5584  * @param   pArg2       The 2nd argument.
    5585  * @param   pResult     Where to store the result.
    5586  */
    5587 static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5588 {
    5589 //    LogFlow(("dbgcOpSub\n"));
    5590 
    5591     /*
    5592      * An subtraction operation will return the left side type in the expression.
    5593      * However, if the left hand side is a number and the right hand a pointer of
    5594      * some kind we'll convert the left hand side to the same type as the right hand.
    5595      * Any strings will be attempted resolved as symbols.
    5596      */
    5597     DBGCVAR     Sym1, Sym2;
    5598     if (    pArg2->enmType == DBGCVAR_TYPE_STRING
    5599         &&  (   pArg1->enmType == DBGCVAR_TYPE_NUMBER
    5600              || pArg1->enmType == DBGCVAR_TYPE_STRING))
    5601     {
    5602         int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
    5603         if (VBOX_FAILURE(rc))
    5604             return rc;
    5605         pArg2 = &Sym2;
    5606     }
    5607 
    5608     if (pArg1->enmType == DBGCVAR_TYPE_STRING)
    5609     {
    5610         DBGCVARTYPE enmType;
    5611         switch (pArg2->enmType)
    5612         {
    5613             case DBGCVAR_TYPE_NUMBER:
    5614                 enmType = DBGCVAR_TYPE_ANY;
    5615                 break;
    5616             case DBGCVAR_TYPE_GC_FLAT:
    5617             case DBGCVAR_TYPE_GC_PHYS:
    5618             case DBGCVAR_TYPE_HC_FLAT:
    5619             case DBGCVAR_TYPE_HC_PHYS:
    5620                 enmType = pArg2->enmType;
    5621                 break;
    5622             case DBGCVAR_TYPE_GC_FAR:
    5623                 enmType = DBGCVAR_TYPE_GC_FLAT;
    5624                 break;
    5625             case DBGCVAR_TYPE_HC_FAR:
    5626                 enmType = DBGCVAR_TYPE_HC_FLAT;
    5627                 break;
    5628 
    5629             default:
    5630             case DBGCVAR_TYPE_STRING:
    5631                 AssertMsgFailed(("Can't happen\n"));
    5632                 enmType = DBGCVAR_TYPE_STRING;
    5633                 break;
    5634         }
    5635         if (enmType != DBGCVAR_TYPE_STRING)
    5636         {
    5637             int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
    5638             if (VBOX_FAILURE(rc))
    5639                 return rc;
    5640             pArg1 = &Sym1;
    5641         }
    5642     }
    5643     else if (pArg1->enmType == DBGCVAR_TYPE_NUMBER)
    5644     {
    5645         PFNDBGCOPUNARY pOp = NULL;
    5646         switch (pArg2->enmType)
    5647         {
    5648             case DBGCVAR_TYPE_GC_FAR:
    5649             case DBGCVAR_TYPE_GC_FLAT:
    5650                 pOp = dbgcOpAddrFlat;
    5651                 break;
    5652             case DBGCVAR_TYPE_GC_PHYS:
    5653                 pOp = dbgcOpAddrPhys;
    5654                 break;
    5655             case DBGCVAR_TYPE_HC_FAR:
    5656             case DBGCVAR_TYPE_HC_FLAT:
    5657                 pOp = dbgcOpAddrHost;
    5658                 break;
    5659             case DBGCVAR_TYPE_HC_PHYS:
    5660                 pOp = dbgcOpAddrHostPhys;
    5661                 break;
    5662             case DBGCVAR_TYPE_NUMBER:
    5663                 break;
    5664             default:
    5665             case DBGCVAR_TYPE_STRING:
    5666                 AssertMsgFailed(("Can't happen\n"));
    5667                 break;
    5668         }
    5669         if (pOp)
    5670         {
    5671             int rc = pOp(pDbgc, pArg1, &Sym1);
    5672             if (VBOX_FAILURE(rc))
    5673                 return rc;
    5674             pArg1 = &Sym1;
    5675         }
    5676     }
    5677 
    5678 
    5679     /*
    5680      * Normal processing.
    5681      */
    5682     int         rc;
    5683     DBGCVAR     Var;
    5684     DBGCVAR     Var2;
    5685     switch (pArg1->enmType)
    5686     {
    5687         /*
    5688          * GC Flat
    5689          */
    5690         case DBGCVAR_TYPE_GC_FLAT:
    5691             switch (pArg2->enmType)
    5692             {
    5693                 case DBGCVAR_TYPE_HC_FLAT:
    5694                 case DBGCVAR_TYPE_HC_FAR:
    5695                 case DBGCVAR_TYPE_HC_PHYS:
    5696                     return VERR_PARSE_INVALID_OPERATION;
    5697                 default:
    5698                     *pResult = *pArg1;
    5699                     rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
    5700                     if (VBOX_FAILURE(rc))
    5701                         return rc;
    5702                     pResult->u.GCFlat -= pArg2->u.GCFlat;
    5703                     break;
    5704             }
    5705             break;
    5706 
    5707         /*
    5708          * GC Far
    5709          */
    5710         case DBGCVAR_TYPE_GC_FAR:
    5711             switch (pArg2->enmType)
    5712             {
    5713                 case DBGCVAR_TYPE_HC_FLAT:
    5714                 case DBGCVAR_TYPE_HC_FAR:
    5715                 case DBGCVAR_TYPE_HC_PHYS:
    5716                     return VERR_PARSE_INVALID_OPERATION;
    5717                 case DBGCVAR_TYPE_NUMBER:
    5718                     *pResult = *pArg1;
    5719                     pResult->u.GCFar.off -= (RTGCPTR)pArg2->u.u64Number;
    5720                     break;
    5721                 default:
    5722                     rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
    5723                     if (VBOX_FAILURE(rc))
    5724                         return rc;
    5725                     rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
    5726                     if (VBOX_FAILURE(rc))
    5727                         return rc;
    5728                     pResult->u.GCFlat -= pArg2->u.GCFlat;
    5729                     break;
    5730             }
    5731             break;
    5732 
    5733         /*
    5734          * GC Phys
    5735          */
    5736         case DBGCVAR_TYPE_GC_PHYS:
    5737             switch (pArg2->enmType)
    5738             {
    5739                 case DBGCVAR_TYPE_HC_FLAT:
    5740                 case DBGCVAR_TYPE_HC_FAR:
    5741                 case DBGCVAR_TYPE_HC_PHYS:
    5742                     return VERR_PARSE_INVALID_OPERATION;
    5743                 default:
    5744                     *pResult = *pArg1;
    5745                     rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
    5746                     if (VBOX_FAILURE(rc))
    5747                         return rc;
    5748                     if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
    5749                         return VERR_PARSE_INVALID_OPERATION;
    5750                     pResult->u.GCPhys -= Var.u.GCPhys;
    5751                     break;
    5752             }
    5753             break;
    5754 
    5755         /*
    5756          * HC Flat
    5757          */
    5758         case DBGCVAR_TYPE_HC_FLAT:
    5759             *pResult = *pArg1;
    5760             rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
    5761             if (VBOX_FAILURE(rc))
    5762                 return rc;
    5763             rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
    5764             if (VBOX_FAILURE(rc))
    5765                 return rc;
    5766             pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
    5767             break;
    5768 
    5769         /*
    5770          * HC Far
    5771          */
    5772         case DBGCVAR_TYPE_HC_FAR:
    5773             switch (pArg2->enmType)
    5774             {
    5775                 case DBGCVAR_TYPE_NUMBER:
    5776                     *pResult = *pArg1;
    5777                     pResult->u.HCFar.off -= (uintptr_t)pArg2->u.u64Number;
    5778                     break;
    5779 
    5780                 default:
    5781                     rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
    5782                     if (VBOX_FAILURE(rc))
    5783                         return rc;
    5784                     rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
    5785                     if (VBOX_FAILURE(rc))
    5786                         return rc;
    5787                     rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
    5788                     if (VBOX_FAILURE(rc))
    5789                         return rc;
    5790                     pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
    5791                     break;
    5792             }
    5793             break;
    5794 
    5795         /*
    5796          * HC Phys
    5797          */
    5798         case DBGCVAR_TYPE_HC_PHYS:
    5799             *pResult = *pArg1;
    5800             rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
    5801             if (VBOX_FAILURE(rc))
    5802                 return rc;
    5803             pResult->u.HCPhys -= Var.u.HCPhys;
    5804             break;
    5805 
    5806         /*
    5807          * Numbers (see start of function)
    5808          */
    5809         case DBGCVAR_TYPE_NUMBER:
    5810             *pResult = *pArg1;
    5811             switch (pArg2->enmType)
    5812             {
    5813                 case DBGCVAR_TYPE_SYMBOL:
    5814                 case DBGCVAR_TYPE_STRING:
    5815                     rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
    5816                     if (VBOX_FAILURE(rc))
    5817                         return rc;
    5818                 case DBGCVAR_TYPE_NUMBER:
    5819                     pResult->u.u64Number -= pArg2->u.u64Number;
    5820                     break;
    5821                 default:
    5822                     return VERR_PARSE_INVALID_OPERATION;
    5823             }
    5824             break;
    5825 
    5826         default:
    5827             return VERR_PARSE_INVALID_OPERATION;
    5828 
    5829     }
    5830     return 0;
    5831 }
    5832 
    5833 
    5834 /**
    5835  * Bitwise shift left operator (binary).
    5836  *
    5837  * @returns 0 on success.
    5838  * @returns VBox evaluation / parsing error code on failure.
    5839  *          The caller does the bitching.
    5840  * @param   pDbgc       Debugger console instance data.
    5841  * @param   pArg1       The first argument.
    5842  * @param   pArg2       The 2nd argument.
    5843  * @param   pResult     Where to store the result.
    5844  */
    5845 static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5846 {
    5847     LogFlow(("dbgcOpBitwiseShiftLeft\n"));
    5848     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5849     return -1;
    5850 }
    5851 
    5852 
    5853 /**
    5854  * Bitwise shift right operator (binary).
    5855  *
    5856  * @returns 0 on success.
    5857  * @returns VBox evaluation / parsing error code on failure.
    5858  *          The caller does the bitching.
    5859  * @param   pDbgc       Debugger console instance data.
    5860  * @param   pArg1       The first argument.
    5861  * @param   pArg2       The 2nd argument.
    5862  * @param   pResult     Where to store the result.
    5863  */
    5864 static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5865 {
    5866     LogFlow(("dbgcOpBitwiseShiftRight\n"));
    5867     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5868     return -1;
    5869 }
    5870 
    5871 
    5872 /**
    5873  * Bitwise and operator (binary).
    5874  *
    5875  * @returns 0 on success.
    5876  * @returns VBox evaluation / parsing error code on failure.
    5877  *          The caller does the bitching.
    5878  * @param   pDbgc       Debugger console instance data.
    5879  * @param   pArg1       The first argument.
    5880  * @param   pArg2       The 2nd argument.
    5881  * @param   pResult     Where to store the result.
    5882  */
    5883 static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5884 {
    5885     LogFlow(("dbgcOpBitwiseAnd\n"));
    5886     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5887     return -1;
    5888 }
    5889 
    5890 
    5891 /**
    5892  * Bitwise exclusive or operator (binary).
    5893  *
    5894  * @returns 0 on success.
    5895  * @returns VBox evaluation / parsing error code on failure.
    5896  *          The caller does the bitching.
    5897  * @param   pDbgc       Debugger console instance data.
    5898  * @param   pArg1       The first argument.
    5899  * @param   pArg2       The 2nd argument.
    5900  * @param   pResult     Where to store the result.
    5901  */
    5902 static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5903 {
    5904     LogFlow(("dbgcOpBitwiseXor\n"));
    5905     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5906     return -1;
    5907 }
    5908 
    5909 
    5910 /**
    5911  * Bitwise inclusive or operator (binary).
    5912  *
    5913  * @returns 0 on success.
    5914  * @returns VBox evaluation / parsing error code on failure.
    5915  *          The caller does the bitching.
    5916  * @param   pDbgc       Debugger console instance data.
    5917  * @param   pArg1       The first argument.
    5918  * @param   pArg2       The 2nd argument.
    5919  * @param   pResult     Where to store the result.
    5920  */
    5921 static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5922 {
    5923     LogFlow(("dbgcOpBitwiseOr\n"));
    5924     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5925     return -1;
    5926 }
    5927 
    5928 
    5929 /**
    5930  * Boolean and operator (binary).
    5931  *
    5932  * @returns 0 on success.
    5933  * @returns VBox evaluation / parsing error code on failure.
    5934  *          The caller does the bitching.
    5935  * @param   pDbgc       Debugger console instance data.
    5936  * @param   pArg1       The first argument.
    5937  * @param   pArg2       The 2nd argument.
    5938  * @param   pResult     Where to store the result.
    5939  */
    5940 static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5941 {
    5942     LogFlow(("dbgcOpBooleanAnd\n"));
    5943     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5944     return -1;
    5945 }
    5946 
    5947 
    5948 /**
    5949  * Boolean or operator (binary).
    5950  *
    5951  * @returns 0 on success.
    5952  * @returns VBox evaluation / parsing error code on failure.
    5953  *          The caller does the bitching.
    5954  * @param   pDbgc       Debugger console instance data.
    5955  * @param   pArg1       The first argument.
    5956  * @param   pArg2       The 2nd argument.
    5957  * @param   pResult     Where to store the result.
    5958  */
    5959 static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5960 {
    5961     LogFlow(("dbgcOpBooleanOr\n"));
    5962     NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
    5963     return -1;
    5964 }
    5965 
    5966 
    5967 /**
    5968  * Range to operator (binary).
    5969  *
    5970  * @returns 0 on success.
    5971  * @returns VBox evaluation / parsing error code on failure.
    5972  *          The caller does the bitching.
    5973  * @param   pDbgc       Debugger console instance data.
    5974  * @param   pArg1       The first argument.
    5975  * @param   pArg2       The 2nd argument.
    5976  * @param   pResult     Where to store the result.
    5977  */
    5978 static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    5979 {
    5980 //    LogFlow(("dbgcOpRangeLength\n"));
    5981     /*
    5982      * Make result. Strings needs to be resolved into symbols.
    5983      */
    5984     if (pArg1->enmType == DBGCVAR_TYPE_STRING)
    5985     {
    5986         int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
    5987         if (VBOX_FAILURE(rc))
    5988             return rc;
    5989     }
    5990     else
    5991         *pResult = *pArg1;
    5992 
    5993     /*
    5994      * Convert 2nd argument to element count.
    5995      */
    5996     pResult->enmRangeType = DBGCVAR_RANGE_ELEMENTS;
    5997     switch (pArg2->enmType)
    5998     {
    5999         case DBGCVAR_TYPE_NUMBER:
    6000             pResult->u64Range = pArg2->u.u64Number;
    6001             break;
    6002 
    6003         case DBGCVAR_TYPE_STRING:
    6004         {
    6005             int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
    6006             if (VBOX_FAILURE(rc))
    6007                 return rc;
    6008             pResult->u64Range = pArg2->u.u64Number;
    6009             break;
    6010         }
    6011 
    6012         default:
    6013             return VERR_PARSE_INVALID_OPERATION;
    6014     }
    6015 
    6016     return VINF_SUCCESS;
    6017 }
    6018 
    6019 
    6020 /**
    6021  * Range to operator (binary).
    6022  *
    6023  * @returns 0 on success.
    6024  * @returns VBox evaluation / parsing error code on failure.
    6025  *          The caller does the bitching.
    6026  * @param   pDbgc       Debugger console instance data.
    6027  * @param   pArg1       The first argument.
    6028  * @param   pArg2       The 2nd argument.
    6029  * @param   pResult     Where to store the result.
    6030  */
    6031 static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    6032 {
    6033 //    LogFlow(("dbgcOpRangeLengthBytes\n"));
    6034     int rc = dbgcOpRangeLength(pDbgc, pArg1, pArg2, pResult);
    6035     if (VBOX_SUCCESS(rc))
    6036         pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
    6037     return rc;
    6038 }
    6039 
    6040 
    6041 /**
    6042  * Range to operator (binary).
    6043  *
    6044  * @returns 0 on success.
    6045  * @returns VBox evaluation / parsing error code on failure.
    6046  *          The caller does the bitching.
    6047  * @param   pDbgc       Debugger console instance data.
    6048  * @param   pArg1       The first argument.
    6049  * @param   pArg2       The 2nd argument.
    6050  * @param   pResult     Where to store the result.
    6051  */
    6052 static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
    6053 {
    6054 //    LogFlow(("dbgcOpRangeTo\n"));
    6055     /*
    6056      * Calc number of bytes between the two args.
    6057      */
    6058     DBGCVAR Diff;
    6059     int rc = dbgcOpSub(pDbgc, pArg2, pArg1, &Diff);
    6060     if (VBOX_FAILURE(rc))
    6061         return rc;
    6062 
    6063     /*
    6064      * Use the diff as the range of Arg1.
    6065      */
    6066     *pResult = *pArg1;
    6067     pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
    6068     switch (Diff.enmType)
    6069     {
    6070         case DBGCVAR_TYPE_GC_FLAT:
    6071             pResult->u64Range = (RTGCUINTPTR)Diff.u.GCFlat;
    6072             break;
    6073         case DBGCVAR_TYPE_GC_PHYS:
    6074             pResult->u64Range = Diff.u.GCPhys;
    6075             break;
    6076         case DBGCVAR_TYPE_HC_FLAT:
    6077             pResult->u64Range = (uintptr_t)Diff.u.pvHCFlat;
    6078             break;
    6079         case DBGCVAR_TYPE_HC_PHYS:
    6080             pResult->u64Range = Diff.u.HCPhys;
    6081             break;
    6082         case DBGCVAR_TYPE_NUMBER:
    6083             pResult->u64Range = Diff.u.u64Number;
    6084             break;
    6085 
    6086         case DBGCVAR_TYPE_GC_FAR:
    6087         case DBGCVAR_TYPE_STRING:
    6088         case DBGCVAR_TYPE_HC_FAR:
    6089         default:
    6090             AssertMsgFailed(("Impossible!\n"));
    6091             return VERR_PARSE_INVALID_OPERATION;
    6092     }
    6093 
    6094     return 0;
    6095 }
    6096 
    6097 
    6098 
    6099 
    6100 
    6101 /**
    6102  * Output callback.
    6103  *
    6104  * @returns number of bytes written.
    6105  * @param   pvArg       User argument.
    6106  * @param   pachChars   Pointer to an array of utf-8 characters.
    6107  * @param   cbChars     Number of bytes in the character array pointed to by pachChars.
    6108  */
    6109 static DECLCALLBACK(size_t) dbgcFormatOutput(void *pvArg, const char *pachChars, size_t cbChars)
    6110 {
    6111     PDBGC   pDbgc = (PDBGC)pvArg;
    6112     if (cbChars)
    6113     {
    6114         int rc = pDbgc->pBack->pfnWrite(pDbgc->pBack, pachChars, cbChars, NULL);
    6115         if (VBOX_FAILURE(rc))
    6116         {
    6117             pDbgc->rcOutput = rc;
    6118             cbChars = 0;
    6119         }
    6120     }
    6121 
    6122     return cbChars;
    6123 }
    6124 
    6125 
    6126 
    6127 
    6128 
    6129 
    6130 
    6131 
    6132 
    6133 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    6134 //
    6135 //
    6136 //      C a l l b a c k   H e l p e r s
    6137 //
    6138 //
    6139 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    6140 
    6141 
    6142 
    6143 /**
    6144  * Command helper for writing text to the debug console.
    6145  *
    6146  * @returns VBox status.
    6147  * @param   pCmdHlp     Pointer to the command callback structure.
    6148  * @param   pvBuf       What to write.
    6149  * @param   cbBuf       Number of bytes to write.
    6150  * @param   pcbWritten  Where to store the number of bytes actually written.
    6151  *                      If NULL the entire buffer must be successfully written.
    6152  */
    6153 static DECLCALLBACK(int) dbgcHlpWrite(PDBGCCMDHLP pCmdHlp, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
    6154 {
    6155     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    6156     return pDbgc->pBack->pfnWrite(pDbgc->pBack, pvBuf, cbBuf, pcbWritten);
    6157 }
    6158 
    6159 
    6160 /**
    6161  * Command helper for writing formatted text to the debug console.
    6162  *
    6163  * @returns VBox status.
    6164  * @param   pCmdHlp     Pointer to the command callback structure.
    6165  * @param   pcb         Where to store the number of bytes written.
    6166  * @param   pszFormat   The format string.
    6167  *                      This is using the log formatter, so it's format extensions can be used.
    6168  * @param   ...         Arguments specified in the format string.
    6169  */
    6170 static DECLCALLBACK(int) dbgcHlpPrintf(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten, const char *pszFormat, ...)
    6171 {
    6172     /*
    6173      * Do the formatting and output.
    6174      */
    6175     va_list args;
    6176     va_start(args, pszFormat);
    6177     int rc = pCmdHlp->pfnPrintfV(pCmdHlp, pcbWritten, pszFormat, args);
    6178     va_end(args);
    6179 
    6180     return rc;
    6181 }
    6182 
    6183 /**
    6184  * Callback to format non-standard format specifiers.
    6185  *
    6186  * @returns The number of bytes formatted.
    6187  * @param   pvArg           Formatter argument.
    6188  * @param   pfnOutput       Pointer to output function.
    6189  * @param   pvArgOutput     Argument for the output function.
    6190  * @param   ppszFormat      Pointer to the format string pointer. Advance this till the char
    6191  *                          after the format specifier.
    6192  * @param   pArgs           Pointer to the argument list. Use this to fetch the arguments.
    6193  * @param   cchWidth        Format Width. -1 if not specified.
    6194  * @param   cchPrecision    Format Precision. -1 if not specified.
    6195  * @param   fFlags          Flags (RTSTR_NTFS_*).
    6196  * @param   chArgSize       The argument size specifier, 'l' or 'L'.
    6197  */
    6198 static DECLCALLBACK(size_t) dbgcStringFormatter(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
    6199                                                 const char **ppszFormat, va_list *pArgs, int cchWidth,
    6200                                                 int cchPrecision, unsigned fFlags, char chArgSize)
    6201 {
    6202     NOREF(cchWidth); NOREF(cchPrecision); NOREF(fFlags); NOREF(chArgSize); NOREF(pvArg);
    6203     if (**ppszFormat != 'D')
    6204     {
    6205         (*ppszFormat)++;
    6206         return 0;
    6207     }
    6208 
    6209     (*ppszFormat)++;
    6210     switch (**ppszFormat)
    6211     {
    6212         /*
    6213          * Print variable without range.
    6214          * The argument is a const pointer to the variable.
    6215          */
    6216         case 'V':
    6217         {
    6218             (*ppszFormat)++;
    6219             PCDBGCVAR   pVar = va_arg(*pArgs, PCDBGCVAR);
    6220             switch (pVar->enmType)
    6221             {
    6222                 case DBGCVAR_TYPE_GC_FLAT:
    6223                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%VGv", pVar->u.GCFlat);
    6224                 case DBGCVAR_TYPE_GC_FAR:
    6225                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%04x:%08x", pVar->u.GCFar.sel, pVar->u.GCFar.off);
    6226                 case DBGCVAR_TYPE_GC_PHYS:
    6227                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%%%VGp", pVar->u.GCPhys);
    6228                 case DBGCVAR_TYPE_HC_FLAT:
    6229                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%VHv", (uintptr_t)pVar->u.pvHCFlat);
    6230                 case DBGCVAR_TYPE_HC_FAR:
    6231                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%04x:%08x", pVar->u.HCFar.sel, pVar->u.HCFar.off);
    6232                 case DBGCVAR_TYPE_HC_PHYS:
    6233                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%VHp", pVar->u.HCPhys);
    6234                 case DBGCVAR_TYPE_STRING:
    6235                     return pfnOutput(pvArgOutput, pVar->u.pszString, (size_t)pVar->u64Range);
    6236                 case DBGCVAR_TYPE_NUMBER:
    6237                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx", pVar->u.u64Number);
    6238 
    6239                 case DBGCVAR_TYPE_UNKNOWN:
    6240                 default:
    6241                     return pfnOutput(pvArgOutput, "??", 2);
    6242             }
    6243         }
    6244 
    6245         /*
    6246          * Print variable with range.
    6247          * The argument is a const pointer to the variable.
    6248          */
    6249         case 'v':
    6250         {
    6251             (*ppszFormat)++;
    6252             PCDBGCVAR   pVar = va_arg(*pArgs, PCDBGCVAR);
    6253 
    6254             char szRange[32];
    6255             switch (pVar->enmRangeType)
    6256             {
    6257                 case DBGCVAR_RANGE_NONE:
    6258                     szRange[0] = '\0';
    6259                     break;
    6260                 case DBGCVAR_RANGE_ELEMENTS:
    6261                     RTStrPrintf(szRange, sizeof(szRange), " L %llx", pVar->u64Range);
    6262                     break;
    6263                 case DBGCVAR_RANGE_BYTES:
    6264                     RTStrPrintf(szRange, sizeof(szRange), " LB %llx", pVar->u64Range);
    6265                     break;
    6266             }
    6267 
    6268             switch (pVar->enmType)
    6269             {
    6270                 case DBGCVAR_TYPE_GC_FLAT:
    6271                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%VGv%s", pVar->u.GCFlat, szRange);
    6272                 case DBGCVAR_TYPE_GC_FAR:
    6273                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%04x:%08x%s", pVar->u.GCFar.sel, pVar->u.GCFar.off, szRange);
    6274                 case DBGCVAR_TYPE_GC_PHYS:
    6275                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%%%VGp%s", pVar->u.GCPhys, szRange);
    6276                 case DBGCVAR_TYPE_HC_FLAT:
    6277                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%VHv%s", (uintptr_t)pVar->u.pvHCFlat, szRange);
    6278                 case DBGCVAR_TYPE_HC_FAR:
    6279                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%04x:%08x%s", pVar->u.HCFar.sel, pVar->u.HCFar.off, szRange);
    6280                 case DBGCVAR_TYPE_HC_PHYS:
    6281                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%VHp%s", pVar->u.HCPhys, szRange);
    6282                 case DBGCVAR_TYPE_STRING:
    6283                     return pfnOutput(pvArgOutput, pVar->u.pszString, (size_t)pVar->u64Range);
    6284                 case DBGCVAR_TYPE_NUMBER:
    6285                     return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx%s", pVar->u.u64Number, szRange);
    6286 
    6287                 case DBGCVAR_TYPE_UNKNOWN:
    6288                 default:
    6289                     return pfnOutput(pvArgOutput, "??", 2);
    6290             }
    6291         }
    6292 
    6293         default:
    6294             AssertMsgFailed(("Invalid format type '%s'!\n", **ppszFormat));
    6295             return 0;
    6296     }
    6297 }
    6298 
    6299 
    6300 /**
    6301  * Command helper for writing formatted text to the debug console.
    6302  *
    6303  * @returns VBox status.
    6304  * @param   pCmdHlp     Pointer to the command callback structure.
    6305  * @param   pcb         Where to store the number of bytes written.
    6306  * @param   pszFormat   The format string.
    6307  *                      This is using the log formatter, so it's format extensions can be used.
    6308  * @param   args        Arguments specified in the format string.
    6309  */
    6310 static DECLCALLBACK(int) dbgcHlpPrintfV(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten, const char *pszFormat, va_list args)
    6311 {
    6312     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    6313 
    6314     /*
    6315      * Do the formatting and output.
    6316      */
    6317     pDbgc->rcOutput = 0;
    6318     size_t cb = RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, args);
    6319 
    6320     if (pcbWritten)
    6321         *pcbWritten = cb;
    6322 
    6323     return pDbgc->rcOutput;
    6324 }
    6325 
    6326 
    6327 /**
    6328  * Reports an error from a DBGF call.
    6329  *
    6330  * @returns VBox status code appropriate to return from a command.
    6331  * @param   pCmdHlp     Pointer to command helpers.
    6332  * @param   rc          The VBox status code returned by a DBGF call.
    6333  * @param   pszFormat   Format string for additional messages. Can be NULL.
    6334  * @param   ...         Format arguments, optional.
    6335  */
    6336 static DECLCALLBACK(int) dbgcHlpVBoxErrorV(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, va_list args)
    6337 {
    6338     switch (rc)
    6339     {
    6340         case VINF_SUCCESS:
    6341             break;
    6342 
    6343         default:
    6344             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: %Vrc: %s", rc, pszFormat ? " " : "\n");
    6345             if (VBOX_SUCCESS(rc) && pszFormat)
    6346                 rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
    6347             break;
    6348     }
    6349     return rc;
    6350 }
    6351 
    6352 
    6353 /**
    6354  * Reports an error from a DBGF call.
    6355  *
    6356  * @returns VBox status code appropriate to return from a command.
    6357  * @param   pCmdHlp     Pointer to command helpers.
    6358  * @param   rc          The VBox status code returned by a DBGF call.
    6359  * @param   pszFormat   Format string for additional messages. Can be NULL.
    6360  * @param   ...         Format arguments, optional.
    6361  */
    6362 static DECLCALLBACK(int) dbgcHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
    6363 {
    6364     va_list args;
    6365     va_start(args, pszFormat);
    6366     int rcRet = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, args);
    6367     va_end(args);
    6368     return rcRet;
    6369 }
    6370 
    6371 
    6372 /**
    6373  * Command helper for reading memory specified by a DBGC variable.
    6374  *
    6375  * @returns VBox status code appropriate to return from a command.
    6376  * @param   pCmdHlp     Pointer to the command callback structure.
    6377  * @param   pVM         VM handle if GC or physical HC address.
    6378  * @param   pvBuffer    Where to store the read data.
    6379  * @param   cbRead      Number of bytes to read.
    6380  * @param   pVarPointer DBGC variable specifying where to start reading.
    6381  * @param   pcbRead     Where to store the number of bytes actually read.
    6382  *                      This optional, but it's useful when read GC virtual memory where a
    6383  *                      page in the requested range might not be present.
    6384  *                      If not specified not-present failure or end of a HC physical page
    6385  *                      will cause failure.
    6386  */
    6387 static DECLCALLBACK(int) dbgcHlpMemRead(PDBGCCMDHLP pCmdHlp, PVM pVM, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
    6388 {
    6389     PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    6390 
    6391     /*
    6392      * Dummy check.
    6393      */
    6394     if (cbRead == 0)
    6395     {
    6396         if (*pcbRead)
    6397             *pcbRead = 0;
    6398         return VINF_SUCCESS;
    6399     }
    6400 
    6401     /*
    6402      * Convert Far addresses getting size and the correct base address.
    6403      * Getting and checking the size is what makes this messy and slow.
    6404      */
    6405     DBGCVAR Var = *pVarPointer;
    6406     switch (pVarPointer->enmType)
    6407     {
    6408         case DBGCVAR_TYPE_GC_FAR:
    6409         {
    6410             /* Use DBGFR3AddrFromSelOff for the conversion. */
    6411             Assert(pDbgc->pVM);
    6412             DBGFADDRESS Address;
    6413             int rc = DBGFR3AddrFromSelOff(pDbgc->pVM, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
    6414             if (VBOX_FAILURE(rc))
    6415                 return rc;
    6416 
    6417             /* don't bother with flat selectors (for now). */
    6418             if (!DBGFADDRESS_IS_FLAT(&Address))
    6419             {
    6420                 SELMSELINFO SelInfo;
    6421                 rc = SELMR3GetSelectorInfo(pDbgc->pVM, Address.Sel, &SelInfo);
    6422                 if (VBOX_SUCCESS(rc))
    6423                 {
    6424                     RTGCUINTPTR cb; /* -1 byte */
    6425                     if (SELMSelInfoIsExpandDown(&SelInfo))
    6426                     {
    6427                         if (    !SelInfo.Raw.Gen.u1Granularity
    6428                             &&  Address.off > UINT16_C(0xffff))
    6429                             return VERR_OUT_OF_SELECTOR_BOUNDS;
    6430                         if (Address.off <= SelInfo.cbLimit)
    6431                             return VERR_OUT_OF_SELECTOR_BOUNDS;
    6432                         cb = (SelInfo.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
    6433                     }
    6434                     else
    6435                     {
    6436                         if (Address.off > SelInfo.cbLimit)
    6437                             return VERR_OUT_OF_SELECTOR_BOUNDS;
    6438                         cb = SelInfo.cbLimit - Address.off;
    6439                     }
    6440                     if (cbRead - 1 > cb)
    6441                     {
    6442                         if (!pcbRead)
    6443                             return VERR_OUT_OF_SELECTOR_BOUNDS;
    6444                         cbRead = cb + 1;
    6445                     }
    6446                 }
    6447 
    6448                 Var.enmType = DBGCVAR_TYPE_GC_FLAT;
    6449                 Var.u.GCFlat = Address.FlatPtr;
    6450             }
    6451             break;
    6452         }
    6453 
    6454         case DBGCVAR_TYPE_GC_FLAT:
    6455         case DBGCVAR_TYPE_GC_PHYS:
    6456         case DBGCVAR_TYPE_HC_FLAT:
    6457         case DBGCVAR_TYPE_HC_PHYS:
    6458             break;
    6459 
    6460         case DBGCVAR_TYPE_HC_FAR: /* not supported yet! */
    6461         default:
    6462             return VERR_NOT_IMPLEMENTED;
    6463     }
    6464 
    6465 
    6466 
    6467     /*
    6468      * Copy page by page.
    6469      */
    6470     size_t cbLeft = cbRead;
    6471     for (;;)
    6472     {
    6473         /*
    6474          * Calc read size.
    6475          */
    6476         size_t cb = RT_MIN(PAGE_SIZE, cbLeft);
    6477         switch (pVarPointer->enmType)
    6478         {
    6479             case DBGCVAR_TYPE_GC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCFlat & PAGE_OFFSET_MASK)); break;
    6480             case DBGCVAR_TYPE_GC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCPhys & PAGE_OFFSET_MASK)); break;
    6481             case DBGCVAR_TYPE_HC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - ((uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK)); break;
    6482             case DBGCVAR_TYPE_HC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - ((size_t)Var.u.HCPhys & PAGE_OFFSET_MASK)); break; /* size_t: MSC has braindead loss of data warnings! */
    6483             default: break;
    6484         }
    6485 
    6486         /*
    6487          * Perform read.
    6488          */
    6489         int rc;
    6490         switch (Var.enmType)
    6491         {
    6492             case DBGCVAR_TYPE_GC_FLAT:
    6493                 rc = MMR3ReadGCVirt(pVM, pvBuffer, Var.u.GCFlat, cb);
    6494                 break;
    6495             case DBGCVAR_TYPE_GC_PHYS:
    6496                 rc = PGMPhysReadGCPhys(pVM, pvBuffer, Var.u.GCPhys, cb);
    6497                 break;
    6498 
    6499             case DBGCVAR_TYPE_HC_PHYS:
    6500             case DBGCVAR_TYPE_HC_FLAT:
    6501             case DBGCVAR_TYPE_HC_FAR:
    6502             {
    6503                 DBGCVAR Var2;
    6504                 rc = dbgcOpAddrFlat(pDbgc, &Var, &Var2);
    6505                 if (VBOX_SUCCESS(rc))
    6506                 {
    6507                     /** @todo protect this!!! */
    6508                     memcpy(pvBuffer, Var2.u.pvHCFlat, cb);
    6509                     rc = 0;
    6510                 }
    6511                 else
    6512                     rc = VERR_INVALID_POINTER;
    6513                 break;
    6514             }
    6515 
    6516             default:
    6517                 rc = VERR_PARSE_INCORRECT_ARG_TYPE;
    6518         }
    6519 
    6520         /*
    6521          * Check for failure.
    6522          */
    6523         if (VBOX_FAILURE(rc))
    6524         {
    6525             if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
    6526                 return VINF_SUCCESS;
    6527             return rc;
    6528         }
    6529 
    6530         /*
    6531          * Next.
    6532          */
    6533         cbLeft -= cb;
    6534         if (!cbLeft)
    6535             break;
    6536         pvBuffer = (char *)pvBuffer + cb;
    6537         rc = pCmdHlp->pfnEval(pCmdHlp, &Var, "%DV + %d", &Var, cb);
    6538         if (VBOX_FAILURE(rc))
    6539         {
    6540             if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
    6541                 return VINF_SUCCESS;
    6542             return rc;
    6543         }
    6544     }
    6545 
    6546     /*
    6547      * Done
    6548      */
    6549     if (pcbRead)
    6550         *pcbRead = cbRead;
    6551     return 0;
    6552 }
    6553 
    6554 /**
    6555  * Command helper for writing memory specified by a DBGC variable.
    6556  *
    6557  * @returns VBox status code appropriate to return from a command.
    6558  * @param   pCmdHlp     Pointer to the command callback structure.
    6559  * @param   pVM         VM handle if GC or physical HC address.
    6560  * @param   pvBuffer    What to write.
    6561  * @param   cbWrite     Number of bytes to write.
    6562  * @param   pVarPointer DBGC variable specifying where to start reading.
    6563  * @param   pcbWritten  Where to store the number of bytes written.
    6564  *                      This is optional. If NULL be aware that some of the buffer
    6565  *                      might have been written to the specified address.
    6566  */
    6567 static DECLCALLBACK(int) dbgcHlpMemWrite(PDBGCCMDHLP pCmdHlp, PVM pVM, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten)
    6568 {
    6569     NOREF(pCmdHlp); NOREF(pVM); NOREF(pvBuffer); NOREF(cbWrite); NOREF(pVarPointer); NOREF(pcbWritten);
    6570     return VERR_NOT_IMPLEMENTED;
    6571 }
    6572 
    6573 
    6574 /**
    6575  * Evaluates an expression.
    6576  * (Hopefully the parser and functions are fully reentrant.)
    6577  *
    6578  * @returns VBox status code appropriate to return from a command.
    6579  * @param   pCmdHlp     Pointer to the command callback structure.
    6580  * @param   pResult     Where to store the result.
    6581  * @param   pszExpr     The expression. Format string with the format DBGC extensions.
    6582  * @param   ...         Format arguments.
    6583  */
    6584 static DECLCALLBACK(int) dbgcHlpEval(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, ...)
    6585 {
    6586     PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    6587 
    6588     /*
    6589      * Format the expression.
    6590      */
    6591     char szExprFormatted[2048];
    6592     va_list args;
    6593     va_start(args, pszExpr);
    6594     size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, szExprFormatted, sizeof(szExprFormatted), pszExpr, args);
    6595     va_end(args);
    6596     /* ignore overflows. */
    6597 
    6598     return dbgcEvalSub(pDbgc, &szExprFormatted[0], cb, pResult);
    6599 }
    6600 
    6601 
    6602 /**
    6603  * Executes one command expression.
    6604  * (Hopefully the parser and functions are fully reentrant.)
    6605  *
    6606  * @returns VBox status code appropriate to return from a command.
    6607  * @param   pCmdHlp     Pointer to the command callback structure.
    6608  * @param   pszExpr     The expression. Format string with the format DBGC extensions.
    6609  * @param   ...         Format arguments.
    6610  */
    6611 static DECLCALLBACK(int) dbgcHlpExec(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)
    6612 {
    6613     PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    6614     /* Save the scratch state. */
    6615     char       *pszScratch  = pDbgc->pszScratch;
    6616     unsigned    iArg        = pDbgc->iArg;
    6617 
    6618     /*
    6619      * Format the expression.
    6620      */
    6621     va_list args;
    6622     va_start(args, pszExpr);
    6623     size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
    6624     size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, pDbgc->pszScratch, cbScratch, pszExpr, args);
    6625     va_end(args);
    6626     if (cb >= cbScratch)
    6627         return VERR_BUFFER_OVERFLOW;
    6628 
    6629     /*
    6630      * Execute the command.
    6631      * We save and restore the arg index and scratch buffer pointer.
    6632      */
    6633     pDbgc->pszScratch = pDbgc->pszScratch + cb + 1;
    6634     int rc = dbgcProcessCommand(pDbgc, pszScratch, cb);
    6635 
    6636     /* Restore the scratch state. */
    6637     pDbgc->iArg         = iArg;
    6638     pDbgc->pszScratch   = pszScratch;
    6639 
    6640     return rc;
    6641 }
    6642 
    6643 
    6644 /**
    6645  * Converts a DBGC variable to a DBGF address structure.
    6646  *
    6647  * @returns VBox status code.
    6648  * @param   pCmdHlp     Pointer to the command callback structure.
    6649  * @param   pVar        The variable to convert.
    6650  * @param   pAddress    The target address.
    6651  */
    6652 static DECLCALLBACK(int) dbgcHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
    6653 {
    6654     PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    6655     return dbgcVarToDbgfAddr(pDbgc, pVar, pAddress);
    6656 }
    6657 
    6658 
    6659 /**
    6660  * Converts a DBGC variable to a boolean.
    6661  *
    6662  * @returns VBox status code.
    6663  * @param   pCmdHlp     Pointer to the command callback structure.
    6664  * @param   pVar        The variable to convert.
    6665  * @param   pf          Where to store the boolean.
    6666  */
    6667 static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
    6668 {
    6669     PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    6670     NOREF(pDbgc);
    6671 
    6672     switch (pVar->enmType)
    6673     {
    6674         case DBGCVAR_TYPE_STRING:
    6675             /** @todo add strcasecmp / stricmp wrappers to iprt/string.h. */
    6676             if (    !strcmp(pVar->u.pszString, "true")
    6677                 ||  !strcmp(pVar->u.pszString, "True")
    6678                 ||  !strcmp(pVar->u.pszString, "TRUE")
    6679                 ||  !strcmp(pVar->u.pszString, "on")
    6680                 ||  !strcmp(pVar->u.pszString, "On")
    6681                 ||  !strcmp(pVar->u.pszString, "oN")
    6682                 ||  !strcmp(pVar->u.pszString, "ON")
    6683                 ||  !strcmp(pVar->u.pszString, "enabled")
    6684                 ||  !strcmp(pVar->u.pszString, "Enabled")
    6685                 ||  !strcmp(pVar->u.pszString, "DISABLED"))
    6686             {
    6687                 *pf = true;
    6688                 return VINF_SUCCESS;
    6689             }
    6690             if (    !strcmp(pVar->u.pszString, "false")
    6691                 ||  !strcmp(pVar->u.pszString, "False")
    6692                 ||  !strcmp(pVar->u.pszString, "FALSE")
    6693                 ||  !strcmp(pVar->u.pszString, "off")
    6694                 ||  !strcmp(pVar->u.pszString, "Off")
    6695                 ||  !strcmp(pVar->u.pszString, "OFF")
    6696                 ||  !strcmp(pVar->u.pszString, "disabled")
    6697                 ||  !strcmp(pVar->u.pszString, "Disabled")
    6698                 ||  !strcmp(pVar->u.pszString, "DISABLED"))
    6699             {
    6700                 *pf = false;
    6701                 return VINF_SUCCESS;
    6702             }
    6703             return VERR_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
    6704 
    6705         case DBGCVAR_TYPE_GC_FLAT:
    6706         case DBGCVAR_TYPE_GC_PHYS:
    6707         case DBGCVAR_TYPE_HC_FLAT:
    6708         case DBGCVAR_TYPE_HC_PHYS:
    6709         case DBGCVAR_TYPE_NUMBER:
    6710             *pf = pVar->u.u64Number != 0;
    6711             return VINF_SUCCESS;
    6712 
    6713         case DBGCVAR_TYPE_HC_FAR:
    6714         case DBGCVAR_TYPE_GC_FAR:
    6715         case DBGCVAR_TYPE_SYMBOL:
    6716         default:
    6717             return VERR_PARSE_INCORRECT_ARG_TYPE;
    6718     }
    6719 }
    6720 
    6721 
    6722 
    6723 
    6724 
    6725 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    6726 //
    6727 //
    6728 //      V a r i a b l e   M a n i p u l a t i o n
    6729 //
    6730 //
    6731 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    6732 
    6733 
    6734 
    6735 /** @todo move me!*/
    6736 static void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat)
    6737 {
    6738     if (pVar)
    6739     {
    6740         pVar->enmType  = DBGCVAR_TYPE_GC_FLAT;
    6741         pVar->u.GCFlat = GCFlat;
    6742         pVar->enmRangeType = DBGCVAR_RANGE_NONE;
    6743         pVar->u64Range  = 0;
    6744     }
    6745 }
    6746 
    6747 
    6748 /** @todo move me!*/
    6749 static void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb)
    6750 {
    6751     if (pVar)
    6752     {
    6753         pVar->enmType  = DBGCVAR_TYPE_GC_FLAT;
    6754         pVar->u.GCFlat = GCFlat;
    6755         pVar->enmRangeType = DBGCVAR_RANGE_BYTES;
    6756         pVar->u64Range  = cb;
    6757     }
    6758 }
    6759 
    6760 
    6761 /** @todo move me!*/
    6762 static void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2)
    6763 {
    6764     if (pVar)
    6765     {
    6766         if (pVar2)
    6767             *pVar = *pVar2;
    6768         else
    6769         {
    6770             pVar->enmType = DBGCVAR_TYPE_UNKNOWN;
    6771             memset(&pVar->u, 0, sizeof(pVar->u));
    6772             pVar->enmRangeType = DBGCVAR_RANGE_NONE;
    6773             pVar->u64Range  = 0;
    6774         }
    6775     }
    6776 }
    6777 
    6778 
    6779 /** @todo move me!*/
    6780 static void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb)
    6781 {
    6782     if (pVar)
    6783     {
    6784         pVar->enmRangeType = DBGCVAR_RANGE_BYTES;
    6785         pVar->u64Range  = cb;
    6786     }
    6787 }
    6788 
    6789 
    6790 /** @todo move me!*/
    6791 static void dbgcVarSetNoRange(PDBGCVAR pVar)
    6792 {
    6793     if (pVar)
    6794     {
    6795         pVar->enmRangeType = DBGCVAR_RANGE_NONE;
    6796         pVar->u64Range  = 0;
    6797     }
    6798 }
    6799 
    6800 
    6801 /**
    6802  * Converts a DBGC variable to a DBGF address.
    6803  *
    6804  * @returns VBox status code.
    6805  * @param   pDbgc       The DBGC instance.
    6806  * @param   pVar        The variable.
    6807  * @param   pAddress    Where to store the address.
    6808  */
    6809 static int dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
    6810 {
    6811     AssertReturn(pVar, VERR_INVALID_PARAMETER);
    6812     switch (pVar->enmType)
    6813     {
    6814         case DBGCVAR_TYPE_GC_FLAT:
    6815             DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, pVar->u.GCFlat);
    6816             return VINF_SUCCESS;
    6817 
    6818         case DBGCVAR_TYPE_NUMBER:
    6819             DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, (RTGCUINTPTR)pVar->u.u64Number);
    6820             return VINF_SUCCESS;
    6821 
    6822         case DBGCVAR_TYPE_GC_FAR:
    6823             return DBGFR3AddrFromSelOff(pDbgc->pVM, pAddress, pVar->u.GCFar.sel, pVar->u.GCFar.sel);
    6824 
    6825         case DBGCVAR_TYPE_STRING:
    6826         case DBGCVAR_TYPE_SYMBOL:
    6827         {
    6828             DBGCVAR Var;
    6829             int rc = pDbgc->CmdHlp.pfnEval(&pDbgc->CmdHlp, &Var, "%%(%DV)", pVar);
    6830             if (VBOX_FAILURE(rc))
    6831                 return rc;
    6832             return dbgcVarToDbgfAddr(pDbgc, &Var, pAddress);
    6833         }
    6834 
    6835         case DBGCVAR_TYPE_GC_PHYS:
    6836         case DBGCVAR_TYPE_HC_FLAT:
    6837         case DBGCVAR_TYPE_HC_FAR:
    6838         case DBGCVAR_TYPE_HC_PHYS:
    6839         default:
    6840             return VERR_PARSE_CONVERSION_FAILED;
    6841     }
    6842 }
    6843 
    6844 
    6845 
    6846 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    6847 //
    6848 //
    6849 //      B r e a k p o i n t   M a n a g e m e n t
    6850 //
    6851 //
    6852 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    6853 
    6854 
    6855 /**
    6856  * Adds a breakpoint to the DBGC breakpoint list.
    6857  */
    6858 static int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
    6859 {
    6860     /*
    6861      * Check if it already exists.
    6862      */
    6863     PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
    6864     if (pBp)
    6865         return VERR_DBGC_BP_EXISTS;
    6866 
    6867     /*
    6868      * Add the breakpoint.
    6869      */
    6870     if (pszCmd)
    6871         pszCmd = RTStrStripL(pszCmd);
    6872     size_t cchCmd = pszCmd ? strlen(pszCmd) : 0;
    6873     pBp = (PDBGCBP)RTMemAlloc(RT_OFFSETOF(DBGCBP, szCmd[cchCmd + 1]));
    6874     if (!pBp)
    6875         return VERR_NO_MEMORY;
    6876     if (cchCmd)
    6877         memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
    6878     else
    6879         pBp->szCmd[0] = '\0';
    6880     pBp->cchCmd = cchCmd;
    6881     pBp->iBp    = iBp;
    6882     pBp->pNext  = pDbgc->pFirstBp;
    6883     pDbgc->pFirstBp = pBp;
    6884 
    6885     return VINF_SUCCESS;
    6886 }
    6887 
    6888 /**
    6889  * Updates the a breakpoint.
    6890  *
    6891  * @returns VBox status code.
    6892  * @param   pDbgc       The DBGC instance.
    6893  * @param   iBp         The breakpoint to update.
    6894  * @param   pszCmd      The new command.
    6895  */
    6896 static int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
    6897 {
    6898     /*
    6899      * Find the breakpoint.
    6900      */
    6901     PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
    6902     if (!pBp)
    6903         return VERR_DBGC_BP_NOT_FOUND;
    6904 
    6905     /*
    6906      * Do we need to reallocate?
    6907      */
    6908     if (pszCmd)
    6909         pszCmd = RTStrStripL(pszCmd);
    6910     if (!pszCmd || !*pszCmd)
    6911         pBp->szCmd[0] = '\0';
    6912     else
    6913     {
    6914         size_t cchCmd = strlen(pszCmd);
    6915         if (strlen(pBp->szCmd) >= cchCmd)
    6916         {
    6917             memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
    6918             pBp->cchCmd = cchCmd;
    6919         }
    6920         else
    6921         {
    6922             /*
    6923              * Yes, let's do it the simple way...
    6924              */
    6925             int rc = dbgcBpDelete(pDbgc, iBp);
    6926             AssertRC(rc);
    6927             return dbgcBpAdd(pDbgc, iBp, pszCmd);
    6928         }
    6929     }
    6930     return VINF_SUCCESS;
    6931 }
    6932 
    6933 
    6934 /**
    6935  * Deletes a breakpoint.
    6936  *
    6937  * @returns VBox status code.
    6938  * @param   pDbgc       The DBGC instance.
    6939  * @param   iBp         The breakpoint to delete.
    6940  */
    6941 static int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp)
    6942 {
    6943     /*
    6944      * Search thru the list, when found unlink and free it.
    6945      */
    6946     PDBGCBP pBpPrev = NULL;
    6947     PDBGCBP pBp = pDbgc->pFirstBp;
    6948     for (; pBp; pBp = pBp->pNext)
    6949     {
    6950         if (pBp->iBp == iBp)
    6951         {
    6952             if (pBpPrev)
    6953                 pBpPrev->pNext = pBp->pNext;
    6954             else
    6955                 pDbgc->pFirstBp = pBp->pNext;
    6956             RTMemFree(pBp);
    6957             return VINF_SUCCESS;
    6958         }
    6959         pBpPrev = pBp;
    6960     }
    6961 
    6962     return VERR_DBGC_BP_NOT_FOUND;
    6963 }
    6964 
    6965 
    6966 /**
    6967  * Get a breakpoint.
    6968  *
    6969  * @returns Pointer to the breakpoint.
    6970  * @returns NULL if the breakpoint wasn't found.
    6971  * @param   pDbgc       The DBGC instance.
    6972  * @param   iBp         The breakpoint to get.
    6973  */
    6974 static PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp)
    6975 {
    6976     /*
    6977      * Enumerate the list.
    6978      */
    6979     PDBGCBP pBp = pDbgc->pFirstBp;
    6980     for (; pBp; pBp = pBp->pNext)
    6981         if (pBp->iBp == iBp)
    6982             return pBp;
    6983     return NULL;
    6984 }
    6985 
    6986 
    6987 /**
    6988  * Executes the command of a breakpoint.
    6989  *
    6990  * @returns VINF_DBGC_BP_NO_COMMAND if there is no command associated with the breakpoint.
    6991  * @returns VERR_DBGC_BP_NOT_FOUND if the breakpoint wasn't found.
    6992  * @returns VERR_BUFFER_OVERFLOW if the is not enough space in the scratch buffer for the command.
    6993  * @returns VBox status code from dbgcProcessCommand() other wise.
    6994  * @param   pDbgc       The DBGC instance.
    6995  * @param   iBp         The breakpoint to execute.
    6996  */
    6997 static int dbgcBpExec(PDBGC pDbgc, RTUINT iBp)
    6998 {
    6999     /*
    7000      * Find the breakpoint.
    7001      */
    7002     PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
    7003     if (!pBp)
    7004         return VERR_DBGC_BP_NOT_FOUND;
    7005 
    7006     /*
    7007      * Anything to do?
    7008      */
    7009     if (!pBp->cchCmd)
    7010         return VINF_DBGC_BP_NO_COMMAND;
    7011 
    7012     /*
    7013      * Execute the command.
    7014      * This means copying it to the scratch buffer and process it as if it
    7015      * were user input. We must save and restore the state of the scratch buffer.
    7016      */
    7017     /* Save the scratch state. */
    7018     char       *pszScratch  = pDbgc->pszScratch;
    7019     unsigned    iArg        = pDbgc->iArg;
    7020 
    7021     /* Copy the command to the scratch buffer. */
    7022     size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
    7023     if (pBp->cchCmd >= cbScratch)
    7024         return VERR_BUFFER_OVERFLOW;
    7025     memcpy(pDbgc->pszScratch, pBp->szCmd, pBp->cchCmd + 1);
    7026 
    7027     /* Execute the command. */
    7028     pDbgc->pszScratch = pDbgc->pszScratch + pBp->cchCmd + 1;
    7029     int rc = dbgcProcessCommand(pDbgc, pszScratch, pBp->cchCmd);
    7030 
    7031     /* Restore the scratch state. */
    7032     pDbgc->iArg         = iArg;
    7033     pDbgc->pszScratch   = pszScratch;
    7034 
    7035     return rc;
    7036 }
    7037 
    7038 
    7039 
    7040 
    7041 
    7042 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    7043 //
    7044 //
    7045 //      I n p u t ,   p a r s i n g   a n d   l o g g i n g
    7046 //
    7047 //
    7048 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    7049 
    7050 
    7051 
    7052 /**
    7053  * Prints any log lines from the log buffer.
    7054  *
    7055  * The caller must not call function this unless pDbgc->fLog is set.
    7056  *
    7057  * @returns VBox status. (output related)
    7058  * @param   pDbgc   Debugger console instance data.
    7059  */
    7060 static int dbgcProcessLog(PDBGC pDbgc)
    7061 {
    7062     /** @todo */
    7063     NOREF(pDbgc);
    7064     return 0;
    7065 }
    7066 
    7067 
    7068 
    7069 /**
    7070  * Handle input buffer overflow.
    7071  *
    7072  * Will read any available input looking for a '\n' to reset the buffer on.
    7073  *
    7074  * @returns VBox status.
    7075  * @param   pDbgc   Debugger console instance data.
    7076  */
    7077 static int dbgcInputOverflow(PDBGC pDbgc)
    7078 {
    7079     /*
    7080      * Assert overflow status and reset the input buffer.
    7081      */
    7082     if (!pDbgc->fInputOverflow)
    7083     {
    7084         pDbgc->fInputOverflow = true;
    7085         pDbgc->iRead = pDbgc->iWrite = 0;
    7086         pDbgc->cInputLines = 0;
    7087         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Input overflow!!\n");
    7088     }
    7089 
    7090     /*
    7091      * Eat input till no more or there is a '\n'.
    7092      * When finding a '\n' we'll continue normal processing.
    7093      */
    7094     while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0))
    7095     {
    7096         size_t cbRead;
    7097         int rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &pDbgc->achInput[0], sizeof(pDbgc->achInput) - 1, &cbRead);
    7098         if (VBOX_FAILURE(rc))
    7099             return rc;
    7100         char *psz = (char *)memchr(&pDbgc->achInput[0], '\n', cbRead);
    7101         if (psz)
    7102         {
    7103             pDbgc->fInputOverflow = false;
    7104             pDbgc->iRead = psz - &pDbgc->achInput[0] + 1;
    7105             pDbgc->iWrite = (unsigned)cbRead;
    7106             pDbgc->cInputLines = 0;
    7107             break;
    7108         }
    7109     }
    7110 
    7111     return 0;
    7112 }
    7113 
    7114 
    7115 
    7116 /**
    7117  * Read input and do some preprocessing.
    7118  *
    7119  * @returns VBox status.
    7120  *          In addition to the iWrite and achInput, cInputLines is maintained.
    7121  *          In case of an input overflow the fInputOverflow flag will be set.
    7122  * @param   pDbgc   Debugger console instance data.
    7123  */
    7124 static int dbgcInputRead(PDBGC pDbgc)
    7125 {
    7126     /*
    7127      * We have ready input.
    7128      * Read it till we don't have any or we have a full input buffer.
    7129      */
    7130     int     rc = 0;
    7131     do
    7132     {
    7133         /*
    7134          * More available buffer space?
    7135          */
    7136         size_t cbLeft;
    7137         if (pDbgc->iWrite > pDbgc->iRead)
    7138             cbLeft = sizeof(pDbgc->achInput) - pDbgc->iWrite - (pDbgc->iRead == 0);
    7139         else
    7140             cbLeft = pDbgc->iRead - pDbgc->iWrite - 1;
    7141         if (!cbLeft)
    7142         {
    7143             /* overflow? */
    7144             if (!pDbgc->cInputLines)
    7145                 rc = dbgcInputOverflow(pDbgc);
    7146             break;
    7147         }
    7148 
    7149         /*
    7150          * Read one char and interpret it.
    7151          */
    7152         char    achRead[128];
    7153         size_t  cbRead;
    7154         rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &achRead[0], RT_MIN(cbLeft, sizeof(achRead)), &cbRead);
    7155         if (VBOX_FAILURE(rc))
    7156             return rc;
    7157         char *psz = &achRead[0];
    7158         while (cbRead-- > 0)
    7159         {
    7160             char ch = *psz++;
    7161             switch (ch)
    7162             {
    7163                 /*
    7164                  * Ignore.
    7165                  */
    7166                 case '\0':
    7167                 case '\r':
    7168                 case '\a':
    7169                     break;
    7170 
    7171                 /*
    7172                  * Backspace.
    7173                  */
    7174                 case '\b':
    7175                     Log2(("DBGC: backspace\n"));
    7176                     if (pDbgc->iRead != pDbgc->iWrite)
    7177                     {
    7178                         unsigned iWriteUndo = pDbgc->iWrite;
    7179                         if (pDbgc->iWrite)
    7180                             pDbgc->iWrite--;
    7181                         else
    7182                             pDbgc->iWrite = sizeof(pDbgc->achInput) - 1;
    7183 
    7184                         if (pDbgc->achInput[pDbgc->iWrite] == '\n')
    7185                             pDbgc->iWrite = iWriteUndo;
    7186                     }
    7187                     break;
    7188 
    7189                 /*
    7190                  * Add char to buffer.
    7191                  */
    7192                 case '\t':
    7193                 case '\n':
    7194                 case ';':
    7195                     switch (ch)
    7196                     {
    7197                         case '\t': ch = ' '; break;
    7198                         case '\n': pDbgc->cInputLines++; break;
    7199                     }
    7200                 default:
    7201                     Log2(("DBGC: ch=%02x\n", (unsigned char)ch));
    7202                     pDbgc->achInput[pDbgc->iWrite] = ch;
    7203                     if (++pDbgc->iWrite >= sizeof(pDbgc->achInput))
    7204                         pDbgc->iWrite = 0;
    7205                     break;
    7206             }
    7207         }
    7208 
    7209         /* Terminate it to make it easier to read in the debugger. */
    7210         pDbgc->achInput[pDbgc->iWrite] = '\0';
    7211     } while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0));
    7212 
    7213     return rc;
    7214 }
    7215 
    7216 
    7217 /**
    7218  * Finds a builtin symbol.
    7219  * @returns Pointer to symbol descriptor on success.
    7220  * @returns NULL on failure.
    7221  * @param   pDbgc       The debug console instance.
    7222  * @param   pszSymbol   The symbol name.
    7223  */
    7224 static PCDBGCSYM dbgcLookupRegisterSymbol(PDBGC pDbgc, const char *pszSymbol)
    7225 {
    7226     for (unsigned iSym = 0; iSym < ELEMENTS(g_aSyms); iSym++)
    7227         if (!strcmp(pszSymbol, g_aSyms[iSym].pszName))
    7228             return &g_aSyms[iSym];
    7229 
    7230     /** @todo externally registered symbols. */
    7231     NOREF(pDbgc);
    7232     return NULL;
    7233 }
    7234 
    7235 
    7236 /**
    7237  * Resolves a symbol (or tries to do so at least).
    7238  *
    7239  * @returns 0 on success.
    7240  * @returns VBox status on failure.
    7241  * @param   pDbgc       The debug console instance.
    7242  * @param   pszSymbol   The symbol name.
    7243  * @param   enmType     The result type.
    7244  * @param   pResult     Where to store the result.
    7245  */
    7246 static int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGCVAR pResult)
    7247 {
    7248     /*
    7249      * Builtin?
    7250      */
    7251     PCDBGCSYM   pSymDesc = dbgcLookupRegisterSymbol(pDbgc, pszSymbol);
    7252     if (pSymDesc)
    7253     {
    7254         if (!pSymDesc->pfnGet)
    7255             return VERR_PARSE_WRITEONLY_SYMBOL;
    7256         return pSymDesc->pfnGet(pSymDesc, &pDbgc->CmdHlp, enmType, pResult);
    7257     }
    7258 
    7259 
    7260     /*
    7261      * Ask PDM.
    7262      */
    7263     /** @todo resolve symbols using PDM. */
    7264 
    7265 
    7266     /*
    7267      * Ask the debug info manager.
    7268      */
    7269     DBGFSYMBOL Symbol;
    7270     int rc = DBGFR3SymbolByName(pDbgc->pVM, pszSymbol, &Symbol);
    7271     if (VBOX_SUCCESS(rc))
    7272     {
    7273         /*
    7274          * Default return is a flat gc address.
    7275          */
    7276         memset(pResult, 0,  sizeof(*pResult));
    7277         pResult->enmRangeType = Symbol.cb ? DBGCVAR_RANGE_BYTES : DBGCVAR_RANGE_NONE;
    7278         pResult->u64Range     = Symbol.cb;
    7279         pResult->enmType      = DBGCVAR_TYPE_GC_FLAT;
    7280         pResult->u.GCFlat     = Symbol.Value;
    7281         DBGCVAR VarTmp;
    7282         switch (enmType)
    7283         {
    7284             /* nothing to do. */
    7285             case DBGCVAR_TYPE_GC_FLAT:
    7286             case DBGCVAR_TYPE_GC_FAR:
    7287             case DBGCVAR_TYPE_ANY:
    7288                 return VINF_SUCCESS;
    7289 
    7290             /* simply make it numeric. */
    7291             case DBGCVAR_TYPE_NUMBER:
    7292                 pResult->enmType = DBGCVAR_TYPE_NUMBER;
    7293                 pResult->u.u64Number = Symbol.Value;
    7294                 return VINF_SUCCESS;
    7295 
    7296             /* cast it. */
    7297 
    7298             case DBGCVAR_TYPE_GC_PHYS:
    7299                 VarTmp = *pResult;
    7300                 return dbgcOpAddrPhys(pDbgc, &VarTmp, pResult);
    7301 
    7302             case DBGCVAR_TYPE_HC_FAR:
    7303             case DBGCVAR_TYPE_HC_FLAT:
    7304                 VarTmp = *pResult;
    7305                 return dbgcOpAddrHost(pDbgc, &VarTmp, pResult);
    7306 
    7307             case DBGCVAR_TYPE_HC_PHYS:
    7308                 VarTmp = *pResult;
    7309                 return dbgcOpAddrHostPhys(pDbgc, &VarTmp, pResult);
    7310 
    7311             default:
    7312                 AssertMsgFailed(("Internal error enmType=%d\n", enmType));
    7313                 return VERR_INVALID_PARAMETER;
    7314         }
    7315     }
    7316 
    7317     return VERR_PARSE_NOT_IMPLEMENTED;
    7318 }
    7319 
    7320 
    7321 
    7322 /**
    7323  * Finds a routine.
    7324  *
    7325  * @returns Pointer to the command descriptor.
    7326  *          If the request was for an external command, the caller is responsible for
    7327  *          unlocking the external command list.
    7328  * @returns NULL if not found.
    7329  * @param   pDbgc       The debug console instance.
    7330  * @param   pachName    Pointer to the routine string (not terminated).
    7331  * @param   cchName     Length of the routine name.
    7332  * @param   fExternal   Whether or not the routine is external.
    7333  */
    7334 static PCDBGCCMD dbgcRoutineLookup(PDBGC pDbgc, const char *pachName, size_t cchName, bool fExternal)
    7335 {
    7336     if (!fExternal)
    7337     {
    7338         /* emulation first, so commands can be overloaded (info ++). */
    7339         PCDBGCCMD pCmd = pDbgc->paEmulationCmds;
    7340         unsigned cLeft = pDbgc->cEmulationCmds;
    7341         while (cLeft-- > 0)
    7342         {
    7343             if (    !strncmp(pachName, pCmd->pszCmd, cchName)
    7344                 &&  !pCmd->pszCmd[cchName])
    7345                 return pCmd;
    7346             pCmd++;
    7347         }
    7348 
    7349         for (unsigned iCmd = 0; iCmd < ELEMENTS(g_aCmds); iCmd++)
    7350         {
    7351             if (    !strncmp(pachName, g_aCmds[iCmd].pszCmd, cchName)
    7352                 &&  !g_aCmds[iCmd].pszCmd[cchName])
    7353                 return &g_aCmds[iCmd];
    7354         }
    7355     }
    7356     else
    7357     {
    7358         DBGCEXTCMDS_LOCK_RD();
    7359         for (PDBGCEXTCMDS pExtCmds = g_pExtCmdsHead; pExtCmds; pExtCmds = pExtCmds->pNext)
    7360         {
    7361             for (unsigned iCmd = 0; iCmd < pExtCmds->cCmds; iCmd++)
    7362             {
    7363                 if (    !strncmp(pachName, pExtCmds->paCmds[iCmd].pszCmd, cchName)
    7364                     &&  !pExtCmds->paCmds[iCmd].pszCmd[cchName])
    7365                     return &pExtCmds->paCmds[iCmd];
    7366             }
    7367         }
    7368         DBGCEXTCMDS_UNLOCK_RD();
    7369     }
    7370 
    7371     NOREF(pDbgc);
    7372     return NULL;
    7373 }
    7374 
    7375 
    7376 /**
    7377  * Searches for an operator descriptor which matches the start of
    7378  * the expression given us.
    7379  *
    7380  * @returns Pointer to the operator on success.
    7381  * @param   pDbgc           The debug console instance.
    7382  * @param   pszExpr         Pointer to the expression string which might start with an operator.
    7383  * @param   fPreferBinary   Whether to favour binary or unary operators.
    7384  *                          Caller must assert that it's the disired type! Both types will still
    7385  *                          be returned, this is only for resolving duplicates.
    7386  * @param   chPrev          The previous char. Some operators requires a blank in front of it.
    7387  */
    7388 static PCDBGCOP dbgcOperatorLookup(PDBGC pDbgc, const char *pszExpr, bool fPreferBinary, char chPrev)
    7389 {
    7390     PCDBGCOP    pOp = NULL;
    7391     for (unsigned iOp = 0; iOp < ELEMENTS(g_aOps); iOp++)
    7392     {
    7393         if (     g_aOps[iOp].szName[0] == pszExpr[0]
    7394             &&  (!g_aOps[iOp].szName[1] || g_aOps[iOp].szName[1] == pszExpr[1])
    7395             &&  (!g_aOps[iOp].szName[2] || g_aOps[iOp].szName[2] == pszExpr[2]))
    7396         {
    7397             /*
    7398              * Check that we don't mistake it for some other operator which have more chars.
    7399              */
    7400             unsigned j;
    7401             for (j = iOp + 1; j < ELEMENTS(g_aOps); j++)
    7402                 if (    g_aOps[j].cchName > g_aOps[iOp].cchName
    7403                     &&  g_aOps[j].szName[0] == pszExpr[0]
    7404                     &&  (!g_aOps[j].szName[1] || g_aOps[j].szName[1] == pszExpr[1])
    7405                     &&  (!g_aOps[j].szName[2] || g_aOps[j].szName[2] == pszExpr[2]) )
    7406                     break;
    7407             if (j < ELEMENTS(g_aOps))
    7408                 continue;       /* we'll catch it later. (for theoretical +,++,+++ cases.) */
    7409             pOp = &g_aOps[iOp];
    7410 
    7411             /*
    7412              * Prefered type?
    7413              */
    7414             if (g_aOps[iOp].fBinary == fPreferBinary)
    7415                 break;
    7416         }
    7417     }
    7418 
    7419     if (pOp)
    7420         Log2(("dbgcOperatorLookup: pOp=%p %s\n", pOp, pOp->szName));
    7421     NOREF(pDbgc); NOREF(chPrev);
    7422     return pOp;
    7423 }
    7424 
    7425 
    7426 /**
    7427  * Initalizes g_bmOperatorChars.
    7428  */
    7429 static void dbgcInitOpCharBitMap(void)
    7430 {
    7431     memset(g_bmOperatorChars, 0, sizeof(g_bmOperatorChars));
    7432     for (unsigned iOp = 0; iOp < RT_ELEMENTS(g_aOps); iOp++)
    7433         ASMBitSet(&g_bmOperatorChars[0], (uint8_t)g_aOps[iOp].szName[0]);
    7434 }
    7435 
    7436 
    7437 /**
    7438  * Checks whether the character may be the start of an operator.
    7439  *
    7440  * @returns true/false.
    7441  * @param   ch      The character.
    7442  */
    7443 DECLINLINE(bool) dbgcIsOpChar(char ch)
    7444 {
    7445     return ASMBitTest(&g_bmOperatorChars[0], (uint8_t)ch);
    7446 }
    7447 
    7448 
    7449 static int dbgcEvalSubString(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pArg)
    7450 {
    7451     Log2(("dbgcEvalSubString: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
    7452 
    7453     /*
    7454      * Removing any quoting and escapings.
    7455      */
    7456     char ch = *pszExpr;
    7457     if (ch == '"' || ch == '\'' || ch == '`')
    7458     {
    7459         if (pszExpr[--cchExpr] != ch)
    7460             return VERR_PARSE_UNBALANCED_QUOTE;
    7461         cchExpr--;
    7462         pszExpr++;
    7463 
    7464         /** @todo string unescaping. */
    7465     }
    7466     pszExpr[cchExpr] = '\0';
    7467 
    7468     /*
    7469      * Make the argument.
    7470      */
    7471     pArg->pDesc         = NULL;
    7472     pArg->pNext         = NULL;
    7473     pArg->enmType       = DBGCVAR_TYPE_STRING;
    7474     pArg->u.pszString   = pszExpr;
    7475     pArg->enmRangeType  = DBGCVAR_RANGE_BYTES;
    7476     pArg->u64Range      = cchExpr;
    7477 
    7478     NOREF(pDbgc);
    7479     return 0;
    7480 }
    7481 
    7482 
    7483 static int dbgcEvalSubNum(char *pszExpr, unsigned uBase, PDBGCVAR pArg)
    7484 {
    7485     Log2(("dbgcEvalSubNum: uBase=%d pszExpr=%s\n", uBase, pszExpr));
    7486     /*
    7487      * Convert to number.
    7488      */
    7489     uint64_t    u64 = 0;
    7490     char        ch;
    7491     while ((ch = *pszExpr) != '\0')
    7492     {
    7493         uint64_t    u64Prev = u64;
    7494         unsigned    u = ch - '0';
    7495         if (u < 10 && u < uBase)
    7496             u64 = u64 * uBase + u;
    7497         else if (ch >= 'a' && (u = ch - ('a' - 10)) < uBase)
    7498             u64 = u64 * uBase + u;
    7499         else if (ch >= 'A' && (u = ch - ('A' - 10)) < uBase)
    7500             u64 = u64 * uBase + u;
    7501         else
    7502             return VERR_PARSE_INVALID_NUMBER;
    7503 
    7504         /* check for overflow - ARG!!! How to detect overflow correctly!?!?!? */
    7505         if (u64Prev != u64 / uBase)
    7506             return VERR_PARSE_NUMBER_TOO_BIG;
    7507 
    7508         /* next */
    7509         pszExpr++;
    7510     }
    7511 
    7512     /*
    7513      * Initialize the argument.
    7514      */
    7515     pArg->pDesc         = NULL;
    7516     pArg->pNext         = NULL;
    7517     pArg->enmType       = DBGCVAR_TYPE_NUMBER;
    7518     pArg->u.u64Number   = u64;
    7519     pArg->enmRangeType  = DBGCVAR_RANGE_NONE;
    7520     pArg->u64Range      = 0;
    7521 
    7522     return 0;
    7523 }
    7524 
    7525 
    7526 /**
    7527  * Match variable and variable descriptor, promoting the variable if necessary.
    7528  *
    7529  * @returns VBox status code.
    7530  * @param   pDbgc       Debug console instanace.
    7531  * @param   pVar        Variable.
    7532  * @param   pVarDesc    Variable descriptor.
    7533  */
    7534 static int dbgcEvalSubMatchVar(PDBGC pDbgc, PDBGCVAR pVar, PCDBGCVARDESC pVarDesc)
    7535 {
    7536     /*
    7537      * (If match or promoted to match, return, else break.)
    7538      */
    7539     switch (pVarDesc->enmCategory)
    7540     {
    7541         /*
    7542          * Anything goes
    7543          */
    7544         case DBGCVAR_CAT_ANY:
    7545             return VINF_SUCCESS;
    7546 
    7547         /*
    7548          * Pointer with and without range.
    7549          * We can try resolve strings and symbols as symbols and
    7550          * promote numbers to flat GC pointers.
    7551          */
    7552         case DBGCVAR_CAT_POINTER_NO_RANGE:
    7553             if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    7554                 return VERR_PARSE_NO_RANGE_ALLOWED;
    7555             /* fallthru */
    7556         case DBGCVAR_CAT_POINTER:
    7557             switch (pVar->enmType)
    7558             {
    7559                 case DBGCVAR_TYPE_GC_FLAT:
    7560                 case DBGCVAR_TYPE_GC_FAR:
    7561                 case DBGCVAR_TYPE_GC_PHYS:
    7562                 case DBGCVAR_TYPE_HC_FLAT:
    7563                 case DBGCVAR_TYPE_HC_FAR:
    7564                 case DBGCVAR_TYPE_HC_PHYS:
    7565                     return VINF_SUCCESS;
    7566 
    7567                 case DBGCVAR_TYPE_SYMBOL:
    7568                 case DBGCVAR_TYPE_STRING:
    7569                 {
    7570                     DBGCVAR Var;
    7571                     int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_GC_FLAT, &Var);
    7572                     if (VBOX_SUCCESS(rc))
    7573                     {
    7574                         /* deal with range */
    7575                         if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    7576                         {
    7577                             Var.enmRangeType = pVar->enmRangeType;
    7578                             Var.u64Range = pVar->u64Range;
    7579                         }
    7580                         else if (pVarDesc->enmCategory == DBGCVAR_CAT_POINTER_NO_RANGE)
    7581                             Var.enmRangeType = DBGCVAR_RANGE_NONE;
    7582                         *pVar = Var;
    7583                         return rc;
    7584                     }
    7585                     break;
    7586                 }
    7587 
    7588                 case DBGCVAR_TYPE_NUMBER:
    7589                 {
    7590                     RTGCPTR GCPtr = (RTGCPTR)pVar->u.u64Number;
    7591                     pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
    7592                     pVar->u.GCFlat = GCPtr;
    7593                     return VINF_SUCCESS;
    7594                 }
    7595 
    7596                 default:
    7597                     break;
    7598             }
    7599             break;
    7600 
    7601         /*
    7602          * GC pointer with and without range.
    7603          * We can try resolve strings and symbols as symbols and
    7604          * promote numbers to flat GC pointers.
    7605          */
    7606         case DBGCVAR_CAT_GC_POINTER_NO_RANGE:
    7607             if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    7608                 return VERR_PARSE_NO_RANGE_ALLOWED;
    7609             /* fallthru */
    7610         case DBGCVAR_CAT_GC_POINTER:
    7611             switch (pVar->enmType)
    7612             {
    7613                 case DBGCVAR_TYPE_GC_FLAT:
    7614                 case DBGCVAR_TYPE_GC_FAR:
    7615                 case DBGCVAR_TYPE_GC_PHYS:
    7616                     return VINF_SUCCESS;
    7617 
    7618                 case DBGCVAR_TYPE_HC_FLAT:
    7619                 case DBGCVAR_TYPE_HC_FAR:
    7620                 case DBGCVAR_TYPE_HC_PHYS:
    7621                     return VERR_PARSE_CONVERSION_FAILED;
    7622 
    7623                 case DBGCVAR_TYPE_SYMBOL:
    7624                 case DBGCVAR_TYPE_STRING:
    7625                 {
    7626                     DBGCVAR Var;
    7627                     int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_GC_FLAT, &Var);
    7628                     if (VBOX_SUCCESS(rc))
    7629                     {
    7630                         /* deal with range */
    7631                         if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    7632                         {
    7633                             Var.enmRangeType = pVar->enmRangeType;
    7634                             Var.u64Range = pVar->u64Range;
    7635                         }
    7636                         else if (pVarDesc->enmCategory == DBGCVAR_CAT_POINTER_NO_RANGE)
    7637                             Var.enmRangeType = DBGCVAR_RANGE_NONE;
    7638                         *pVar = Var;
    7639                         return rc;
    7640                     }
    7641                     break;
    7642                 }
    7643 
    7644                 case DBGCVAR_TYPE_NUMBER:
    7645                 {
    7646                     RTGCPTR GCPtr = (RTGCPTR)pVar->u.u64Number;
    7647                     pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
    7648                     pVar->u.GCFlat = GCPtr;
    7649                     return VINF_SUCCESS;
    7650                 }
    7651 
    7652                 default:
    7653                     break;
    7654             }
    7655             break;
    7656 
    7657         /*
    7658          * Number with or without a range.
    7659          * Numbers can be resolved from symbols, but we cannot demote a pointer
    7660          * to a number.
    7661          */
    7662         case DBGCVAR_CAT_NUMBER_NO_RANGE:
    7663             if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
    7664                 return VERR_PARSE_NO_RANGE_ALLOWED;
    7665             /* fallthru */
    7666         case DBGCVAR_CAT_NUMBER:
    7667             switch (pVar->enmType)
    7668             {
    7669                 case DBGCVAR_TYPE_NUMBER:
    7670                     return VINF_SUCCESS;
    7671 
    7672                 case DBGCVAR_TYPE_SYMBOL:
    7673                 case DBGCVAR_TYPE_STRING:
    7674                 {
    7675                     DBGCVAR Var;
    7676                     int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
    7677                     if (VBOX_SUCCESS(rc))
    7678                     {
    7679                         *pVar = Var;
    7680                         return rc;
    7681                     }
    7682                     break;
    7683                 }
    7684                 default:
    7685                     break;
    7686             }
    7687             break;
    7688 
    7689         /*
    7690          * Strings can easily be made from symbols (and of course strings).
    7691          * We could consider reformatting the addresses and numbers into strings later...
    7692          */
    7693         case DBGCVAR_CAT_STRING:
    7694             switch (pVar->enmType)
    7695             {
    7696                 case DBGCVAR_TYPE_SYMBOL:
    7697                     pVar->enmType = DBGCVAR_TYPE_STRING;
    7698                     /* fallthru */
    7699                 case DBGCVAR_TYPE_STRING:
    7700                     return VINF_SUCCESS;
    7701                 default:
    7702                     break;
    7703             }
    7704             break;
    7705 
    7706         /*
    7707          * Symol is pretty much the same thing as a string (at least until we actually implement it).
    7708          */
    7709         case DBGCVAR_CAT_SYMBOL:
    7710             switch (pVar->enmType)
    7711             {
    7712                 case DBGCVAR_TYPE_STRING:
    7713                     pVar->enmType = DBGCVAR_TYPE_SYMBOL;
    7714                     /* fallthru */
    7715                 case DBGCVAR_TYPE_SYMBOL:
    7716                     return VINF_SUCCESS;
    7717                 default:
    7718                     break;
    7719             }
    7720             break;
    7721 
    7722         /*
    7723          * Anything else is illegal.
    7724          */
    7725         default:
    7726             AssertMsgFailed(("enmCategory=%d\n", pVar->enmType));
    7727             break;
    7728     }
    7729 
    7730     return VERR_PARSE_NO_ARGUMENT_MATCH;
    7731 }
    7732 
    7733 
    7734 /**
    7735  * Matches a set of variables with a description set.
    7736  *
    7737  * This is typically used for routine arguments before a call. The effects in
    7738  * addition to the validation, is that some variables might be propagated to
    7739  * other types in order to match the description. The following transformations
    7740  * are supported:
    7741  *      - String reinterpreted as a symbol and resolved to a number or pointer.
    7742  *      - Number to a pointer.
    7743  *      - Pointer to a number.
    7744  * @returns 0 on success with paVars.
    7745  * @returns VBox error code for match errors.
    7746  */
    7747 static int dbgcEvalSubMatchVars(PDBGC pDbgc, unsigned cVarsMin, unsigned cVarsMax,
    7748                                 PCDBGCVARDESC paVarDescs, unsigned cVarDescs,
    7749                                 PDBGCVAR paVars, unsigned cVars)
    7750 {
    7751     /*
    7752      * Just do basic min / max checks first.
    7753      */
    7754     if (cVars < cVarsMin)
    7755         return VERR_PARSE_TOO_FEW_ARGUMENTS;
    7756     if (cVars > cVarsMax)
    7757         return VERR_PARSE_TOO_MANY_ARGUMENTS;
    7758 
    7759     /*
    7760      * Match the descriptors and actual variables.
    7761      */
    7762     PCDBGCVARDESC   pPrevDesc = NULL;
    7763     unsigned        cCurDesc = 0;
    7764     unsigned        iVar = 0;
    7765     unsigned        iVarDesc = 0;
    7766     while (iVar < cVars)
    7767     {
    7768         /* walk the descriptors */
    7769         if (iVarDesc >= cVarDescs)
    7770             return VERR_PARSE_TOO_MANY_ARGUMENTS;
    7771         if (    (    paVarDescs[iVarDesc].fFlags & DBGCVD_FLAGS_DEP_PREV
    7772                 &&  &paVarDescs[iVarDesc - 1] != pPrevDesc)
    7773             ||  cCurDesc >= paVarDescs[iVarDesc].cTimesMax)
    7774         {
    7775             iVarDesc++;
    7776             if (iVarDesc >= cVarDescs)
    7777                 return VERR_PARSE_TOO_MANY_ARGUMENTS;
    7778             cCurDesc = 0;
    7779         }
    7780 
    7781         /*
    7782          * Skip thru optional arguments until we find something which matches
    7783          * or can easily be promoted to what the descriptor want.
    7784          */
    7785         for (;;)
    7786         {
    7787             int rc = dbgcEvalSubMatchVar(pDbgc, &paVars[iVar], &paVarDescs[iVarDesc]);
    7788             if (VBOX_SUCCESS(rc))
    7789             {
    7790                 paVars[iVar].pDesc = &paVarDescs[iVarDesc];
    7791                 cCurDesc++;
    7792                 break;
    7793             }
    7794 
    7795             /* can we advance? */
    7796             if (paVarDescs[iVarDesc].cTimesMin > cCurDesc)
    7797                 return VERR_PARSE_ARGUMENT_TYPE_MISMATCH;
    7798             if (++iVarDesc >= cVarDescs)
    7799                 return VERR_PARSE_ARGUMENT_TYPE_MISMATCH;
    7800             cCurDesc = 0;
    7801         }
    7802 
    7803         /* next var */
    7804         iVar++;
    7805     }
    7806 
    7807     /*
    7808      * Check that the rest of the descriptors are optional.
    7809      */
    7810     while (iVarDesc < cVarDescs)
    7811     {
    7812         if (paVarDescs[iVarDesc].cTimesMin > cCurDesc)
    7813             return VERR_PARSE_TOO_FEW_ARGUMENTS;
    7814         cCurDesc = 0;
    7815 
    7816         /* next */
    7817         iVarDesc++;
    7818     }
    7819 
    7820     return 0;
    7821 }
    7822 
    7823 
    7824 /**
    7825  * Evaluates one argument with respect to unary operators.
    7826  *
    7827  * @returns 0 on success. pResult contains the result.
    7828  * @returns VBox error code on parse or other evaluation error.
    7829  *
    7830  * @param   pDbgc       Debugger console instance data.
    7831  * @param   pszExpr     The expression string.
    7832  * @param   pResult     Where to store the result of the expression evaluation.
    7833  */
    7834 static int dbgcEvalSubUnary(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult)
    7835 {
    7836     Log2(("dbgcEvalSubUnary: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
    7837 
    7838     /*
    7839      * The state of the expression is now such that it will start by zero or more
    7840      * unary operators and being followed by an expression of some kind.
    7841      * The expression is either plain or in parenthesis.
    7842      *
    7843      * Being in a lazy, recursive mode today, the parsing is done as simple as possible. :-)
    7844      * ASSUME: unary operators are all of equal precedence.
    7845      */
    7846     int         rc = 0;
    7847     PCDBGCOP    pOp = dbgcOperatorLookup(pDbgc, pszExpr, false, ' ');
    7848     if (pOp)
    7849     {
    7850         /* binary operators means syntax error. */
    7851         if (pOp->fBinary)
    7852             return VERR_PARSE_UNEXPECTED_OPERATOR;
    7853 
    7854         /*
    7855          * If the next expression (the one following the unary operator) is in a
    7856          * parenthesis a full eval is needed. If not the unary eval will suffice.
    7857          */
    7858         /* calc and strip next expr. */
    7859         char *pszExpr2 = pszExpr + pOp->cchName;
    7860         while (isblank(*pszExpr2))
    7861             pszExpr2++;
    7862 
    7863         if (!*pszExpr2)
    7864             rc = VERR_PARSE_EMPTY_ARGUMENT;
    7865         else
    7866         {
    7867             DBGCVAR Arg;
    7868             if (*pszExpr2 == '(')
    7869                 rc = dbgcEvalSub(pDbgc, pszExpr2, cchExpr - (pszExpr2 - pszExpr), &Arg);
    7870             else
    7871                 rc = dbgcEvalSubUnary(pDbgc, pszExpr2, cchExpr - (pszExpr2 - pszExpr), &Arg);
    7872             if (VBOX_SUCCESS(rc))
    7873                 rc = pOp->pfnHandlerUnary(pDbgc, &Arg, pResult);
    7874         }
    7875     }
    7876     else
    7877     {
    7878         /*
    7879          * Didn't find any operators, so it we have to check if this can be an
    7880          * function call before assuming numeric or string expression.
    7881          *
    7882          * (ASSUMPTIONS:)
    7883          * A function name only contains alphanumerical chars and it can not start
    7884          * with a numerical character.
    7885          * Immediately following the name is a parenthesis which must over
    7886          * the remaining part of the expression.
    7887          */
    7888         bool    fExternal = *pszExpr == '.';
    7889         char   *pszFun    = fExternal ? pszExpr + 1 : pszExpr;
    7890         char   *pszFunEnd = NULL;
    7891         if (pszExpr[cchExpr - 1] == ')' && isalpha(*pszFun))
    7892         {
    7893             pszFunEnd = pszExpr + 1;
    7894             while (*pszFunEnd != '(' && isalnum(*pszFunEnd))
    7895                 pszFunEnd++;
    7896             if (*pszFunEnd != '(')
    7897                 pszFunEnd = NULL;
    7898         }
    7899 
    7900         if (pszFunEnd)
    7901         {
    7902             /*
    7903              * Ok, it's a function call.
    7904              */
    7905             if (fExternal)
    7906                 pszExpr++, cchExpr--;
    7907             PCDBGCCMD pFun = dbgcRoutineLookup(pDbgc, pszExpr, pszFunEnd - pszExpr, fExternal);
    7908             if (!pFun)
    7909                 return VERR_PARSE_FUNCTION_NOT_FOUND;
    7910             if (!pFun->pResultDesc)
    7911                 return VERR_PARSE_NOT_A_FUNCTION;
    7912 
    7913             /*
    7914              * Parse the expression in parenthesis.
    7915              */
    7916             cchExpr -= pszFunEnd - pszExpr;
    7917             pszExpr = pszFunEnd;
    7918             /** @todo implement multiple arguments. */
    7919             DBGCVAR     Arg;
    7920             rc = dbgcEvalSub(pDbgc, pszExpr, cchExpr, &Arg);
    7921             if (!rc)
    7922             {
    7923                 rc = dbgcEvalSubMatchVars(pDbgc, pFun->cArgsMin, pFun->cArgsMax, pFun->paArgDescs, pFun->cArgDescs, &Arg, 1);
    7924                 if (!rc)
    7925                     rc = pFun->pfnHandler(pFun, &pDbgc->CmdHlp, pDbgc->pVM, &Arg, 1, pResult);
    7926             }
    7927             else if (rc == VERR_PARSE_EMPTY_ARGUMENT && pFun->cArgsMin == 0)
    7928                 rc = pFun->pfnHandler(pFun, &pDbgc->CmdHlp, pDbgc->pVM, NULL, 0, pResult);
    7929         }
    7930         else
    7931         {
    7932             /*
    7933              * Didn't find any operators, so it must be a plain expression.
    7934              * This might be numeric or a string expression.
    7935              */
    7936             char ch  = pszExpr[0];
    7937             char ch2 = pszExpr[1];
    7938             if (ch == '0' && (ch2 == 'x' || ch2 == 'X'))
    7939                 rc = dbgcEvalSubNum(pszExpr + 2, 16, pResult);
    7940             else if (ch == '0' && (ch2 == 'i' || ch2 == 'i'))
    7941                 rc = dbgcEvalSubNum(pszExpr + 2, 10, pResult);
    7942             else if (ch == '0' && (ch2 == 't' || ch2 == 'T'))
    7943                 rc = dbgcEvalSubNum(pszExpr + 2, 8, pResult);
    7944             /// @todo 0b doesn't work as a binary prefix, we confuse it with 0bf8:0123 and stuff.
    7945             //else if (ch == '0' && (ch2 == 'b' || ch2 == 'b'))
    7946             //    rc = dbgcEvalSubNum(pszExpr + 2, 2, pResult);
    7947             else
    7948             {
    7949                 /*
    7950                  * Hexadecimal number or a string?
    7951                  */
    7952                 char *psz = pszExpr;
    7953                 while (isxdigit(*psz))
    7954                     psz++;
    7955                 if (!*psz)
    7956                     rc = dbgcEvalSubNum(pszExpr, 16, pResult);
    7957                 else if ((*psz == 'h' || *psz == 'H') && !psz[1])
    7958                 {
    7959                     *psz = '\0';
    7960                     rc = dbgcEvalSubNum(pszExpr, 16, pResult);
    7961                 }
    7962                 else
    7963                     rc = dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    7964             }
    7965         }
    7966     }
    7967 
    7968     return rc;
    7969 }
    7970 
    7971 
    7972 /**
    7973  * Evaluates one argument.
    7974  *
    7975  * @returns 0 on success. pResult contains the result.
    7976  * @returns VBox error code on parse or other evaluation error.
    7977  *
    7978  * @param   pDbgc       Debugger console instance data.
    7979  * @param   pszExpr     The expression string.
    7980  * @param   pResult     Where to store the result of the expression evaluation.
    7981  */
    7982 static int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult)
    7983 {
    7984     Log2(("dbgcEvalSub: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
    7985     /*
    7986      * First we need to remove blanks in both ends.
    7987      * ASSUMES: There is no quoting unless the entire expression is a string.
    7988      */
    7989 
    7990     /* stripping. */
    7991     while (cchExpr > 0 && isblank(pszExpr[cchExpr - 1]))
    7992         pszExpr[--cchExpr] = '\0';
    7993     while (isblank(*pszExpr))
    7994         pszExpr++, cchExpr--;
    7995     if (!*pszExpr)
    7996         return VERR_PARSE_EMPTY_ARGUMENT;
    7997 
    7998     /* it there is any kind of quoting in the expression, it's string meat. */
    7999     if (strpbrk(pszExpr, "\"'`"))
    8000         return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
    8001 
    8002     /*
    8003      * Check if there are any parenthesis which needs removing.
    8004      */
    8005     if (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')')
    8006     {
    8007         do
    8008         {
    8009             unsigned cPar = 1;
    8010             char    *psz = pszExpr + 1;
    8011             char     ch;
    8012             while ((ch = *psz) != '\0')
    8013             {
    8014                 if (ch == '(')
    8015                     cPar++;
    8016                 else if (ch == ')')
    8017                 {
    8018                     if (cPar <= 0)
    8019                         return VERR_PARSE_UNBALANCED_PARENTHESIS;
    8020                     cPar--;
    8021                     if (cPar == 0 && psz[1]) /* If not at end, there's nothing to do. */
    8022                         break;
    8023                 }
    8024                 /* next */
    8025                 psz++;
    8026             }
    8027             if (ch)
    8028                 break;
    8029 
    8030             /* remove the parenthesis. */
    8031             pszExpr++;
    8032             cchExpr -= 2;
    8033             pszExpr[cchExpr] = '\0';
    8034 
    8035             /* strip blanks. */
    8036             while (cchExpr > 0 && isblank(pszExpr[cchExpr - 1]))
    8037                 pszExpr[--cchExpr] = '\0';
    8038             while (isblank(*pszExpr))
    8039                 pszExpr++, cchExpr--;
    8040             if (!*pszExpr)
    8041                 return VERR_PARSE_EMPTY_ARGUMENT;
    8042         } while (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')');
    8043     }
    8044 
    8045     /* tabs to spaces. */
    8046     char *psz = pszExpr;
    8047     while ((psz = strchr(psz, '\t')) != NULL)
    8048         *psz = ' ';
    8049 
    8050     /*
    8051      * Now, we need to look for the binary operator with the lowest precedence.
    8052      *
    8053      * If there are no operators we're left with a simple expression which we
    8054      * evaluate with respect to unary operators
    8055      */
    8056     char       *pszOpSplit = NULL;
    8057     PCDBGCOP    pOpSplit = NULL;
    8058     unsigned    cBinaryOps = 0;
    8059     unsigned    cPar = 0;
    8060     char        ch;
    8061     char        chPrev = ' ';
    8062     bool        fBinary = false;
    8063     psz = pszExpr;
    8064 
    8065     while ((ch = *psz) != '\0')
    8066     {
    8067         //Log2(("ch=%c cPar=%d fBinary=%d\n", ch, cPar, fBinary));
    8068         /*
    8069          * Parenthesis.
    8070          */
    8071         if (ch == '(')
    8072         {
    8073             cPar++;
    8074             fBinary = false;
    8075         }
    8076         else if (ch == ')')
    8077         {
    8078             if (cPar <= 0)
    8079                 return VERR_PARSE_UNBALANCED_PARENTHESIS;
    8080             cPar--;
    8081             fBinary = true;
    8082         }
    8083         /*
    8084          * Potential operator.
    8085          */
    8086         else if (cPar == 0 && !isblank(ch))
    8087         {
    8088             PCDBGCOP pOp = dbgcIsOpChar(ch)
    8089                          ? dbgcOperatorLookup(pDbgc, psz, fBinary, chPrev)
    8090                          : NULL;
    8091             if (pOp)
    8092             {
    8093                 /* If not the right kind of operator we've got a syntax error. */
    8094                 if (pOp->fBinary != fBinary)
    8095                     return VERR_PARSE_UNEXPECTED_OPERATOR;
    8096 
    8097                 /*
    8098                  * Update the parse state and skip the operator.
    8099                  */
    8100                 if (!pOpSplit)
    8101                 {
    8102                     pOpSplit = pOp;
    8103                     pszOpSplit = psz;
    8104                     cBinaryOps = fBinary;
    8105                 }
    8106                 else if (fBinary)
    8107                 {
    8108                     cBinaryOps++;
    8109                     if (pOp->iPrecedence >= pOpSplit->iPrecedence)
    8110                     {
    8111                         pOpSplit = pOp;
    8112                         pszOpSplit = psz;
    8113                     }
    8114                 }
    8115 
    8116                 psz += pOp->cchName - 1;
    8117                 fBinary = false;
    8118             }
    8119             else
    8120                 fBinary = true;
    8121         }
    8122 
    8123         /* next */
    8124         psz++;
    8125         chPrev = ch;
    8126     } /* parse loop. */
    8127 
    8128 
    8129     /*
    8130      * Either we found an operator to divide the expression by
    8131      * or we didn't find any. In the first case it's divide and
    8132      * conquer. In the latter it's a single expression which
    8133      * needs dealing with its unary operators if any.
    8134      */
    8135     int rc;
    8136     if (    cBinaryOps
    8137         &&  pOpSplit->fBinary)
    8138     {
    8139         /* process 1st sub expression. */
    8140         *pszOpSplit = '\0';
    8141         DBGCVAR     Arg1;
    8142         rc = dbgcEvalSub(pDbgc, pszExpr, pszOpSplit - pszExpr, &Arg1);
    8143         if (VBOX_SUCCESS(rc))
    8144         {
    8145             /* process 2nd sub expression. */
    8146             char       *psz2 = pszOpSplit + pOpSplit->cchName;
    8147             DBGCVAR     Arg2;
    8148             rc = dbgcEvalSub(pDbgc, psz2, cchExpr - (psz2 - pszExpr), &Arg2);
    8149             if (VBOX_SUCCESS(rc))
    8150                 /* apply the operator. */
    8151                 rc = pOpSplit->pfnHandlerBinary(pDbgc, &Arg1, &Arg2, pResult);
    8152         }
    8153     }
    8154     else if (cBinaryOps)
    8155     {
    8156         /* process sub expression. */
    8157         pszOpSplit += pOpSplit->cchName;
    8158         DBGCVAR     Arg;
    8159         rc = dbgcEvalSub(pDbgc, pszOpSplit, cchExpr - (pszOpSplit - pszExpr), &Arg);
    8160         if (VBOX_SUCCESS(rc))
    8161             /* apply the operator. */
    8162             rc = pOpSplit->pfnHandlerUnary(pDbgc, &Arg, pResult);
    8163     }
    8164     else
    8165         /* plain expression or using unary operators perhaps with paratheses. */
    8166         rc = dbgcEvalSubUnary(pDbgc, pszExpr, cchExpr, pResult);
    8167 
    8168     return rc;
    8169 }
    8170 
    8171 
    8172 /**
    8173  * Parses the arguments of one command.
    8174  *
    8175  * @returns 0 on success.
    8176  * @returns VBox error code on parse error with *pcArg containing the argument causing trouble.
    8177  * @param   pDbgc       Debugger console instance data.
    8178  * @param   pCmd        Pointer to the command descriptor.
    8179  * @param   pszArg      Pointer to the arguments to parse.
    8180  * @param   paArgs      Where to store the parsed arguments.
    8181  * @param   cArgs       Size of the paArgs array.
    8182  * @param   pcArgs      Where to store the number of arguments.
    8183  *                      In the event of an error this is used to store the index of the offending argument.
    8184  */
    8185 static int dbgcProcessArguments(PDBGC pDbgc, PCDBGCCMD pCmd, char *pszArgs, PDBGCVAR paArgs, unsigned cArgs, unsigned *pcArgs)
    8186 {
    8187     Log2(("dbgcProcessArguments: pCmd=%s pszArgs='%s'\n", pCmd->pszCmd, pszArgs));
    8188     /*
    8189      * Check if we have any argument and if the command takes any.
    8190      */
    8191     *pcArgs = 0;
    8192     /* strip leading blanks. */
    8193     while (*pszArgs && isblank(*pszArgs))
    8194         pszArgs++;
    8195     if (!*pszArgs)
    8196     {
    8197         if (!pCmd->cArgsMin)
    8198             return 0;
    8199         return VERR_PARSE_TOO_FEW_ARGUMENTS;
    8200     }
    8201     /** @todo fixme - foo() doesn't work. */
    8202     if (!pCmd->cArgsMax)
    8203         return VERR_PARSE_TOO_MANY_ARGUMENTS;
    8204 
    8205     /*
    8206      * This is a hack, it's "temporary" and should go away "when" the parser is
    8207      * modified to match arguments while parsing.
    8208      */
    8209     if (    pCmd->cArgsMax == 1
    8210         &&  pCmd->cArgsMin == 1
    8211         &&  pCmd->cArgDescs == 1
    8212         &&  pCmd->paArgDescs[0].enmCategory == DBGCVAR_CAT_STRING
    8213         &&  cArgs >= 1)
    8214     {
    8215         *pcArgs = 1;
    8216         RTStrStripR(pszArgs);
    8217         return dbgcEvalSubString(pDbgc, pszArgs, strlen(pszArgs), &paArgs[0]);
    8218     }
    8219 
    8220 
    8221     /*
    8222      * The parse loop.
    8223      */
    8224     PDBGCVAR        pArg0 = &paArgs[0];
    8225     PDBGCVAR        pArg = pArg0;
    8226     *pcArgs = 0;
    8227     do
    8228     {
    8229         /*
    8230          * Can we have another argument?
    8231          */
    8232         if (*pcArgs >= pCmd->cArgsMax)
    8233             return VERR_PARSE_TOO_MANY_ARGUMENTS;
    8234         if (pArg >= &paArgs[cArgs])
    8235             return VERR_PARSE_ARGUMENT_OVERFLOW;
    8236 
    8237         /*
    8238          * Find the end of the argument.
    8239          */
    8240         int     cPar    = 0;
    8241         char    chQuote = '\0';
    8242         char   *pszEnd  = NULL;
    8243         char   *psz     = pszArgs;
    8244         char    ch;
    8245         bool    fBinary = false;
    8246         for (;;)
    8247         {
    8248             /*
    8249              * Check for the end.
    8250              */
    8251             if ((ch = *psz) == '\0')
    8252             {
    8253                 if (chQuote)
    8254                     return VERR_PARSE_UNBALANCED_QUOTE;
    8255                 if (cPar)
    8256                     return VERR_PARSE_UNBALANCED_PARENTHESIS;
    8257                 pszEnd = psz;
    8258                 break;
    8259             }
    8260             /*
    8261              * When quoted we ignore everything but the quotation char.
    8262              * We use the REXX way of escaping the quotation char, i.e. double occurence.
    8263              */
    8264             else if (ch == '\'' || ch == '"' || ch == '`')
    8265             {
    8266                 if (chQuote)
    8267                 {
    8268                     /* end quote? */
    8269                     if (ch == chQuote)
    8270                     {
    8271                         if (psz[1] == ch)
    8272                             psz++;          /* skip the escaped quote char */
    8273                         else
    8274                             chQuote = '\0'; /* end of quoted string. */
    8275                     }
    8276                 }
    8277                 else
    8278                     chQuote = ch;           /* open new quote */
    8279             }
    8280             /*
    8281              * Parenthesis can of course be nested.
    8282              */
    8283             else if (ch == '(')
    8284             {
    8285                 cPar++;
    8286                 fBinary = false;
    8287             }
    8288             else if (ch == ')')
    8289             {
    8290                 if (!cPar)
    8291                     return VERR_PARSE_UNBALANCED_PARENTHESIS;
    8292                 cPar--;
    8293                 fBinary = true;
    8294             }
    8295             else if (!chQuote && !cPar)
    8296             {
    8297                 /*
    8298                  * Encountering blanks may mean the end of it all. A binary operator
    8299                  * will force continued parsing.
    8300                  */
    8301                 if (isblank(*psz))
    8302                 {
    8303                     pszEnd = psz++;         /* just in case. */
    8304                     while (isblank(*psz))
    8305                         psz++;
    8306                     PCDBGCOP pOp = dbgcOperatorLookup(pDbgc, psz, fBinary, ' ');
    8307                     if (!pOp || pOp->fBinary != fBinary)
    8308                         break;              /* the end. */
    8309                     psz += pOp->cchName;
    8310                     while (isblank(*psz))   /* skip blanks so we don't get here again */
    8311                         psz++;
    8312                     fBinary = false;
    8313                     continue;
    8314                 }
    8315 
    8316                 /*
    8317                  * Look for operators without a space up front.
    8318                  */
    8319                 if (dbgcIsOpChar(*psz))
    8320                 {
    8321                     PCDBGCOP pOp = dbgcOperatorLookup(pDbgc, psz, fBinary, ' ');
    8322                     if (pOp)
    8323                     {
    8324                         if (pOp->fBinary != fBinary)
    8325                         {
    8326                             pszEnd = psz;
    8327                             /** @todo this is a parsing error really. */
    8328                             break;              /* the end. */
    8329                         }
    8330                         psz += pOp->cchName;
    8331                         while (isblank(*psz))   /* skip blanks so we don't get here again */
    8332                             psz++;
    8333                         fBinary = false;
    8334                         continue;
    8335                     }
    8336                 }
    8337                 fBinary = true;
    8338             }
    8339 
    8340             /* next char */
    8341             psz++;
    8342         }
    8343         *pszEnd = '\0';
    8344         /* (psz = next char to process) */
    8345 
    8346         /*
    8347          * Parse and evaluate the argument.
    8348          */
    8349         int rc = dbgcEvalSub(pDbgc, pszArgs, strlen(pszArgs), pArg);
    8350         if (VBOX_FAILURE(rc))
    8351             return rc;
    8352 
    8353         /*
    8354          * Next.
    8355          */
    8356         pArg++;
    8357         (*pcArgs)++;
    8358         pszArgs = psz;
    8359         while (*pszArgs && isblank(*pszArgs))
    8360             pszArgs++;
    8361     } while (*pszArgs);
    8362 
    8363     /*
    8364      * Match the arguments.
    8365      */
    8366     return dbgcEvalSubMatchVars(pDbgc, pCmd->cArgsMin, pCmd->cArgsMax, pCmd->paArgDescs, pCmd->cArgDescs, pArg0, pArg - pArg0);
    8367 }
    8368 
    8369 
    8370 /**
    8371  * Process one command.
    8372  *
    8373  * @returns VBox status code. Any error indicates the termination of the console session.
    8374  * @param   pDbgc   Debugger console instance data.
    8375  * @param   pszCmd  Pointer to the command.
    8376  * @param   cchCmd  Length of the command.
    8377  */
    8378 static int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd)
    8379 {
    8380     char *pszCmdInput = pszCmd;
    8381 
    8382     /*
    8383      * Skip blanks.
    8384      */
    8385     while (isblank(*pszCmd))
    8386         pszCmd++, cchCmd--;
    8387 
    8388     /* external command? */
    8389     bool fExternal = *pszCmd == '.';
    8390     if (fExternal)
    8391         pszCmd++, cchCmd--;
    8392 
    8393     /*
    8394      * Find arguments.
    8395      */
    8396     char *pszArgs = pszCmd;
    8397     while (isalnum(*pszArgs))
    8398         pszArgs++;
    8399     if (*pszArgs && (!isblank(*pszArgs) || pszArgs == pszCmd))
    8400     {
    8401         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Syntax error in command '%s'!\n", pszCmdInput);
    8402         return 0;
    8403     }
    8404 
    8405     /*
    8406      * Find the command.
    8407      */
    8408     PCDBGCCMD pCmd = dbgcRoutineLookup(pDbgc, pszCmd, pszArgs - pszCmd, fExternal);
    8409     if (!pCmd || (pCmd->fFlags & DBGCCMD_FLAGS_FUNCTION))
    8410         return pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Unknown command '%s'!\n", pszCmdInput);
    8411 
    8412     /*
    8413      * Parse arguments (if any).
    8414      */
    8415     unsigned    cArgs;
    8416     int rc = dbgcProcessArguments(pDbgc, pCmd, pszArgs, &pDbgc->aArgs[pDbgc->iArg], ELEMENTS(pDbgc->aArgs) - pDbgc->iArg, &cArgs);
    8417 
    8418     /*
    8419      * Execute the command.
    8420      */
    8421     if (!rc)
    8422     {
    8423         rc = pCmd->pfnHandler(pCmd, &pDbgc->CmdHlp, pDbgc->pVM, &pDbgc->aArgs[0], cArgs, NULL);
    8424     }
    8425     else
    8426     {
    8427         /* report parse / eval error. */
    8428         switch (rc)
    8429         {
    8430             case VERR_PARSE_TOO_FEW_ARGUMENTS:
    8431                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8432                     "Syntax error: Too few arguments. Minimum is %d for command '%s'.\n", pCmd->cArgsMin, pCmd->pszCmd);
    8433                 break;
    8434             case VERR_PARSE_TOO_MANY_ARGUMENTS:
    8435                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8436                     "Syntax error: Too many arguments. Maximum is %d for command '%s'.\n", pCmd->cArgsMax, pCmd->pszCmd);
    8437                 break;
    8438             case VERR_PARSE_ARGUMENT_OVERFLOW:
    8439                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8440                     "Syntax error: Too many arguments.\n");
    8441                 break;
    8442             case VERR_PARSE_UNBALANCED_QUOTE:
    8443                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8444                     "Syntax error: Unbalanced quote (argument %d).\n", cArgs);
    8445                 break;
    8446             case VERR_PARSE_UNBALANCED_PARENTHESIS:
    8447                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8448                     "Syntax error: Unbalanced parenthesis (argument %d).\n", cArgs);
    8449                 break;
    8450             case VERR_PARSE_EMPTY_ARGUMENT:
    8451                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8452                     "Syntax error: An argument or subargument contains nothing useful (argument %d).\n", cArgs);
    8453                 break;
    8454             case VERR_PARSE_UNEXPECTED_OPERATOR:
    8455                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8456                     "Syntax error: Invalid operator usage (argument %d).\n", cArgs);
    8457                 break;
    8458             case VERR_PARSE_INVALID_NUMBER:
    8459                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8460                     "Syntax error: Ivalid numeric value (argument %d). If a string was the intention, then quote it.\n", cArgs);
    8461                 break;
    8462             case VERR_PARSE_NUMBER_TOO_BIG:
    8463                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8464                     "Error: Numeric overflow (argument %d).\n", cArgs);
    8465                 break;
    8466             case VERR_PARSE_INVALID_OPERATION:
    8467                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8468                     "Error: Invalid operation attempted (argument %d).\n", cArgs);
    8469                 break;
    8470             case VERR_PARSE_FUNCTION_NOT_FOUND:
    8471                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8472                     "Error: Function not found (argument %d).\n", cArgs);
    8473                 break;
    8474             case VERR_PARSE_NOT_A_FUNCTION:
    8475                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8476                     "Error: The function specified is not a function (argument %d).\n", cArgs);
    8477                 break;
    8478             case VERR_PARSE_NO_MEMORY:
    8479                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8480                     "Error: Out memory in the regular heap! Expect odd stuff to happen...\n", cArgs);
    8481                 break;
    8482             case VERR_PARSE_INCORRECT_ARG_TYPE:
    8483                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8484                     "Error: Incorrect argument type (argument %d?).\n", cArgs);
    8485                 break;
    8486             case VERR_PARSE_VARIABLE_NOT_FOUND:
    8487                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8488                     "Error: An undefined variable was referenced (argument %d).\n", cArgs);
    8489                 break;
    8490             case VERR_PARSE_CONVERSION_FAILED:
    8491                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8492                     "Error: A conversion between two types failed (argument %d).\n", cArgs);
    8493                 break;
    8494             case VERR_PARSE_NOT_IMPLEMENTED:
    8495                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8496                     "Error: You hit a debugger feature which isn't implemented yet (argument %d).\n", cArgs);
    8497                 break;
    8498             case VERR_PARSE_BAD_RESULT_TYPE:
    8499                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8500                     "Error: Couldn't satisfy a request for a specific result type (argument %d). (Usually applies to symbols)\n", cArgs);
    8501                 break;
    8502             case VERR_PARSE_WRITEONLY_SYMBOL:
    8503                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8504                     "Error: Cannot get symbol, it's set only (argument %d).\n", cArgs);
    8505                 break;
    8506 
    8507             default:
    8508                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8509                     "Error: Unknown error %d!\n", rc);
    8510                 return rc;
    8511         }
    8512 
    8513         /*
    8514          * Parse errors are non fatal.
    8515          */
    8516         if (rc >= VERR_PARSE_FIRST && rc < VERR_PARSE_LAST)
    8517             rc = 0;
    8518     }
    8519 
    8520     return rc;
    8521 }
    8522 
    8523 
    8524 /**
    8525  * Process all commands current in the buffer.
    8526  *
    8527  * @returns VBox status code. Any error indicates the termination of the console session.
    8528  * @param   pDbgc   Debugger console instance data.
    8529  */
    8530 static int dbgcProcessCommands(PDBGC pDbgc)
    8531 {
    8532     int rc = 0;
    8533     while (pDbgc->cInputLines)
    8534     {
    8535         /*
    8536          * Empty the log buffer if we're hooking the log.
    8537          */
    8538         if (pDbgc->fLog)
    8539         {
    8540             rc = dbgcProcessLog(pDbgc);
    8541             if (VBOX_FAILURE(rc))
    8542                 break;
    8543         }
    8544 
    8545         if (pDbgc->iRead == pDbgc->iWrite)
    8546         {
    8547             AssertMsgFailed(("The input buffer is empty while cInputLines=%d!\n", pDbgc->cInputLines));
    8548             pDbgc->cInputLines = 0;
    8549             return 0;
    8550         }
    8551 
    8552         /*
    8553          * Copy the command to the parse buffer.
    8554          */
    8555         char    ch;
    8556         char   *psz = &pDbgc->achInput[pDbgc->iRead];
    8557         char   *pszTrg = &pDbgc->achScratch[0];
    8558         while ((*pszTrg = ch = *psz++) != ';' && ch != '\n' )
    8559         {
    8560             if (psz == &pDbgc->achInput[sizeof(pDbgc->achInput)])
    8561                 psz = &pDbgc->achInput[0];
    8562 
    8563             if (psz == &pDbgc->achInput[pDbgc->iWrite])
    8564             {
    8565                 AssertMsgFailed(("The buffer contains no commands while cInputLines=%d!\n", pDbgc->cInputLines));
    8566                 pDbgc->cInputLines = 0;
    8567                 return 0;
    8568             }
    8569 
    8570             pszTrg++;
    8571         }
    8572         *pszTrg = '\0';
    8573 
    8574         /*
    8575          * Advance the buffer.
    8576          */
    8577         pDbgc->iRead = psz - &pDbgc->achInput[0];
    8578         if (ch == '\n')
    8579             pDbgc->cInputLines--;
    8580 
    8581         /*
    8582          * Parse and execute this command.
    8583          */
    8584         pDbgc->pszScratch = psz;
    8585         pDbgc->iArg       = 0;
    8586         rc = dbgcProcessCommand(pDbgc, &pDbgc->achScratch[0], psz - &pDbgc->achScratch[0] - 1);
    8587         if (rc)
    8588             break;
    8589     }
    8590 
    8591     return rc;
    8592 }
    8593 
    8594 
    8595 /**
    8596  * Reads input, parses it and executes commands on '\n'.
    8597  *
    8598  * @returns VBox status.
    8599  * @param   pDbgc   Debugger console instance data.
    8600  */
    8601 static int dbgcProcessInput(PDBGC pDbgc)
    8602 {
    8603     /*
    8604      * We know there's input ready, so let's read it first.
    8605      */
    8606     int rc = dbgcInputRead(pDbgc);
    8607     if (VBOX_FAILURE(rc))
    8608         return rc;
    8609 
    8610     /*
    8611      * Now execute any ready commands.
    8612      */
    8613     if (pDbgc->cInputLines)
    8614     {
    8615         /** @todo this fReady stuff is broken. */
    8616         pDbgc->fReady = false;
    8617         rc = dbgcProcessCommands(pDbgc);
    8618         if (VBOX_SUCCESS(rc) && rc != VWRN_DBGC_CMD_PENDING)
    8619             pDbgc->fReady = true;
    8620         if (    VBOX_SUCCESS(rc)
    8621             &&  pDbgc->iRead == pDbgc->iWrite
    8622             &&  pDbgc->fReady)
    8623             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");
    8624     }
    8625 
    8626     return rc;
    8627 }
    8628 
    8629 
    8630 /**
    8631  * Gets the event context identifier string.
    8632  * @returns Read only string.
    8633  * @param   enmCtx          The context.
    8634  */
    8635 static const char *dbgcGetEventCtx(DBGFEVENTCTX enmCtx)
    8636 {
    8637     switch (enmCtx)
    8638     {
    8639         case DBGFEVENTCTX_RAW:      return "raw";
    8640         case DBGFEVENTCTX_REM:      return "rem";
    8641         case DBGFEVENTCTX_HWACCL:   return "hwaccl";
    8642         case DBGFEVENTCTX_HYPER:    return "hyper";
    8643         case DBGFEVENTCTX_OTHER:    return "other";
    8644 
    8645         case DBGFEVENTCTX_INVALID:  return "!Invalid Event Ctx!";
    8646         default:
    8647             AssertMsgFailed(("enmCtx=%d\n", enmCtx));
    8648             return "!Unknown Event Ctx!";
    8649     }
    8650 }
    8651 
    8652 
    8653 /**
    8654  * Processes debugger events.
    8655  *
    8656  * @returns VBox status.
    8657  * @param   pDbgc   DBGC Instance data.
    8658  * @param   pEvent  Pointer to event data.
    8659  */
    8660 static int dbgcProcessEvent(PDBGC pDbgc, PCDBGFEVENT pEvent)
    8661 {
    8662     /*
    8663      * Flush log first.
    8664      */
    8665     if (pDbgc->fLog)
    8666     {
    8667         int rc = dbgcProcessLog(pDbgc);
    8668         if (VBOX_FAILURE(rc))
    8669             return rc;
    8670     }
    8671 
    8672     /*
    8673      * Process the event.
    8674      */
    8675     pDbgc->pszScratch = &pDbgc->achInput[0];
    8676     pDbgc->iArg       = 0;
    8677     bool fPrintPrompt = true;
    8678     int rc = VINF_SUCCESS;
    8679     switch (pEvent->enmType)
    8680     {
    8681         /*
    8682          * The first part is events we have initiated with commands.
    8683          */
    8684         case DBGFEVENT_HALT_DONE:
    8685         {
    8686             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: VM %p is halted! (%s)\n",
    8687                                          pDbgc->pVM, dbgcGetEventCtx(pEvent->enmCtx));
    8688             pDbgc->fRegCtxGuest = true; /* we're always in guest context when halted. */
    8689             if (VBOX_SUCCESS(rc))
    8690                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    8691             break;
    8692         }
    8693 
    8694 
    8695         /*
    8696          * The second part is events which can occur at any time.
    8697          */
    8698         case DBGFEVENT_FATAL_ERROR:
    8699         {
    8700             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbf event: Fatal error! (%s)\n",
    8701                                          dbgcGetEventCtx(pEvent->enmCtx));
    8702             pDbgc->fRegCtxGuest = false; /* fatal errors are always in hypervisor. */
    8703             if (VBOX_SUCCESS(rc))
    8704                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    8705             break;
    8706         }
    8707 
    8708         case DBGFEVENT_BREAKPOINT:
    8709         case DBGFEVENT_BREAKPOINT_HYPER:
    8710         {
    8711             bool fRegCtxGuest = pDbgc->fRegCtxGuest;
    8712             pDbgc->fRegCtxGuest = pEvent->enmType == DBGFEVENT_BREAKPOINT;
    8713 
    8714             rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp);
    8715             switch (rc)
    8716             {
    8717                 case VERR_DBGC_BP_NOT_FOUND:
    8718                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Unknown breakpoint %u! (%s)\n",
    8719                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    8720                     break;
    8721 
    8722                 case VINF_DBGC_BP_NO_COMMAND:
    8723                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! (%s)\n",
    8724                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    8725                     break;
    8726 
    8727                 case VINF_BUFFER_OVERFLOW:
    8728                     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
    8729                                                  pEvent->u.Bp.iBp, dbgcGetEventCtx(pEvent->enmCtx));
    8730                     break;
    8731 
    8732                 default:
    8733                     break;
    8734             }
    8735             if (VBOX_SUCCESS(rc) && DBGFR3IsHalted(pDbgc->pVM))
    8736                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    8737             else
    8738                 pDbgc->fRegCtxGuest = fRegCtxGuest;
    8739             break;
    8740         }
    8741 
    8742         case DBGFEVENT_STEPPED:
    8743         case DBGFEVENT_STEPPED_HYPER:
    8744         {
    8745             pDbgc->fRegCtxGuest = pEvent->enmType == DBGFEVENT_STEPPED;
    8746 
    8747             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Single step! (%s)\n", dbgcGetEventCtx(pEvent->enmCtx));
    8748             if (VBOX_SUCCESS(rc))
    8749                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    8750             break;
    8751         }
    8752 
    8753         case DBGFEVENT_ASSERTION_HYPER:
    8754         {
    8755             pDbgc->fRegCtxGuest = false;
    8756 
    8757             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8758                                          "\ndbgf event: Hypervisor Assertion! (%s)\n"
    8759                                          "%s"
    8760                                          "%s"
    8761                                          "\n",
    8762                                          dbgcGetEventCtx(pEvent->enmCtx),
    8763                                          pEvent->u.Assert.pszMsg1,
    8764                                          pEvent->u.Assert.pszMsg2);
    8765             if (VBOX_SUCCESS(rc))
    8766                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    8767             break;
    8768         }
    8769 
    8770         case DBGFEVENT_DEV_STOP:
    8771         {
    8772             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8773                                          "\n"
    8774                                          "dbgf event: DBGFSTOP (%s)\n"
    8775                                          "File:     %s\n"
    8776                                          "Line:     %d\n"
    8777                                          "Function: %s\n",
    8778                                          dbgcGetEventCtx(pEvent->enmCtx),
    8779                                          pEvent->u.Src.pszFile,
    8780                                          pEvent->u.Src.uLine,
    8781                                          pEvent->u.Src.pszFunction);
    8782             if (VBOX_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage)
    8783                 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8784                                          "Message:  %s\n",
    8785                                              pEvent->u.Src.pszMessage);
    8786             if (VBOX_SUCCESS(rc))
    8787                 rc = pDbgc->CmdHlp.pfnExec(&pDbgc->CmdHlp, "r");
    8788             break;
    8789         }
    8790 
    8791 
    8792         case DBGFEVENT_INVALID_COMMAND:
    8793         {
    8794             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Invalid command event!\n");
    8795             fPrintPrompt = !pDbgc->fReady;
    8796             break;
    8797         }
    8798 
    8799         case DBGFEVENT_TERMINATING:
    8800         {
    8801             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nVM is terminating!\n");
    8802             rc = VERR_GENERAL_FAILURE;
    8803             break;
    8804         }
    8805 
    8806 
    8807         default:
    8808         {
    8809             rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
    8810             fPrintPrompt = !pDbgc->fReady;
    8811             break;
    8812         }
    8813     }
    8814 
    8815     /*
    8816      * Prompt, anyone?
    8817      */
    8818     if (fPrintPrompt && VBOX_SUCCESS(rc))
    8819     {
    8820         rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");
    8821     }
    8822 
    8823     return rc;
    8824 }
    8825 
    8826 
    8827 
    8828 
    8829 
    8830 /**
    8831  * Make a console instance.
    8832  *
    8833  * This will not return until either an 'exit' command is issued or a error code
    8834  * indicating connection loss is encountered.
    8835  *
    8836  * @returns VINF_SUCCESS if console termination caused by the 'exit' command.
    8837  * @returns The VBox status code causing the console termination.
    8838  *
    8839  * @param   pVM         VM Handle.
    8840  * @param   pBack       Pointer to the backend structure. This must contain
    8841  *                      a full set of function pointers to service the console.
    8842  * @param   fFlags      Reserved, must be zero.
    8843  * @remark  A forced termination of the console is easiest done by forcing the
    8844  *          callbacks to return fatal failures.
    8845  */
    8846 DBGDECL(int)    DBGCCreate(PVM pVM, PDBGCBACK pBack, unsigned fFlags)
    8847 {
    8848     /*
    8849      * Validate input.
    8850      */
    8851     AssertReturn(VALID_PTR(pVM), VERR_INVALID_PARAMETER);
    8852     AssertReturn(VALID_PTR(pBack), VERR_INVALID_PARAMETER);
    8853     AssertMsgReturn(!fFlags, ("%#x", fFlags), VERR_INVALID_PARAMETER);
    8854 
    8855     /*
    8856      * Allocate and initialize instance data
    8857      */
    8858     PDBGC   pDbgc = (PDBGC)RTMemAllocZ(sizeof(*pDbgc));
    8859     if (!pDbgc)
    8860         return VERR_NO_MEMORY;
    8861 
    8862     pDbgc->CmdHlp.pfnWrite      = dbgcHlpWrite;
    8863     pDbgc->CmdHlp.pfnPrintfV    = dbgcHlpPrintfV;
    8864     pDbgc->CmdHlp.pfnPrintf     = dbgcHlpPrintf;
    8865     pDbgc->CmdHlp.pfnVBoxErrorV = dbgcHlpVBoxErrorV;
    8866     pDbgc->CmdHlp.pfnVBoxError  = dbgcHlpVBoxError;
    8867     pDbgc->CmdHlp.pfnMemRead    = dbgcHlpMemRead;
    8868     pDbgc->CmdHlp.pfnMemWrite   = dbgcHlpMemWrite;
    8869     pDbgc->CmdHlp.pfnEval       = dbgcHlpEval;
    8870     pDbgc->CmdHlp.pfnExec       = dbgcHlpExec;
    8871     pDbgc->CmdHlp.pfnVarToDbgfAddr = dbgcHlpVarToDbgfAddr;
    8872     pDbgc->CmdHlp.pfnVarToBool = dbgcHlpVarToBool;
    8873     pDbgc->pBack            = pBack;
    8874     pDbgc->pVM              = NULL;
    8875     pDbgc->pszEmulation     = "CodeView/WinDbg";
    8876     pDbgc->paEmulationCmds  = &g_aCmdsCodeView[0];
    8877     pDbgc->cEmulationCmds   = RT_ELEMENTS(g_aCmdsCodeView);
    8878     //pDbgc->fLog             = false;
    8879     pDbgc->fRegCtxGuest     = true;
    8880     pDbgc->fRegTerse        = true;
    8881     //pDbgc->DisasmPos        = {0};
    8882     //pDbgc->SourcePos        = {0};
    8883     //pDbgc->DumpPos          = {0};
    8884     //pDbgc->cbDumpElement    = 0;
    8885     //pDbgc->cVars            = 0;
    8886     //pDbgc->paVars           = NULL;
    8887     //pDbgc->pFirstBp         = NULL;
    8888     //pDbgc->uInputZero       = 0;
    8889     //pDbgc->iRead            = 0;
    8890     //pDbgc->iWrite           = 0;
    8891     //pDbgc->cInputLines      = 0;
    8892     //pDbgc->fInputOverflow   = false;
    8893     pDbgc->fReady           = true;
    8894     pDbgc->pszScratch       = &pDbgc->achScratch[0];
    8895     //pDbgc->iArg             = 0;
    8896     //pDbgc->rcOutput         = 0;
    8897 
    8898     dbgcInitOpCharBitMap();
    8899 
    8900     /*
    8901      * Print welcome message.
    8902      */
    8903     int rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8904         "Welcome to the VirtualBox Debugger!\n");
    8905     if (VBOX_FAILURE(rc))
    8906         goto l_failure;
    8907 
    8908     /*
    8909      * Attach to the VM.
    8910      */
    8911     rc = DBGFR3Attach(pVM);
    8912     if (VBOX_FAILURE(rc))
    8913     {
    8914         rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to attach to VM %p\n", pDbgc->pVM);
    8915         goto l_failure;
    8916     }
    8917     pDbgc->pVM = pVM;
    8918 
    8919     /*
    8920      * Print commandline and auto select result.
    8921      */
    8922     rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
    8923         "Current VM is %08x\n" /** @todo get and print the VM name! */
    8924         "VBoxDbg> ",
    8925         pDbgc->pVM);
    8926     if (VBOX_FAILURE(rc))
    8927         goto l_failure;
    8928 
    8929     /*
    8930      * Main Debugger Loop.
    8931      *
    8932      * This loop will either block on waiting for input or on waiting on
    8933      * debug events. If we're forwarding the log we cannot wait for long
    8934      * before we must flush the log.
    8935      */
    8936     for (rc = 0;;)
    8937     {
    8938         if (pDbgc->pVM && DBGFR3CanWait(pDbgc->pVM))
    8939         {
    8940             /*
    8941              * Wait for a debug event.
    8942              */
    8943             PCDBGFEVENT pEvent;
    8944             rc = DBGFR3EventWait(pDbgc->pVM, pDbgc->fLog ? 1 : 32, &pEvent);
    8945             if (VBOX_SUCCESS(rc))
    8946             {
    8947                 rc = dbgcProcessEvent(pDbgc, pEvent);
    8948                 if (VBOX_FAILURE(rc))
    8949                     break;
    8950             }
    8951             else if (rc != VERR_TIMEOUT)
    8952                 break;
    8953 
    8954             /*
    8955              * Check for input.
    8956              */
    8957             if (pBack->pfnInput(pDbgc->pBack, 0))
    8958             {
    8959                 rc = dbgcProcessInput(pDbgc);
    8960                 if (VBOX_FAILURE(rc))
    8961                     break;
    8962             }
    8963         }
    8964         else
    8965         {
    8966             /*
    8967              * Wait for input. If Logging is enabled we'll only wait very briefly.
    8968              */
    8969             if (pBack->pfnInput(pDbgc->pBack, pDbgc->fLog ? 1 : 1000))
    8970             {
    8971                 rc = dbgcProcessInput(pDbgc);
    8972                 if (VBOX_FAILURE(rc))
    8973                     break;
    8974             }
    8975         }
    8976 
    8977         /*
    8978          * Forward log output.
    8979          */
    8980         if (pDbgc->fLog)
    8981         {
    8982             rc = dbgcProcessLog(pDbgc);
    8983             if (VBOX_FAILURE(rc))
    8984                 break;
    8985         }
    8986     }
    8987 
    8988 
    8989 l_failure:
    8990     /*
    8991      * Cleanup console debugger session.
    8992      */
    8993     /* Disable log hook. */
    8994     if (pDbgc->fLog)
    8995     {
    8996 
    8997     }
    8998 
    8999     /* Detach from the VM. */
    9000     if (pDbgc->pVM)
    9001         DBGFR3Detach(pDbgc->pVM);
    9002 
    9003     /* finally, free the instance memory. */
    9004     RTMemFree(pDbgc);
    9005 
    9006     return rc;
    9007 }
    9008 
    9009 
    9010 
    9011 /**
    9012  * Register one or more external commands.
    9013  *
    9014  * @returns VBox status.
    9015  * @param   paCommands      Pointer to an array of command descriptors.
    9016  *                          The commands must be unique. It's not possible
    9017  *                          to register the same commands more than once.
    9018  * @param   cCommands       Number of commands.
    9019  */
    9020 DBGDECL(int)    DBGCRegisterCommands(PCDBGCCMD paCommands, unsigned cCommands)
    9021 {
    9022     /*
    9023      * Lock the list.
    9024      */
    9025     DBGCEXTCMDS_LOCK_WR();
    9026     PDBGCEXTCMDS pCur = g_pExtCmdsHead;
    9027     while (pCur)
    9028     {
    9029         if (paCommands == pCur->paCmds)
    9030         {
    9031             DBGCEXTCMDS_UNLOCK_WR();
    9032             AssertMsgFailed(("Attempt at re-registering %d command(s)!\n", cCommands));
    9033             return VWRN_DBGC_ALREADY_REGISTERED;
    9034         }
    9035         pCur = pCur->pNext;
    9036     }
    9037 
    9038     /*
    9039      * Allocate new chunk.
    9040      */
    9041     int rc = 0;
    9042     pCur = (PDBGCEXTCMDS)RTMemAlloc(sizeof(*pCur));
    9043     if (pCur)
    9044     {
    9045         pCur->cCmds  = cCommands;
    9046         pCur->paCmds = paCommands;
    9047         pCur->pNext = g_pExtCmdsHead;
    9048         g_pExtCmdsHead = pCur;
    9049     }
    9050     else
    9051         rc = VERR_NO_MEMORY;
    9052     DBGCEXTCMDS_UNLOCK_WR();
    9053 
    9054     return rc;
    9055 }
    9056 
    9057 
    9058 /**
    9059  * Deregister one or more external commands previously registered by
    9060  * DBGCRegisterCommands().
    9061  *
    9062  * @returns VBox status.
    9063  * @param   paCommands      Pointer to an array of command descriptors
    9064  *                          as given to DBGCRegisterCommands().
    9065  * @param   cCommands       Number of commands.
    9066  */
    9067 DBGDECL(int)    DBGCDeregisterCommands(PCDBGCCMD paCommands, unsigned cCommands)
    9068 {
    9069     /*
    9070      * Lock the list.
    9071      */
    9072     DBGCEXTCMDS_LOCK_WR();
    9073     PDBGCEXTCMDS pPrev = NULL;
    9074     PDBGCEXTCMDS pCur = g_pExtCmdsHead;
    9075     while (pCur)
    9076     {
    9077         if (paCommands == pCur->paCmds)
    9078         {
    9079             if (pPrev)
    9080                 pPrev->pNext = pCur->pNext;
    9081             else
    9082                 g_pExtCmdsHead = pCur->pNext;
    9083             DBGCEXTCMDS_UNLOCK_WR();
    9084 
    9085             RTMemFree(pCur);
    9086             return VINF_SUCCESS;
    9087         }
    9088         pPrev = pCur;
    9089         pCur = pCur->pNext;
    9090     }
    9091     DBGCEXTCMDS_UNLOCK_WR();
    9092 
    9093     NOREF(cCommands);
    9094     return VERR_DBGC_COMMANDS_NOT_REGISTERED;
    9095 }
    9096 
  • trunk/src/VBox/Debugger/DBGCInternal.h

    r5668 r5669  
    337337*   Internal Functions                                                         *
    338338*******************************************************************************/
    339 #if 0
    340 static void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat);
    341 static void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb);
    342 static void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2);
    343 static void dbgcVarSetNoRange(PDBGCVAR pVar);
    344 static void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb);
    345 static int dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress);
    346 
    347 static int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
    348 static int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
    349 static int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp);
    350 static PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp);
    351 static int dbgcBpExec(PDBGC pDbgc, RTUINT iBp);
    352 
    353 static PCDBGCSYM dbgcLookupRegisterSymbol(PDBGC pDbgc, const char *pszSymbol);
    354 static int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGCVAR pResult);
    355 static int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult);
    356 static int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd);
     339int     dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
     340int     dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
     341int     dbgcBpDelete(PDBGC pDbgc, RTUINT iBp);
     342PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp);
     343int     dbgcBpExec(PDBGC pDbgc, RTUINT iBp);
     344
     345void    dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat);
     346void    dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb);
     347void    dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2);
     348void    dbgcVarSetNoRange(PDBGCVAR pVar);
     349void    dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb);
     350int     dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress);
     351
     352PCDBGCSYM dbgcLookupRegisterSymbol(PDBGC pDbgc, const char *pszSymbol);
     353
     354
     355/*******************************************************************************
     356*   Global Variables                                                           *
     357*******************************************************************************/
     358extern const DBGCCMD    g_aCmds[];
     359extern const DBGCCMD    g_aCmdsCodeView[];
     360extern const unsigned   g_cCmdsCodeView;
     361
    357362#endif
    358 
    359 
    360 /*******************************************************************************
    361 *   Global Variables                                                           *
    362 *******************************************************************************/
    363 /** Command descriptors for the basic commands. */
    364 extern const DBGCCMD    g_aCmds[];
    365 /** Command descriptors for the CodeView / WinDbg emulation.
    366  * The emulation isn't attempting to be identical, only somewhat similar.
    367  */
    368 extern const DBGCCMD    g_aCmdsCodeView[];
    369 
    370 #endif
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r5668 r5669  
    131131*   Internal Functions                                                         *
    132132*******************************************************************************/
    133 static DECLCALLBACK(int) dbgcCmdBrkREM(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    134133static DECLCALLBACK(int) dbgcCmdHelp(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    135134static DECLCALLBACK(int) dbgcCmdQuit(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    136135static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    137 static DECLCALLBACK(int) dbgcCmdStack(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    138 static DECLCALLBACK(int) dbgcCmdDumpDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    139 static DECLCALLBACK(int) dbgcCmdDumpIDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    140 static DECLCALLBACK(int) dbgcCmdDumpPageDir(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    141 static DECLCALLBACK(int) dbgcCmdDumpPageDirBoth(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    142 static DECLCALLBACK(int) dbgcCmdDumpPageTable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    143 static DECLCALLBACK(int) dbgcCmdDumpPageTableBoth(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    144 static DECLCALLBACK(int) dbgcCmdDumpTSS(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    145136static DECLCALLBACK(int) dbgcCmdInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    146137static DECLCALLBACK(int) dbgcCmdLog(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    147138static DECLCALLBACK(int) dbgcCmdLogDest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    148139static DECLCALLBACK(int) dbgcCmdLogFlags(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    149 static DECLCALLBACK(int) dbgcCmdMemoryInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    150140static DECLCALLBACK(int) dbgcCmdFormat(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    151141static DECLCALLBACK(int) dbgcCmdLoadSyms(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     
    157147static DECLCALLBACK(int) dbgcCmdEcho(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    158148static DECLCALLBACK(int) dbgcCmdRunScript(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    159 
    160 static DECLCALLBACK(int) dbgcCmdBrkAccess(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    161 static DECLCALLBACK(int) dbgcCmdBrkClear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    162 static DECLCALLBACK(int) dbgcCmdBrkDisable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    163 static DECLCALLBACK(int) dbgcCmdBrkEnable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    164 static DECLCALLBACK(int) dbgcCmdBrkList(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    165 static DECLCALLBACK(int) dbgcCmdBrkSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    166 static DECLCALLBACK(int) dbgcCmdDumpMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    167 static DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    168 static DECLCALLBACK(int) dbgcCmdListSource(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    169 static DECLCALLBACK(int) dbgcCmdListNear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    170 static DECLCALLBACK(int) dbgcCmdReg(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    171 static DECLCALLBACK(int) dbgcCmdRegGuest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    172 static DECLCALLBACK(int) dbgcCmdRegHyper(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    173 static DECLCALLBACK(int) dbgcCmdRegTerse(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    174 static DECLCALLBACK(int) dbgcCmdSearchMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    175 static DECLCALLBACK(int) dbgcCmdTrace(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    176 static DECLCALLBACK(int) dbgcCmdUnassemble(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    177149
    178150static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
     
    206178static DECLCALLBACK(int) dbgcSymSetReg(PCDBGCSYM pSymDesc, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pValue);
    207179
    208 static void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat);
    209 static void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb);
    210 static void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2);
    211 static void dbgcVarSetNoRange(PDBGCVAR pVar);
    212 static void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb);
    213 static int dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress);
    214 
    215 static int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
    216 static int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd);
    217 static int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp);
    218 static PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp);
    219 static int dbgcBpExec(PDBGC pDbgc, RTUINT iBp);
    220 
    221 static PCDBGCSYM dbgcLookupRegisterSymbol(PDBGC pDbgc, const char *pszSymbol);
    222180static int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGCVAR pResult);
    223181static int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult);
     
    264222
    265223
    266 /** 'br' arguments. */
    267 static const DBGCVARDESC    g_aArgBrkREM[] =
    268 {
    269     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    270     {  1,           1,          DBGCVAR_CAT_GC_POINTER, 0,                              "address",      "The address." },
    271     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "passes",       "The number of passes before we trigger the breakpoint. (0 is default)" },
    272     {  0,           1,          DBGCVAR_CAT_NUMBER,     DBGCVD_FLAGS_DEP_PREV,          "max passes",   "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
    273     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "cmds",         "String of commands to be executed when the breakpoint is hit. Quote it!" },
    274 };
    275 
    276 
    277 /** 'dg', 'dga', 'dl', 'dla' arguments. */
    278 static const DBGCVARDESC    g_aArgDumpDT[] =
    279 {
    280     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    281     {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "sel",          "Selector or selector range." },
    282     {  0,           ~0,         DBGCVAR_CAT_POINTER,    0,                              "address",      "Far address which selector should be dumped." },
    283 };
    284 
    285 
    286 /** 'di', 'dia' arguments. */
    287 static const DBGCVARDESC    g_aArgDumpIDT[] =
    288 {
    289     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    290     {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "int",          "The interrupt vector or interrupt vector range." },
    291 };
    292 
    293 
    294 /** 'dpd*' arguments. */
    295 static const DBGCVARDESC    g_aArgDumpPD[] =
    296 {
    297     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    298     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "index",        "Index into the page directory." },
    299     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address which page directory entry to start dumping from. Range is applied to the page directory." },
    300 };
    301 
    302 
    303 /** 'dpda' arguments. */
    304 static const DBGCVARDESC    g_aArgDumpPDAddr[] =
    305 {
    306     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    307     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address of the page directory entry to start dumping from." },
    308 };
    309 
    310 
    311 /** 'dpt?' arguments. */
    312 static const DBGCVARDESC    g_aArgDumpPT[] =
    313 {
    314     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    315     {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address which page directory entry to start dumping from." },
    316 };
    317 
    318 
    319 /** 'dpta' arguments. */
    320 static const DBGCVARDESC    g_aArgDumpPTAddr[] =
    321 {
    322     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    323     {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address of the page table entry to start dumping from." },
    324 };
    325 
    326 
    327 /** 'dt' arguments. */
    328 static const DBGCVARDESC    g_aArgDumpTSS[] =
    329 {
    330     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    331     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "tss",          "TSS selector number." },
    332     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "tss:ign|addr", "TSS address. If the selector is a TSS selector, the offset will be ignored." }
    333 };
    334 
    335 
    336224/** 'help' arguments. */
    337225static const DBGCVARDESC    g_aArgHelp[] =
     
    403291{
    404292    /* pszCmd,      cArgsMin, cArgsMax, paArgDescs,         cArgDescs,                  pResultDesc,        fFlags,     pfnHandler          pszSyntax,          ....pszDescription */
    405     { "br",         1,        4,        &g_aArgBrkREM[0],   ELEMENTS(g_aArgBrkREM),     NULL,               0,          dbgcCmdBrkREM,      "<address> [passes [max passes]] [cmds]",
    406                                                                                                                                                                     "Sets a recompiler specific breakpoint." },
    407293    { "bye",        0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
    408     { "dg",         0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the global descriptor table (GDT)." },
    409     { "dga",        0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the global descriptor table (GDT) including not-present entries." },
    410     { "di",         0,       ~0,        &g_aArgDumpIDT[0],  ELEMENTS(g_aArgDumpIDT),    NULL,               0,          dbgcCmdDumpIDT,     "[int [..]]",           "Dump the interrupt descriptor table (IDT)." },
    411     { "dia",        0,       ~0,        &g_aArgDumpIDT[0],  ELEMENTS(g_aArgDumpIDT),    NULL,               0,          dbgcCmdDumpIDT,     "[int [..]]",           "Dump the interrupt descriptor table (IDT) including not-present entries." },
    412     { "dl",         0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the local descriptor table (LDT)." },
    413     { "dla",        0,       ~0,        &g_aArgDumpDT[0],   ELEMENTS(g_aArgDumpDT),     NULL,               0,          dbgcCmdDumpDT,      "[sel [..]]",           "Dump the local descriptor table (LDT) including not-present entries." },
    414     { "dpd",        0,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the default context." },
    415     { "dpda",       0,        1,        &g_aArgDumpPDAddr[0],ELEMENTS(g_aArgDumpPDAddr),NULL,               0,          dbgcCmdDumpPageDir, "[addr]",               "Dumps specified page directory." },
    416     { "dpdb",       1,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDirBoth, "[addr] [index]",   "Dumps page directory entries of the guest and the hypervisor. " },
    417     { "dpdg",       0,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the guest." },
    418     { "dpdh",       0,        1,        &g_aArgDumpPD[0],   ELEMENTS(g_aArgDumpPD),     NULL,               0,          dbgcCmdDumpPageDir, "[addr] [index]",       "Dumps page directory entries of the hypervisor. " },
    419     { "dpt",        1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the default context." },
    420     { "dpta",       1,        1,        &g_aArgDumpPTAddr[0],ELEMENTS(g_aArgDumpPTAddr), NULL,              0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps specified page table." },
    421     { "dptb",       1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTableBoth,"<addr>",          "Dumps page table entries of the guest and the hypervisor." },
    422     { "dptg",       1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the guest." },
    423     { "dpth",       1,        1,        &g_aArgDumpPT[0],   ELEMENTS(g_aArgDumpPT),     NULL,               0,          dbgcCmdDumpPageTable,"<addr>",              "Dumps page table entries of the hypervisor." },
    424     { "dt",         0,        1,        &g_aArgDumpTSS[0],  ELEMENTS(g_aArgDumpTSS),    NULL,               0,          dbgcCmdDumpTSS,     "[tss|tss:ign|addr]",   "Dump the task state segment (TSS)." },
    425294    { "echo",       1,        ~0,       &g_aArgMultiStr[0], ELEMENTS(g_aArgMultiStr),   NULL,               0,          dbgcCmdEcho,        "<str1> [str2..[strN]]", "Displays the strings separated by one blank space and the last one followed by a newline." },
    426295    { "exit",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
     
    440309    { "stop",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdStop,        "",                     "Stop execution." },
    441310    { "unset",      1,        ~0,       &g_aArgMultiStr[0], ELEMENTS(g_aArgMultiStr),   NULL,               0,          dbgcCmdUnset,       "<var1> [var1..[varN]]", "Unsets (delete) one or more global variables." },
    442 };
    443 
    444 
    445 /** 'ba' arguments. */
    446 static const DBGCVARDESC    g_aArgBrkAcc[] =
    447 {
    448     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    449     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "access",       "The access type: x=execute, rw=read/write (alias r), w=write, i=not implemented." },
    450     {  1,           1,          DBGCVAR_CAT_NUMBER,     0,                              "size",         "The access size: 1, 2, 4, or 8. 'x' access requires 1, and 8 requires amd64 long mode." },
    451     {  1,           1,          DBGCVAR_CAT_GC_POINTER, 0,                              "address",      "The address." },
    452     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "passes",       "The number of passes before we trigger the breakpoint. (0 is default)" },
    453     {  0,           1,          DBGCVAR_CAT_NUMBER,     DBGCVD_FLAGS_DEP_PREV,          "max passes",   "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
    454     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "cmds",         "String of commands to be executed when the breakpoint is hit. Quote it!" },
    455 };
    456 
    457 
    458 /** 'bc', 'bd', 'be' arguments. */
    459 static const DBGCVARDESC    g_aArgBrks[] =
    460 {
    461     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    462     {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "#bp",          "Breakpoint number." },
    463     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "all",          "All breakpoints." },
    464 };
    465 
    466 
    467 /** 'bp' arguments. */
    468 static const DBGCVARDESC    g_aArgBrkSet[] =
    469 {
    470     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    471     {  1,           1,          DBGCVAR_CAT_GC_POINTER, 0,                              "address",      "The address." },
    472     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "passes",       "The number of passes before we trigger the breakpoint. (0 is default)" },
    473     {  0,           1,          DBGCVAR_CAT_NUMBER,     DBGCVD_FLAGS_DEP_PREV,          "max passes",   "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
    474     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "cmds",         "String of commands to be executed when the breakpoint is hit. Quote it!" },
    475 };
    476 
    477 
    478 /** 'd?' arguments. */
    479 static const DBGCVARDESC    g_aArgDumpMem[] =
    480 {
    481     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    482     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address where to start dumping memory." },
    483 };
    484 
    485 
    486 /** 'ln' arguments. */
    487 static const DBGCVARDESC    g_aArgListNear[] =
    488 {
    489     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    490     {  0,           ~0,         DBGCVAR_CAT_POINTER,    0,                              "address",      "Address of the symbol to look up." },
    491     {  0,           ~0,         DBGCVAR_CAT_SYMBOL,     0,                              "symbol",       "Symbol to lookup." },
    492 };
    493 
    494 /** 'ln' return. */
    495 static const DBGCVARDESC    g_RetListNear =
    496 {
    497        1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "The last resolved symbol/address with adjusted range."
    498 };
    499 
    500 
    501 /** 'ls' arguments. */
    502 static const DBGCVARDESC    g_aArgListSource[] =
    503 {
    504     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    505     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address where to start looking for source lines." },
    506 };
    507 
    508 
    509 /** 'm' argument. */
    510 static const DBGCVARDESC    g_aArgMemoryInfo[] =
    511 {
    512     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    513     {  1,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Pointer to obtain info about." },
    514 };
    515 
    516 
    517 /** 'r' arguments. */
    518 static const DBGCVARDESC    g_aArgReg[] =
    519 {
    520     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    521     {  0,           1,          DBGCVAR_CAT_SYMBOL,     0,                              "register",     "Register to show or set." },
    522     {  0,           1,     DBGCVAR_CAT_NUMBER_NO_RANGE, DBGCVD_FLAGS_DEP_PREV,          "value",        "New register value." },
    523 };
    524 
    525 
    526 /** 's' arguments. */
    527 static const DBGCVARDESC    g_aArgSearchMem[] =
    528 {
    529     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    530     {  1,           1,          DBGCVAR_CAT_GC_POINTER, 0,                              "range",        "Register to show or set." },
    531     {  1,           ~0,         DBGCVAR_CAT_ANY,        0,                              "pattern",      "Pattern to search for." },
    532 };
    533 
    534 
    535 /** 'u' arguments. */
    536 static const DBGCVARDESC    g_aArgUnassemble[] =
    537 {
    538     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    539     {  0,           1,          DBGCVAR_CAT_POINTER,    0,                              "address",      "Address where to start disassembling." },
    540 };
    541 
    542 
    543 /** Command descriptors for the CodeView / WinDbg emulation.
    544  * The emulation isn't attempting to be identical, only somewhat similar.
    545  */
    546 static const DBGCCMD    g_aCmdsCodeView[] =
    547 {
    548     /* pszCmd,      cArgsMin, cArgsMax, paArgDescs,         cArgDescs,                     pResultDesc,        fFlags,  pfnHandler          pszSyntax,          ....pszDescription */
    549     { "ba",         3,        6,        &g_aArgBrkAcc[0],   RT_ELEMENTS(g_aArgBrkAcc),     NULL,               0,       dbgcCmdBrkAccess,   "<access> <size> <address> [passes [max passes]] [cmds]",
    550                                                                                                                                                                     "Sets a data access breakpoint." },
    551     { "bc",         1,       ~0,        &g_aArgBrks[0],     RT_ELEMENTS(g_aArgBrks),       NULL,               0,       dbgcCmdBrkClear,    "all | <bp#> [bp# []]", "Enabled a set of breakpoints." },
    552     { "bd",         1,       ~0,        &g_aArgBrks[0],     RT_ELEMENTS(g_aArgBrks),       NULL,               0,       dbgcCmdBrkDisable,  "all | <bp#> [bp# []]", "Disables a set of breakpoints." },
    553     { "be",         1,       ~0,        &g_aArgBrks[0],     RT_ELEMENTS(g_aArgBrks),       NULL,               0,       dbgcCmdBrkEnable,   "all | <bp#> [bp# []]", "Enabled a set of breakpoints." },
    554     { "bl",         0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdBrkList,     "",                     "Lists all the breakpoints." },
    555     { "bp",         1,        4,        &g_aArgBrkSet[0],   RT_ELEMENTS(g_aArgBrkSet),     NULL,               0,       dbgcCmdBrkSet,      "<address> [passes [max passes]] [cmds]",
    556                                                                                                                                                                  "Sets a breakpoint (int 3)." },
    557     { "d",          0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory using last element size." },
    558     { "da",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory as ascii string." },
    559     { "db",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in bytes." },
    560     { "dd",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in double words." },
    561     { "dq",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in quad words." },
    562     { "dw",         0,        1,        &g_aArgDumpMem[0],  RT_ELEMENTS(g_aArgDumpMem),    NULL,               0,       dbgcCmdDumpMem,     "[addr]",               "Dump memory in words." },
    563     { "g",          0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdGo,          "",                     "Continue execution." },
    564     { "k",          0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdStack,       "",                     "Callstack." },
    565     { "kg",         0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdStack,       "",                     "Callstack - guest." },
    566     { "kh",         0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdStack,       "",                     "Callstack - hypervisor." },
    567     { "ln",         0,        ~0,       &g_aArgListNear[0], RT_ELEMENTS(g_aArgListNear),   &g_RetListNear,     0,       dbgcCmdListNear,    "[addr/sym [..]]",      "List symbols near to the address. Default address is CS:EIP." },
    568     { "ls",         0,        1,        &g_aArgListSource[0],RT_ELEMENTS(g_aArgListSource),NULL,               0,       dbgcCmdListSource,  "[addr]",               "Source." },
    569     { "m",          1,        1,        &g_aArgMemoryInfo[0],RT_ELEMENTS(g_aArgMemoryInfo),NULL,               0,       dbgcCmdMemoryInfo,  "<addr>",               "Display information about that piece of memory." },
    570     { "r",          0,        2,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),        NULL,               0,       dbgcCmdReg,         "[reg [newval]]",       "Show or set register(s) - active reg set." },
    571     { "rg",         0,        2,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),        NULL,               0,       dbgcCmdRegGuest,    "[reg [newval]]",       "Show or set register(s) - guest reg set." },
    572     { "rh",         0,        2,        &g_aArgReg[0],      RT_ELEMENTS(g_aArgReg),        NULL,               0,       dbgcCmdRegHyper,    "[reg [newval]]",       "Show or set register(s) - hypervisor reg set." },
    573     { "rt",         0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdRegTerse,    "",                     "Toggles terse / verbose register info." },
    574     //{ "s",          2,       ~0,        &g_aArgSearchMem[0],RT_ELEMENTS(g_aArgSearchMem),  NULL,               0,       dbgcCmdSearchMem,   "<range> <pattern>",    "Continue last search." },
    575     { "sa",         2,       ~0,        &g_aArgSearchMem[0],RT_ELEMENTS(g_aArgSearchMem),  NULL,               0,       dbgcCmdSearchMem,   "<range> <pattern>",    "Search memory for an ascii string." },
    576     { "sb",         2,       ~0,        &g_aArgSearchMem[0],RT_ELEMENTS(g_aArgSearchMem),  NULL,               0,       dbgcCmdSearchMem,   "<range> <pattern>",    "Search memory for one or more bytes." },
    577     { "sd",         2,       ~0,        &g_aArgSearchMem[0],RT_ELEMENTS(g_aArgSearchMem),  NULL,               0,       dbgcCmdSearchMem,   "<range> <pattern>",    "Search memory for one or more double words." },
    578     { "sq",         2,       ~0,        &g_aArgSearchMem[0],RT_ELEMENTS(g_aArgSearchMem),  NULL,               0,       dbgcCmdSearchMem,   "<range> <pattern>",    "Search memory for one or more quad words." },
    579     { "su",         2,       ~0,        &g_aArgSearchMem[0],RT_ELEMENTS(g_aArgSearchMem),  NULL,               0,       dbgcCmdSearchMem,   "<range> <pattern>",    "Search memory for an unicode string." },
    580     { "sw",         2,       ~0,        &g_aArgSearchMem[0],RT_ELEMENTS(g_aArgSearchMem),  NULL,               0,       dbgcCmdSearchMem,   "<range> <pattern>",    "Search memory for one or more words." },
    581     { "t",          0,        0,        NULL,               0,                             NULL,               0,       dbgcCmdTrace,       "",                     "Instruction trace (step into)." },
    582     { "u",          0,        1,        &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble),NULL,               0,       dbgcCmdUnassemble,  "[addr]",               "Unassemble." },
    583311};
    584312
     
    1013741
    1014742/**
    1015  * The 'go' command.
     743 * The 'stop' command.
    1016744 *
    1017745 * @returns VBox status.
     
    1022750 * @param   cArgs       Number of arguments in the array.
    1023751 */
    1024 static DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1025 {
    1026     /*
    1027      * Check if the VM is halted or not before trying to resume it.
    1028      */
    1029     if (!DBGFR3IsHalted(pVM))
    1030         pCmdHlp->pfnPrintf(pCmdHlp, NULL, "warning: The VM is already running...\n");
    1031     else
    1032     {
    1033         int rc = DBGFR3Resume(pVM);
    1034         if (VBOX_FAILURE(rc))
    1035             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Executing DBGFR3Resume().");
    1036     }
    1037 
    1038     NOREF(pCmd);
    1039     NOREF(paArgs);
    1040     NOREF(cArgs);
    1041     NOREF(pResult);
    1042     return 0;
    1043 }
    1044 
    1045 /**
    1046  * The 'stop' command.
    1047  *
    1048  * @returns VBox status.
    1049  * @param   pCmd        Pointer to the command descriptor (as registered).
    1050  * @param   pCmdHlp     Pointer to command helper functions.
    1051  * @param   pVM         Pointer to the current VM (if any).
    1052  * @param   paArgs      Pointer to (readonly) array of arguments.
    1053  * @param   cArgs       Number of arguments in the array.
    1054  */
    1055752static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1056753{
     
    1072769    NOREF(pCmd); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    1073770    return rc;
    1074 }
    1075 
    1076 
    1077 /**
    1078  * The 'ba' command.
    1079  *
    1080  * @returns VBox status.
    1081  * @param   pCmd        Pointer to the command descriptor (as registered).
    1082  * @param   pCmdHlp     Pointer to command helper functions.
    1083  * @param   pVM         Pointer to the current VM (if any).
    1084  * @param   paArgs      Pointer to (readonly) array of arguments.
    1085  * @param   cArgs       Number of arguments in the array.
    1086  */
    1087 static DECLCALLBACK(int) dbgcCmdBrkAccess(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR /*pResult*/)
    1088 {
    1089     /*
    1090      * Interpret access type.
    1091      */
    1092     if (    !strchr("xrwi", paArgs[0].u.pszString[0])
    1093         ||  paArgs[0].u.pszString[1])
    1094         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid access type '%s' for '%s'. Valid types are 'e', 'r', 'w' and 'i'.\n",
    1095                                   paArgs[0].u.pszString, pCmd->pszCmd);
    1096     uint8_t fType = 0;
    1097     switch (paArgs[0].u.pszString[0])
    1098     {
    1099         case 'x':  fType = X86_DR7_RW_EO; break;
    1100         case 'r':  fType = X86_DR7_RW_RW; break;
    1101         case 'w':  fType = X86_DR7_RW_WO; break;
    1102         case 'i':  fType = X86_DR7_RW_IO; break;
    1103     }
    1104 
    1105     /*
    1106      * Validate size.
    1107      */
    1108     if (fType == X86_DR7_RW_EO && paArgs[1].u.u64Number != 1)
    1109         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid access size %RX64 for '%s'. 'x' access type requires size 1!\n",
    1110                                   paArgs[1].u.u64Number, pCmd->pszCmd);
    1111     switch (paArgs[1].u.u64Number)
    1112     {
    1113         case 1:
    1114         case 2:
    1115         case 4:
    1116             break;
    1117         /*case 8: - later*/
    1118         default:
    1119             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid access size %RX64 for '%s'. 1, 2 or 4!\n",
    1120                                       paArgs[1].u.u64Number, pCmd->pszCmd);
    1121     }
    1122     uint8_t cb = (uint8_t)paArgs[1].u.u64Number;
    1123 
    1124     /*
    1125      * Convert the pointer to a DBGF address.
    1126      */
    1127     DBGFADDRESS Address;
    1128     int rc = pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, &paArgs[2], &Address);
    1129     if (VBOX_FAILURE(rc))
    1130         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Couldn't convert '%DV' to a DBGF address, rc=%Vrc.\n", &paArgs[2], rc);
    1131 
    1132     /*
    1133      * Pick out the optional arguments.
    1134      */
    1135     uint64_t iHitTrigger = 0;
    1136     uint64_t iHitDisable = ~0;
    1137     const char *pszCmds = NULL;
    1138     unsigned iArg = 3;
    1139     if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    1140     {
    1141         iHitTrigger = paArgs[iArg].u.u64Number;
    1142         iArg++;
    1143         if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    1144         {
    1145             iHitDisable = paArgs[iArg].u.u64Number;
    1146             iArg++;
    1147         }
    1148     }
    1149     if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_STRING)
    1150     {
    1151         pszCmds = paArgs[iArg].u.pszString;
    1152         iArg++;
    1153     }
    1154 
    1155     /*
    1156      * Try set the breakpoint.
    1157      */
    1158     RTUINT iBp;
    1159     rc = DBGFR3BpSetReg(pVM, &Address, iHitTrigger, iHitDisable, fType, cb, &iBp);
    1160     if (VBOX_SUCCESS(rc))
    1161     {
    1162         PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1163         rc = dbgcBpAdd(pDbgc, iBp, pszCmds);
    1164         if (VBOX_SUCCESS(rc))
    1165             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Set access breakpoint %u at %VGv\n", iBp, Address.FlatPtr);
    1166         if (rc == VERR_DBGC_BP_EXISTS)
    1167         {
    1168             rc = dbgcBpUpdate(pDbgc, iBp, pszCmds);
    1169             if (VBOX_SUCCESS(rc))
    1170                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Updated access breakpoint %u at %VGv\n", iBp, Address.FlatPtr);
    1171         }
    1172         int rc2 = DBGFR3BpClear(pDbgc->pVM, iBp);
    1173         AssertRC(rc2);
    1174     }
    1175     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Failed to set access breakpoint at %VGv, rc=%Vrc.\n", Address.FlatPtr, rc);
    1176 }
    1177 
    1178 
    1179 /**
    1180  * The 'bc' command.
    1181  *
    1182  * @returns VBox status.
    1183  * @param   pCmd        Pointer to the command descriptor (as registered).
    1184  * @param   pCmdHlp     Pointer to command helper functions.
    1185  * @param   pVM         Pointer to the current VM (if any).
    1186  * @param   paArgs      Pointer to (readonly) array of arguments.
    1187  * @param   cArgs       Number of arguments in the array.
    1188  */
    1189 static DECLCALLBACK(int) dbgcCmdBrkClear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR /*pResult*/)
    1190 {
    1191     /*
    1192      * Enumerate the arguments.
    1193      */
    1194     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1195     int     rc = VINF_SUCCESS;
    1196     for (unsigned iArg = 0; iArg < cArgs && VBOX_SUCCESS(rc); iArg++)
    1197     {
    1198         if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
    1199         {
    1200             /* one */
    1201             RTUINT iBp = (RTUINT)paArgs[iArg].u.u64Number;
    1202             if (iBp != paArgs[iArg].u.u64Number)
    1203             {
    1204                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Breakpoint id %RX64 is too large!\n", paArgs[iArg].u.u64Number);
    1205                 break;
    1206             }
    1207             int rc2 = DBGFR3BpClear(pVM, iBp);
    1208             if (VBOX_FAILURE(rc2))
    1209                 rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc2, "DBGFR3BpClear failed for breakpoint %u!\n", iBp);
    1210             if (VBOX_SUCCESS(rc2) || rc2 == VERR_DBGF_BP_NOT_FOUND)
    1211                 dbgcBpDelete(pDbgc, iBp);
    1212         }
    1213         else if (!strcmp(paArgs[iArg].u.pszString, "all"))
    1214         {
    1215             /* all */
    1216             PDBGCBP pBp = pDbgc->pFirstBp;
    1217             while (pBp)
    1218             {
    1219                 RTUINT iBp = pBp->iBp;
    1220                 pBp = pBp->pNext;
    1221 
    1222                 int rc2 = DBGFR3BpClear(pVM, iBp);
    1223                 if (VBOX_FAILURE(rc2))
    1224                     rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc2, "DBGFR3BpClear failed for breakpoint %u!\n", iBp);
    1225                 if (VBOX_SUCCESS(rc2) || rc2 == VERR_DBGF_BP_NOT_FOUND)
    1226                     dbgcBpDelete(pDbgc, iBp);
    1227             }
    1228         }
    1229         else
    1230         {
    1231             /* invalid parameter */
    1232             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid argument '%s' to '%s'!\n", paArgs[iArg].u.pszString, pCmd->pszCmd);
    1233             break;
    1234         }
    1235     }
    1236     return rc;
    1237 }
    1238 
    1239 
    1240 /**
    1241  * The 'bd' command.
    1242  *
    1243  * @returns VBox status.
    1244  * @param   pCmd        Pointer to the command descriptor (as registered).
    1245  * @param   pCmdHlp     Pointer to command helper functions.
    1246  * @param   pVM         Pointer to the current VM (if any).
    1247  * @param   paArgs      Pointer to (readonly) array of arguments.
    1248  * @param   cArgs       Number of arguments in the array.
    1249  */
    1250 static DECLCALLBACK(int) dbgcCmdBrkDisable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR /*pResult*/)
    1251 {
    1252     /*
    1253      * Enumerate the arguments.
    1254      */
    1255     int rc = VINF_SUCCESS;
    1256     for (unsigned iArg = 0; iArg < cArgs && VBOX_SUCCESS(rc); iArg++)
    1257     {
    1258         if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
    1259         {
    1260             /* one */
    1261             RTUINT iBp = (RTUINT)paArgs[iArg].u.u64Number;
    1262             if (iBp != paArgs[iArg].u.u64Number)
    1263             {
    1264                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Breakpoint id %RX64 is too large!\n", paArgs[iArg].u.u64Number);
    1265                 break;
    1266             }
    1267             rc = DBGFR3BpDisable(pVM, iBp);
    1268             if (VBOX_FAILURE(rc))
    1269                 rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3BpDisable failed for breakpoint %u!\n", iBp);
    1270         }
    1271         else if (!strcmp(paArgs[iArg].u.pszString, "all"))
    1272         {
    1273             /* all */
    1274             PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1275             for (PDBGCBP pBp = pDbgc->pFirstBp; pBp; pBp = pBp->pNext)
    1276             {
    1277                 rc = DBGFR3BpDisable(pVM, pBp->iBp);
    1278                 if (VBOX_FAILURE(rc))
    1279                     rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3BpDisable failed for breakpoint %u!\n", pBp->iBp);
    1280             }
    1281         }
    1282         else
    1283         {
    1284             /* invalid parameter */
    1285             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid argument '%s' to '%s'!\n", paArgs[iArg].u.pszString, pCmd->pszCmd);
    1286             break;
    1287         }
    1288     }
    1289     return rc;
    1290 }
    1291 
    1292 
    1293 /**
    1294  * The 'be' command.
    1295  *
    1296  * @returns VBox status.
    1297  * @param   pCmd        Pointer to the command descriptor (as registered).
    1298  * @param   pCmdHlp     Pointer to command helper functions.
    1299  * @param   pVM         Pointer to the current VM (if any).
    1300  * @param   paArgs      Pointer to (readonly) array of arguments.
    1301  * @param   cArgs       Number of arguments in the array.
    1302  */
    1303 static DECLCALLBACK(int) dbgcCmdBrkEnable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR /*pResult*/)
    1304 {
    1305     /*
    1306      * Enumerate the arguments.
    1307      */
    1308     int rc = VINF_SUCCESS;
    1309     for (unsigned iArg = 0; iArg < cArgs && VBOX_SUCCESS(rc); iArg++)
    1310     {
    1311         if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
    1312         {
    1313             /* one */
    1314             RTUINT iBp = (RTUINT)paArgs[iArg].u.u64Number;
    1315             if (iBp != paArgs[iArg].u.u64Number)
    1316             {
    1317                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Breakpoint id %RX64 is too large!\n", paArgs[iArg].u.u64Number);
    1318                 break;
    1319             }
    1320             rc = DBGFR3BpEnable(pVM, iBp);
    1321             if (VBOX_FAILURE(rc))
    1322                 rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3BpEnable failed for breakpoint %u!\n", iBp);
    1323         }
    1324         else if (!strcmp(paArgs[iArg].u.pszString, "all"))
    1325         {
    1326             /* all */
    1327             PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1328             for (PDBGCBP pBp = pDbgc->pFirstBp; pBp; pBp = pBp->pNext)
    1329             {
    1330                 rc = DBGFR3BpEnable(pVM, pBp->iBp);
    1331                 if (VBOX_FAILURE(rc))
    1332                     rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3BpEnable failed for breakpoint %u!\n", pBp->iBp);
    1333             }
    1334         }
    1335         else
    1336         {
    1337             /* invalid parameter */
    1338             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid argument '%s' to '%s'!\n", paArgs[iArg].u.pszString, pCmd->pszCmd);
    1339             break;
    1340         }
    1341     }
    1342     return rc;
    1343 }
    1344 
    1345 
    1346 /**
    1347  * Breakpoint enumeration callback function.
    1348  *
    1349  * @returns VBox status code. Any failure will stop the enumeration.
    1350  * @param   pVM         The VM handle.
    1351  * @param   pvUser      The user argument.
    1352  * @param   pBp         Pointer to the breakpoint information. (readonly)
    1353  */
    1354 static DECLCALLBACK(int) dbgcEnumBreakpointsCallback(PVM pVM, void *pvUser, PCDBGFBP pBp)
    1355 {
    1356     PDBGC pDbgc = (PDBGC)pvUser;
    1357     PDBGCBP pDbgcBp = dbgcBpGet(pDbgc, pBp->iBp);
    1358 
    1359     /*
    1360      * BP type and size.
    1361      */
    1362     char chType;
    1363     char cb = 1;
    1364     switch (pBp->enmType)
    1365     {
    1366         case DBGFBPTYPE_INT3:
    1367             chType = 'p';
    1368             break;
    1369         case DBGFBPTYPE_REG:
    1370             switch (pBp->u.Reg.fType)
    1371             {
    1372                 case X86_DR7_RW_EO: chType = 'x'; break;
    1373                 case X86_DR7_RW_WO: chType = 'w'; break;
    1374                 case X86_DR7_RW_IO: chType = 'i'; break;
    1375                 case X86_DR7_RW_RW: chType = 'r'; break;
    1376                 default:            chType = '?'; break;
    1377 
    1378             }
    1379             cb = pBp->u.Reg.cb;
    1380             break;
    1381         case DBGFBPTYPE_REM:
    1382             chType = 'r';
    1383             break;
    1384         default:
    1385             chType = '?';
    1386             break;
    1387     }
    1388 
    1389     pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "%2u %c %d %c %VGv %04RX64 (%04RX64 to ",
    1390                             pBp->iBp, pBp->fEnabled ? 'e' : 'd', cb, chType,
    1391                             pBp->GCPtr, pBp->cHits, pBp->iHitTrigger);
    1392     if (pBp->iHitDisable == ~(uint64_t)0)
    1393         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "~0)  ");
    1394     else
    1395         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "%04RX64)");
    1396 
    1397     /*
    1398      * Try resolve the address.
    1399      */
    1400     DBGFSYMBOL Sym;
    1401     RTGCINTPTR off;
    1402     int rc = DBGFR3SymbolByAddr(pVM, pBp->GCPtr, &off, &Sym);
    1403     if (VBOX_SUCCESS(rc))
    1404     {
    1405         if (!off)
    1406             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "%s", Sym.szName);
    1407         else if (off > 0)
    1408             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "%s+%VGv", Sym.szName, off);
    1409         else
    1410             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "%s+%VGv", Sym.szName, -off);
    1411     }
    1412 
    1413     /*
    1414      * The commands.
    1415      */
    1416     if (pDbgcBp)
    1417     {
    1418         if (pDbgcBp->cchCmd)
    1419             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n  cmds: '%s'\n",
    1420                                     pDbgcBp->szCmd);
    1421         else
    1422             pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\n");
    1423     }
    1424     else
    1425         pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, " [unknown bp]\n");
    1426 
    1427     return VINF_SUCCESS;
    1428 }
    1429 
    1430 
    1431 /**
    1432  * The 'bl' command.
    1433  *
    1434  * @returns VBox status.
    1435  * @param   pCmd        Pointer to the command descriptor (as registered).
    1436  * @param   pCmdHlp     Pointer to command helper functions.
    1437  * @param   pVM         Pointer to the current VM (if any).
    1438  * @param   paArgs      Pointer to (readonly) array of arguments.
    1439  * @param   cArgs       Number of arguments in the array.
    1440  */
    1441 static DECLCALLBACK(int) dbgcCmdBrkList(PCDBGCCMD /*pCmd*/, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR /*paArgs*/, unsigned /*cArgs*/, PDBGCVAR /*pResult*/)
    1442 {
    1443     PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1444 
    1445     /*
    1446      * Enumerate the breakpoints.
    1447      */
    1448     int rc = DBGFR3BpEnum(pVM, dbgcEnumBreakpointsCallback, pDbgc);
    1449     if (VBOX_FAILURE(rc))
    1450         return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3BpEnum failed.\n");
    1451     return rc;
    1452 }
    1453 
    1454 
    1455 /**
    1456  * The 'bp' command.
    1457  *
    1458  * @returns VBox status.
    1459  * @param   pCmd        Pointer to the command descriptor (as registered).
    1460  * @param   pCmdHlp     Pointer to command helper functions.
    1461  * @param   pVM         Pointer to the current VM (if any).
    1462  * @param   paArgs      Pointer to (readonly) array of arguments.
    1463  * @param   cArgs       Number of arguments in the array.
    1464  */
    1465 static DECLCALLBACK(int) dbgcCmdBrkSet(PCDBGCCMD /*pCmd*/, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR /*pResult*/)
    1466 {
    1467     /*
    1468      * Convert the pointer to a DBGF address.
    1469      */
    1470     DBGFADDRESS Address;
    1471     int rc = pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, &paArgs[0], &Address);
    1472     if (VBOX_FAILURE(rc))
    1473         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Couldn't convert '%DV' to a DBGF address, rc=%Vrc.\n", &paArgs[0], rc);
    1474 
    1475     /*
    1476      * Pick out the optional arguments.
    1477      */
    1478     uint64_t iHitTrigger = 0;
    1479     uint64_t iHitDisable = ~0;
    1480     const char *pszCmds = NULL;
    1481     unsigned iArg = 1;
    1482     if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    1483     {
    1484         iHitTrigger = paArgs[iArg].u.u64Number;
    1485         iArg++;
    1486         if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    1487         {
    1488             iHitDisable = paArgs[iArg].u.u64Number;
    1489             iArg++;
    1490         }
    1491     }
    1492     if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_STRING)
    1493     {
    1494         pszCmds = paArgs[iArg].u.pszString;
    1495         iArg++;
    1496     }
    1497 
    1498     /*
    1499      * Try set the breakpoint.
    1500      */
    1501     RTUINT iBp;
    1502     rc = DBGFR3BpSet(pVM, &Address, iHitTrigger, iHitDisable, &iBp);
    1503     if (VBOX_SUCCESS(rc))
    1504     {
    1505         PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1506         rc = dbgcBpAdd(pDbgc, iBp, pszCmds);
    1507         if (VBOX_SUCCESS(rc))
    1508             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Set breakpoint %u at %VGv\n", iBp, Address.FlatPtr);
    1509         if (rc == VERR_DBGC_BP_EXISTS)
    1510         {
    1511             rc = dbgcBpUpdate(pDbgc, iBp, pszCmds);
    1512             if (VBOX_SUCCESS(rc))
    1513                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Updated breakpoint %u at %VGv\n", iBp, Address.FlatPtr);
    1514         }
    1515         int rc2 = DBGFR3BpClear(pDbgc->pVM, iBp);
    1516         AssertRC(rc2);
    1517     }
    1518     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Failed to set breakpoint at %VGv, rc=%Vrc.\n", Address.FlatPtr, rc);
    1519 }
    1520 
    1521 
    1522 /**
    1523  * The 'br' command.
    1524  *
    1525  * @returns VBox status.
    1526  * @param   pCmd        Pointer to the command descriptor (as registered).
    1527  * @param   pCmdHlp     Pointer to command helper functions.
    1528  * @param   pVM         Pointer to the current VM (if any).
    1529  * @param   paArgs      Pointer to (readonly) array of arguments.
    1530  * @param   cArgs       Number of arguments in the array.
    1531  */
    1532 static DECLCALLBACK(int) dbgcCmdBrkREM(PCDBGCCMD /*pCmd*/, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR /*pResult*/)
    1533 {
    1534     /*
    1535      * Convert the pointer to a DBGF address.
    1536      */
    1537     DBGFADDRESS Address;
    1538     int rc = pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, &paArgs[0], &Address);
    1539     if (VBOX_FAILURE(rc))
    1540         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Couldn't convert '%DV' to a DBGF address, rc=%Vrc.\n", &paArgs[0], rc);
    1541 
    1542     /*
    1543      * Pick out the optional arguments.
    1544      */
    1545     uint64_t iHitTrigger = 0;
    1546     uint64_t iHitDisable = ~0;
    1547     const char *pszCmds = NULL;
    1548     unsigned iArg = 1;
    1549     if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    1550     {
    1551         iHitTrigger = paArgs[iArg].u.u64Number;
    1552         iArg++;
    1553         if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    1554         {
    1555             iHitDisable = paArgs[iArg].u.u64Number;
    1556             iArg++;
    1557         }
    1558     }
    1559     if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_STRING)
    1560     {
    1561         pszCmds = paArgs[iArg].u.pszString;
    1562         iArg++;
    1563     }
    1564 
    1565     /*
    1566      * Try set the breakpoint.
    1567      */
    1568     RTUINT iBp;
    1569     rc = DBGFR3BpSetREM(pVM, &Address, iHitTrigger, iHitDisable, &iBp);
    1570     if (VBOX_SUCCESS(rc))
    1571     {
    1572         PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1573         rc = dbgcBpAdd(pDbgc, iBp, pszCmds);
    1574         if (VBOX_SUCCESS(rc))
    1575             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Set REM breakpoint %u at %VGv\n", iBp, Address.FlatPtr);
    1576         if (rc == VERR_DBGC_BP_EXISTS)
    1577         {
    1578             rc = dbgcBpUpdate(pDbgc, iBp, pszCmds);
    1579             if (VBOX_SUCCESS(rc))
    1580                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Updated REM breakpoint %u at %VGv\n", iBp, Address.FlatPtr);
    1581         }
    1582         int rc2 = DBGFR3BpClear(pDbgc->pVM, iBp);
    1583         AssertRC(rc2);
    1584     }
    1585     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Failed to set REM breakpoint at %VGv, rc=%Vrc.\n", Address.FlatPtr, rc);
    1586 }
    1587 
    1588 
    1589 /**
    1590  * The 'u' command.
    1591  *
    1592  * @returns VBox status.
    1593  * @param   pCmd        Pointer to the command descriptor (as registered).
    1594  * @param   pCmdHlp     Pointer to command helper functions.
    1595  * @param   pVM         Pointer to the current VM (if any).
    1596  * @param   paArgs      Pointer to (readonly) array of arguments.
    1597  * @param   cArgs       Number of arguments in the array.
    1598  */
    1599 static DECLCALLBACK(int) dbgcCmdUnassemble(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1600 {
    1601     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1602 
    1603     /*
    1604      * Validate input.
    1605      */
    1606     if (    cArgs > 1
    1607         ||  (cArgs == 1 && !DBGCVAR_ISPOINTER(paArgs[0].enmType)))
    1608         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: The parser doesn't do its job properly yet.. It might help to use the '%%' operator.\n");
    1609     if (!pVM && !cArgs && !DBGCVAR_ISPOINTER(pDbgc->DisasmPos.enmType))
    1610         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Don't know where to start disassembling...\n");
    1611     if (!pVM && cArgs && DBGCVAR_ISGCPOINTER(paArgs[0].enmType))
    1612         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: GC address but no VM.\n");
    1613 
    1614     /*
    1615      * Find address.
    1616      */
    1617     unsigned fFlags = DBGF_DISAS_FLAGS_NO_ADDRESS;
    1618     if (!cArgs)
    1619     {
    1620         if (!DBGCVAR_ISPOINTER(pDbgc->DisasmPos.enmType))
    1621         {
    1622             pDbgc->DisasmPos.enmType     = DBGCVAR_TYPE_GC_FAR;
    1623             pDbgc->SourcePos.u.GCFar.off = pDbgc->fRegCtxGuest ? CPUMGetGuestEIP(pVM) : CPUMGetHyperEIP(pVM);
    1624             pDbgc->SourcePos.u.GCFar.sel = pDbgc->fRegCtxGuest ? CPUMGetGuestCS(pVM)  : CPUMGetHyperCS(pVM);
    1625             if (pDbgc->fRegCtxGuest)
    1626                 fFlags |= DBGF_DISAS_FLAGS_CURRENT_GUEST;
    1627             else
    1628                 fFlags |= DBGF_DISAS_FLAGS_CURRENT_HYPER;
    1629         }
    1630         pDbgc->DisasmPos.enmRangeType = DBGCVAR_RANGE_NONE;
    1631     }
    1632     else
    1633         pDbgc->DisasmPos = paArgs[0];
    1634 
    1635     /*
    1636      * Range.
    1637      */
    1638     switch (pDbgc->DisasmPos.enmRangeType)
    1639     {
    1640         case DBGCVAR_RANGE_NONE:
    1641             pDbgc->DisasmPos.enmRangeType = DBGCVAR_RANGE_ELEMENTS;
    1642             pDbgc->DisasmPos.u64Range     = 10;
    1643             break;
    1644 
    1645         case DBGCVAR_RANGE_ELEMENTS:
    1646             if (pDbgc->DisasmPos.u64Range > 2048)
    1647                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Too many lines requested. Max is 2048 lines.\n");
    1648             break;
    1649 
    1650         case DBGCVAR_RANGE_BYTES:
    1651             if (pDbgc->DisasmPos.u64Range > 65536)
    1652                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The requested range is too big. Max is 64KB.\n");
    1653             break;
    1654 
    1655         default:
    1656             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: Unknown range type %d.\n", pDbgc->DisasmPos.enmRangeType);
    1657     }
    1658 
    1659     /*
    1660      * Convert physical and host addresses to guest addresses.
    1661      */
    1662     int rc;
    1663     switch (pDbgc->DisasmPos.enmType)
    1664     {
    1665         case DBGCVAR_TYPE_GC_FLAT:
    1666         case DBGCVAR_TYPE_GC_FAR:
    1667             break;
    1668         case DBGCVAR_TYPE_GC_PHYS:
    1669         case DBGCVAR_TYPE_HC_FLAT:
    1670         case DBGCVAR_TYPE_HC_PHYS:
    1671         case DBGCVAR_TYPE_HC_FAR:
    1672         {
    1673             DBGCVAR VarTmp;
    1674             rc = pCmdHlp->pfnEval(pCmdHlp, &VarTmp, "%%(%Dv)", &pDbgc->DisasmPos);
    1675             if (VBOX_FAILURE(rc))
    1676                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: failed to evaluate '%%(%Dv)' -> %Vrc .\n", pDbgc->DisasmPos, rc);
    1677             pDbgc->DisasmPos = VarTmp;
    1678             break;
    1679         }
    1680         default: AssertFailed(); break;
    1681     }
    1682 
    1683     /*
    1684      * Print address.
    1685      * todo: Change to list near.
    1686      */
    1687 #if 0
    1688     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%DV:\n", &pDbgc->DisasmPos);
    1689     if (VBOX_FAILURE(rc))
    1690         return rc;
    1691 #endif
    1692 
    1693     /*
    1694      * Do the disassembling.
    1695      */
    1696     unsigned    cTries = 32;
    1697     int         iRangeLeft = (int)pDbgc->DisasmPos.u64Range;
    1698     if (iRangeLeft == 0)                /* klugde for 'r'. */
    1699         iRangeLeft = -1;
    1700     for (;;)
    1701     {
    1702         /*
    1703          * Disassemble the instruction.
    1704          */
    1705         char        szDis[256];
    1706         uint32_t    cbInstr = 1;
    1707         if (pDbgc->DisasmPos.enmType == DBGCVAR_TYPE_GC_FLAT)
    1708             rc = DBGFR3DisasInstrEx(pVM, DBGF_SEL_FLAT, pDbgc->DisasmPos.u.GCFlat, fFlags, &szDis[0], sizeof(szDis), &cbInstr);
    1709         else
    1710             rc = DBGFR3DisasInstrEx(pVM, pDbgc->DisasmPos.u.GCFar.sel, pDbgc->DisasmPos.u.GCFar.off, fFlags, &szDis[0], sizeof(szDis), &cbInstr);
    1711         if (VBOX_SUCCESS(rc))
    1712         {
    1713             /* print it */
    1714             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%-16DV %s\n", &pDbgc->DisasmPos, &szDis[0]);
    1715             if (VBOX_FAILURE(rc))
    1716                 return rc;
    1717         }
    1718         else
    1719         {
    1720             /* bitch. */
    1721             int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Failed to disassemble instruction, skipping one byte.\n");
    1722             if (VBOX_FAILURE(rc))
    1723                 return rc;
    1724             if (cTries-- > 0)
    1725                 return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Too many disassembly failures. Giving up.\n");
    1726             cbInstr = 1;
    1727         }
    1728 
    1729         /* advance */
    1730         if (iRangeLeft < 0)             /* 'r' */
    1731             break;
    1732         if (pDbgc->DisasmPos.enmRangeType == DBGCVAR_RANGE_ELEMENTS)
    1733             iRangeLeft--;
    1734         else
    1735             iRangeLeft -= cbInstr;
    1736         rc = pCmdHlp->pfnEval(pCmdHlp, &pDbgc->DisasmPos, "(%Dv) + %x", &pDbgc->DisasmPos, cbInstr);
    1737         if (VBOX_FAILURE(rc))
    1738             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Expression: (%Dv) + %x\n", &pDbgc->DisasmPos, cbInstr);
    1739         if (iRangeLeft <= 0)
    1740             break;
    1741         fFlags &= ~(DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_CURRENT_HYPER);
    1742     }
    1743 
    1744     NOREF(pCmd); NOREF(pResult);
    1745     return 0;
    1746 }
    1747 
    1748 
    1749 /**
    1750  * The 'ls' command.
    1751  *
    1752  * @returns VBox status.
    1753  * @param   pCmd        Pointer to the command descriptor (as registered).
    1754  * @param   pCmdHlp     Pointer to command helper functions.
    1755  * @param   pVM         Pointer to the current VM (if any).
    1756  * @param   paArgs      Pointer to (readonly) array of arguments.
    1757  * @param   cArgs       Number of arguments in the array.
    1758  */
    1759 static DECLCALLBACK(int) dbgcCmdListSource(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1760 {
    1761     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1762 
    1763     /*
    1764      * Validate input.
    1765      */
    1766     if (    cArgs > 1
    1767         ||  (cArgs == 1 && !DBGCVAR_ISPOINTER(paArgs[0].enmType)))
    1768         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: The parser doesn't do its job properly yet.. It might help to use the '%%' operator.\n");
    1769     if (!pVM && !cArgs && !DBGCVAR_ISPOINTER(pDbgc->SourcePos.enmType))
    1770         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Don't know where to start disassembling...\n");
    1771     if (!pVM && cArgs && DBGCVAR_ISGCPOINTER(paArgs[0].enmType))
    1772         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: GC address but no VM.\n");
    1773 
    1774     /*
    1775      * Find address.
    1776      */
    1777     if (!cArgs)
    1778     {
    1779         if (!DBGCVAR_ISPOINTER(pDbgc->SourcePos.enmType))
    1780         {
    1781             pDbgc->SourcePos.enmType     = DBGCVAR_TYPE_GC_FAR;
    1782             pDbgc->SourcePos.u.GCFar.off = pDbgc->fRegCtxGuest ? CPUMGetGuestEIP(pVM) : CPUMGetHyperEIP(pVM);
    1783             pDbgc->SourcePos.u.GCFar.sel = pDbgc->fRegCtxGuest ? CPUMGetGuestCS(pVM)  : CPUMGetHyperCS(pVM);
    1784         }
    1785         pDbgc->SourcePos.enmRangeType = DBGCVAR_RANGE_NONE;
    1786     }
    1787     else
    1788         pDbgc->SourcePos = paArgs[0];
    1789 
    1790     /*
    1791      * Ensure the the source address is flat GC.
    1792      */
    1793     switch (pDbgc->SourcePos.enmType)
    1794     {
    1795         case DBGCVAR_TYPE_GC_FLAT:
    1796             break;
    1797         case DBGCVAR_TYPE_GC_PHYS:
    1798         case DBGCVAR_TYPE_GC_FAR:
    1799         case DBGCVAR_TYPE_HC_FLAT:
    1800         case DBGCVAR_TYPE_HC_PHYS:
    1801         case DBGCVAR_TYPE_HC_FAR:
    1802         {
    1803             int rc = pCmdHlp->pfnEval(pCmdHlp, &pDbgc->SourcePos, "%%(%Dv)", &pDbgc->SourcePos);
    1804             if (VBOX_FAILURE(rc))
    1805                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid address or address type. (rc=%d)\n", rc);
    1806             break;
    1807         }
    1808         default: AssertFailed(); break;
    1809     }
    1810 
    1811     /*
    1812      * Range.
    1813      */
    1814     switch (pDbgc->SourcePos.enmRangeType)
    1815     {
    1816         case DBGCVAR_RANGE_NONE:
    1817             pDbgc->SourcePos.enmRangeType = DBGCVAR_RANGE_ELEMENTS;
    1818             pDbgc->SourcePos.u64Range     = 10;
    1819             break;
    1820 
    1821         case DBGCVAR_RANGE_ELEMENTS:
    1822             if (pDbgc->SourcePos.u64Range > 2048)
    1823                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Too many lines requested. Max is 2048 lines.\n");
    1824             break;
    1825 
    1826         case DBGCVAR_RANGE_BYTES:
    1827             if (pDbgc->SourcePos.u64Range > 65536)
    1828                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The requested range is too big. Max is 64KB.\n");
    1829             break;
    1830 
    1831         default:
    1832             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: Unknown range type %d.\n", pDbgc->SourcePos.enmRangeType);
    1833     }
    1834 
    1835     /*
    1836      * Do the disassembling.
    1837      */
    1838     bool        fFirst = 1;
    1839     DBGFLINE    LinePrev = { 0, 0, "" };
    1840     int         iRangeLeft = (int)pDbgc->SourcePos.u64Range;
    1841     if (iRangeLeft == 0)                /* klugde for 'r'. */
    1842         iRangeLeft = -1;
    1843     for (;;)
    1844     {
    1845         /*
    1846          * Get line info.
    1847          */
    1848         DBGFLINE    Line;
    1849         RTGCINTPTR  off;
    1850         int rc = DBGFR3LineByAddr(pVM, pDbgc->SourcePos.u.GCFlat, &off, &Line);
    1851         if (VBOX_FAILURE(rc))
    1852             return VINF_SUCCESS;
    1853 
    1854         unsigned cLines = 0;
    1855         if (memcmp(&Line, &LinePrev, sizeof(Line)))
    1856         {
    1857             /*
    1858              * Print filenamename
    1859              */
    1860             if (!fFirst && strcmp(Line.szFilename, LinePrev.szFilename))
    1861                 fFirst = true;
    1862             if (fFirst)
    1863             {
    1864                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "[%s @ %d]\n", Line.szFilename, Line.uLineNo);
    1865                 if (VBOX_FAILURE(rc))
    1866                     return rc;
    1867             }
    1868 
    1869             /*
    1870              * Try open the file and read the line.
    1871              */
    1872             FILE *phFile = fopen(Line.szFilename, "r");
    1873             if (phFile)
    1874             {
    1875                 /* Skip ahead to the desired line. */
    1876                 char szLine[4096];
    1877                 unsigned cBefore = fFirst ? RT_MIN(2, Line.uLineNo - 1) : Line.uLineNo - LinePrev.uLineNo - 1;
    1878                 if (cBefore > 7)
    1879                     cBefore = 0;
    1880                 unsigned cLeft = Line.uLineNo - cBefore;
    1881                 while (cLeft > 0)
    1882                 {
    1883                     szLine[0] = '\0';
    1884                     if (!fgets(szLine, sizeof(szLine), phFile))
    1885                         break;
    1886                     cLeft--;
    1887                 }
    1888                 if (!cLeft)
    1889                 {
    1890                     /* print the before lines */
    1891                     for (;;)
    1892                     {
    1893                         size_t cch = strlen(szLine);
    1894                         while (cch > 0 && (szLine[cch - 1] == '\r' ||  szLine[cch - 1] == '\n' || isspace(szLine[cch - 1])) )
    1895                             szLine[--cch] = '\0';
    1896                         if (cBefore-- <= 0)
    1897                             break;
    1898 
    1899                         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "         %4d: %s\n", Line.uLineNo - cBefore - 1, szLine);
    1900                         szLine[0] = '\0';
    1901                         fgets(szLine, sizeof(szLine), phFile);
    1902                         cLines++;
    1903                     }
    1904                     /* print the actual line */
    1905                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%08llx %4d: %s\n", Line.Address, Line.uLineNo, szLine);
    1906                 }
    1907                 fclose(phFile);
    1908                 if (VBOX_FAILURE(rc))
    1909                     return rc;
    1910                 fFirst = false;
    1911             }
    1912             else
    1913                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Warning: couldn't open source file '%s'\n", Line.szFilename);
    1914 
    1915             LinePrev = Line;
    1916         }
    1917 
    1918 
    1919         /*
    1920          * Advance
    1921          */
    1922         if (iRangeLeft < 0)             /* 'r' */
    1923             break;
    1924         if (pDbgc->SourcePos.enmRangeType == DBGCVAR_RANGE_ELEMENTS)
    1925             iRangeLeft -= cLines;
    1926         else
    1927             iRangeLeft -= 1;
    1928         rc = pCmdHlp->pfnEval(pCmdHlp, &pDbgc->SourcePos, "(%Dv) + %x", &pDbgc->SourcePos, 1);
    1929         if (VBOX_FAILURE(rc))
    1930             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Expression: (%Dv) + %x\n", &pDbgc->SourcePos, 1);
    1931         if (iRangeLeft <= 0)
    1932             break;
    1933     }
    1934 
    1935     NOREF(pCmd); NOREF(pResult);
    1936     return 0;
    1937 }
    1938 
    1939 
    1940 /**
    1941  * The 'r' command.
    1942  *
    1943  * @returns VBox status.
    1944  * @param   pCmd        Pointer to the command descriptor (as registered).
    1945  * @param   pCmdHlp     Pointer to command helper functions.
    1946  * @param   pVM         Pointer to the current VM (if any).
    1947  * @param   paArgs      Pointer to (readonly) array of arguments.
    1948  * @param   cArgs       Number of arguments in the array.
    1949  */
    1950 static DECLCALLBACK(int) dbgcCmdReg(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1951 {
    1952     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1953 
    1954     if (pDbgc->fRegCtxGuest)
    1955         return dbgcCmdRegGuest(pCmd, pCmdHlp, pVM, paArgs, cArgs, pResult);
    1956     else
    1957         return dbgcCmdRegHyper(pCmd, pCmdHlp, pVM, paArgs, cArgs, pResult);
    1958 }
    1959 
    1960 
    1961 /**
    1962  * Common worker for the dbgcCmdReg*() commands.
    1963  *
    1964  * @returns VBox status.
    1965  * @param   pCmd        Pointer to the command descriptor (as registered).
    1966  * @param   pCmdHlp     Pointer to command helper functions.
    1967  * @param   pVM         Pointer to the current VM (if any).
    1968  * @param   paArgs      Pointer to (readonly) array of arguments.
    1969  * @param   cArgs       Number of arguments in the array.
    1970  * @param   pszPrefix   The symbol prefix.
    1971  */
    1972 static DECLCALLBACK(int) dbgcCmdRegCommon(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult, const char *pszPrefix)
    1973 {
    1974     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1975 
    1976     /*
    1977      * cArgs == 0: Show all
    1978      */
    1979     if (cArgs == 0)
    1980     {
    1981         /*
    1982          * Get register context.
    1983          */
    1984         int             rc;
    1985         PCPUMCTX        pCtx;
    1986         PCCPUMCTXCORE   pCtxCore;
    1987         if (!*pszPrefix)
    1988         {
    1989             rc = CPUMQueryGuestCtxPtr(pVM, &pCtx);
    1990             pCtxCore = CPUMGetGuestCtxCore(pVM);
    1991         }
    1992         else
    1993         {
    1994             rc = CPUMQueryHyperCtxPtr(pVM, &pCtx);
    1995             pCtxCore = CPUMGetHyperCtxCore(pVM);
    1996         }
    1997         if (VBOX_FAILURE(rc))
    1998             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Getting register context\n");
    1999 
    2000         /*
    2001          * Format the flags.
    2002          */
    2003         static struct
    2004         {
    2005             const char *pszSet; const char *pszClear; uint32_t fFlag;
    2006         }   aFlags[] =
    2007         {
    2008             { "vip",NULL, X86_EFL_VIP },
    2009             { "vif",NULL, X86_EFL_VIF },
    2010             { "ac", NULL, X86_EFL_AC },
    2011             { "vm", NULL, X86_EFL_VM },
    2012             { "rf", NULL, X86_EFL_RF },
    2013             { "nt", NULL, X86_EFL_NT },
    2014             { "ov", "nv", X86_EFL_OF },
    2015             { "dn", "up", X86_EFL_DF },
    2016             { "ei", "di", X86_EFL_IF },
    2017             { "tf", NULL, X86_EFL_TF },
    2018             { "nt", "pl", X86_EFL_SF },
    2019             { "nz", "zr", X86_EFL_ZF },
    2020             { "ac", "na", X86_EFL_AF },
    2021             { "po", "pe", X86_EFL_PF },
    2022             { "cy", "nc", X86_EFL_CF },
    2023         };
    2024         char szEFlags[80];
    2025         char *psz = szEFlags;
    2026         uint32_t efl = pCtxCore->eflags.u32;
    2027         for (unsigned i = 0; i < ELEMENTS(aFlags); i++)
    2028         {
    2029             const char *pszAdd = aFlags[i].fFlag & efl ? aFlags[i].pszSet : aFlags[i].pszClear;
    2030             if (pszAdd)
    2031             {
    2032                 strcpy(psz, pszAdd);
    2033                 psz += strlen(pszAdd);
    2034                 *psz++ = ' ';
    2035             }
    2036         }
    2037         psz[-1] = '\0';
    2038 
    2039 
    2040         /*
    2041          * Format the registers.
    2042          */
    2043         if (pDbgc->fRegTerse)
    2044         {
    2045             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    2046                 "%seax=%08x %sebx=%08x %secx=%08x %sedx=%08x %sesi=%08x %sedi=%08x\n"
    2047                 "%seip=%08x %sesp=%08x %sebp=%08x %siopl=%d %*s\n"
    2048                 "%scs=%04x %sds=%04x %ses=%04x %sfs=%04x %sgs=%04x %sss=%04x               %seflags=%08x\n",
    2049                 pszPrefix, pCtxCore->eax, pszPrefix, pCtxCore->ebx, pszPrefix, pCtxCore->ecx, pszPrefix, pCtxCore->edx, pszPrefix, pCtxCore->esi, pszPrefix, pCtxCore->edi,
    2050                 pszPrefix, pCtxCore->eip, pszPrefix, pCtxCore->esp, pszPrefix, pCtxCore->ebp, pszPrefix, X86_EFL_GET_IOPL(efl), *pszPrefix ? 34 : 31, szEFlags,
    2051                 pszPrefix, (RTSEL)pCtxCore->cs, pszPrefix, (RTSEL)pCtxCore->ds, pszPrefix, (RTSEL)pCtxCore->es,
    2052                 pszPrefix, (RTSEL)pCtxCore->fs, pszPrefix, (RTSEL)pCtxCore->gs, pszPrefix, (RTSEL)pCtxCore->ss, pszPrefix, efl);
    2053         }
    2054         else
    2055         {
    2056             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    2057                 "%seax=%08x %sebx=%08x %secx=%08x %sedx=%08x %sesi=%08x %sedi=%08x\n"
    2058                 "%seip=%08x %sesp=%08x %sebp=%08x %siopl=%d %*s\n"
    2059                 "%scs={%04x base=%08x limit=%08x flags=%08x} %sdr0=%08x %sdr1=%08x\n"
    2060                 "%sds={%04x base=%08x limit=%08x flags=%08x} %sdr2=%08x %sdr3=%08x\n"
    2061                 "%ses={%04x base=%08x limit=%08x flags=%08x} %sdr4=%08x %sdr5=%08x\n"
    2062                 "%sfs={%04x base=%08x limit=%08x flags=%08x} %sdr6=%08x %sdr7=%08x\n"
    2063                 "%sgs={%04x base=%08x limit=%08x flags=%08x} %scr0=%08x %scr2=%08x\n"
    2064                 "%sss={%04x base=%08x limit=%08x flags=%08x} %scr3=%08x %scr4=%08x\n"
    2065                 "%sgdtr=%08x:%04x  %sidtr=%08x:%04x  %seflags=%08x\n"
    2066                 "%sldtr={%04x base=%08x limit=%08x flags=%08x}\n"
    2067                 "%str  ={%04x base=%08x limit=%08x flags=%08x}\n"
    2068                 "%sSysEnter={cs=%04llx eip=%08llx esp=%08llx}\n"
    2069                 "%sFCW=%04x %sFSW=%04x %sFTW=%04x\n"
    2070                 ,
    2071                 pszPrefix, pCtxCore->eax, pszPrefix, pCtxCore->ebx, pszPrefix, pCtxCore->ecx, pszPrefix, pCtxCore->edx, pszPrefix, pCtxCore->esi, pszPrefix, pCtxCore->edi,
    2072                 pszPrefix, pCtxCore->eip, pszPrefix, pCtxCore->esp, pszPrefix, pCtxCore->ebp, pszPrefix, X86_EFL_GET_IOPL(efl), *pszPrefix ? 33 : 31, szEFlags,
    2073                 pszPrefix, (RTSEL)pCtxCore->cs, pCtx->csHid.u32Base, pCtx->csHid.u32Limit, pCtx->csHid.Attr.u, pszPrefix, pCtx->dr0,  pszPrefix, pCtx->dr1,
    2074                 pszPrefix, (RTSEL)pCtxCore->ds, pCtx->dsHid.u32Base, pCtx->dsHid.u32Limit, pCtx->dsHid.Attr.u, pszPrefix, pCtx->dr2,  pszPrefix, pCtx->dr3,
    2075                 pszPrefix, (RTSEL)pCtxCore->es, pCtx->esHid.u32Base, pCtx->esHid.u32Limit, pCtx->esHid.Attr.u, pszPrefix, pCtx->dr4,  pszPrefix, pCtx->dr5,
    2076                 pszPrefix, (RTSEL)pCtxCore->fs, pCtx->fsHid.u32Base, pCtx->fsHid.u32Limit, pCtx->fsHid.Attr.u, pszPrefix, pCtx->dr6,  pszPrefix, pCtx->dr7,
    2077                 pszPrefix, (RTSEL)pCtxCore->gs, pCtx->gsHid.u32Base, pCtx->gsHid.u32Limit, pCtx->gsHid.Attr.u, pszPrefix, pCtx->cr0,  pszPrefix, pCtx->cr2,
    2078                 pszPrefix, (RTSEL)pCtxCore->ss, pCtx->ssHid.u32Base, pCtx->ssHid.u32Limit, pCtx->ssHid.Attr.u, pszPrefix, pCtx->cr3,  pszPrefix, pCtx->cr4,
    2079                 pszPrefix, pCtx->gdtr.pGdt,pCtx->gdtr.cbGdt, pszPrefix, pCtx->idtr.pIdt, pCtx->idtr.cbIdt, pszPrefix, pCtxCore->eflags,
    2080                 pszPrefix, (RTSEL)pCtx->ldtr, pCtx->ldtrHid.u32Base, pCtx->ldtrHid.u32Limit, pCtx->ldtrHid.Attr.u,
    2081                 pszPrefix, (RTSEL)pCtx->tr, pCtx->trHid.u32Base, pCtx->trHid.u32Limit, pCtx->trHid.Attr.u,
    2082                 pszPrefix, pCtx->SysEnter.cs, pCtx->SysEnter.eip, pCtx->SysEnter.esp,
    2083                 pszPrefix, pCtx->fpu.FCW, pszPrefix, pCtx->fpu.FSW, pszPrefix, pCtx->fpu.FTW);
    2084         }
    2085 
    2086         /*
    2087          * Disassemble one instruction at cs:eip.
    2088          */
    2089         return pCmdHlp->pfnExec(pCmdHlp, "u %04x:%08x L 0", pCtx->cs, pCtx->eip);
    2090     }
    2091 
    2092     /*
    2093      * cArgs == 1: Show the register.
    2094      * cArgs == 2: Modify the register.
    2095      */
    2096     if (    cArgs == 1
    2097         ||  cArgs == 2)
    2098     {
    2099         /* locate the register symbol. */
    2100         const char *pszReg = paArgs[0].u.pszString;
    2101         if (    *pszPrefix
    2102             &&  pszReg[0] != *pszPrefix)
    2103         {
    2104             /* prepend the prefix. */
    2105             char *psz = (char *)alloca(strlen(pszReg) + 2);
    2106             psz[0] = *pszPrefix;
    2107             strcpy(psz + 1, paArgs[0].u.pszString);
    2108             pszReg = psz;
    2109         }
    2110         PCDBGCSYM pSym = dbgcLookupRegisterSymbol(pDbgc, pszReg);
    2111         if (!pSym)
    2112             return pCmdHlp->pfnVBoxError(pCmdHlp, VERR_INVALID_PARAMETER /* VERR_DBGC_INVALID_REGISTER */, "Invalid register name '%s'.\n", pszReg);
    2113 
    2114         /* show the register */
    2115         if (cArgs == 1)
    2116         {
    2117             DBGCVAR Var;
    2118             memset(&Var, 0, sizeof(Var));
    2119             int rc = pSym->pfnGet(pSym, pCmdHlp, DBGCVAR_TYPE_NUMBER, &Var);
    2120             if (VBOX_FAILURE(rc))
    2121                 return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Failed getting value for register '%s'.\n", pszReg);
    2122             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%s=%Dv\n", pszReg, &Var);
    2123         }
    2124 
    2125         /* change the register */
    2126         int rc = pSym->pfnSet(pSym, pCmdHlp, &paArgs[1]);
    2127         if (VBOX_FAILURE(rc))
    2128             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Failed setting value for register '%s'.\n", pszReg);
    2129         return VINF_SUCCESS;
    2130     }
    2131 
    2132 
    2133     NOREF(pCmd); NOREF(paArgs); NOREF(pResult);
    2134     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Huh? cArgs=%d Expected 0, 1 or 2!\n", cArgs);
    2135 }
    2136 
    2137 
    2138 /**
    2139  * The 'rg' command.
    2140  *
    2141  * @returns VBox status.
    2142  * @param   pCmd        Pointer to the command descriptor (as registered).
    2143  * @param   pCmdHlp     Pointer to command helper functions.
    2144  * @param   pVM         Pointer to the current VM (if any).
    2145  * @param   paArgs      Pointer to (readonly) array of arguments.
    2146  * @param   cArgs       Number of arguments in the array.
    2147  */
    2148 static DECLCALLBACK(int) dbgcCmdRegGuest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2149 {
    2150     return dbgcCmdRegCommon(pCmd, pCmdHlp, pVM, paArgs, cArgs, pResult, "");
    2151 }
    2152 
    2153 
    2154 /**
    2155  * The 'rh' command.
    2156  *
    2157  * @returns VBox status.
    2158  * @param   pCmd        Pointer to the command descriptor (as registered).
    2159  * @param   pCmdHlp     Pointer to command helper functions.
    2160  * @param   pVM         Pointer to the current VM (if any).
    2161  * @param   paArgs      Pointer to (readonly) array of arguments.
    2162  * @param   cArgs       Number of arguments in the array.
    2163  */
    2164 static DECLCALLBACK(int) dbgcCmdRegHyper(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2165 {
    2166     return dbgcCmdRegCommon(pCmd, pCmdHlp, pVM, paArgs, cArgs, pResult, ".");
    2167 }
    2168 
    2169 
    2170 /**
    2171  * The 'rt' command.
    2172  *
    2173  * @returns VBox status.
    2174  * @param   pCmd        Pointer to the command descriptor (as registered).
    2175  * @param   pCmdHlp     Pointer to command helper functions.
    2176  * @param   pVM         Pointer to the current VM (if any).
    2177  * @param   paArgs      Pointer to (readonly) array of arguments.
    2178  * @param   cArgs       Number of arguments in the array.
    2179  */
    2180 static DECLCALLBACK(int) dbgcCmdRegTerse(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2181 {
    2182     NOREF(pCmd); NOREF(pVM); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    2183 
    2184     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    2185     pDbgc->fRegTerse = !pDbgc->fRegTerse;
    2186     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, pDbgc->fRegTerse ? "info: Terse register info.\n" : "info: Verbose register info.\n");
    2187 }
    2188 
    2189 
    2190 /**
    2191  * The 't' command.
    2192  *
    2193  * @returns VBox status.
    2194  * @param   pCmd        Pointer to the command descriptor (as registered).
    2195  * @param   pCmdHlp     Pointer to command helper functions.
    2196  * @param   pVM         Pointer to the current VM (if any).
    2197  * @param   paArgs      Pointer to (readonly) array of arguments.
    2198  * @param   cArgs       Number of arguments in the array.
    2199  */
    2200 static DECLCALLBACK(int) dbgcCmdTrace(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2201 {
    2202     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    2203 
    2204     int rc = DBGFR3Step(pVM);
    2205     if (VBOX_SUCCESS(rc))
    2206         pDbgc->fReady = false;
    2207     else
    2208         rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to single step VM %p\n", pDbgc->pVM);
    2209 
    2210     NOREF(pCmd); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    2211     return rc;
    2212 }
    2213 
    2214 
    2215 /**
    2216  * The 'k', 'kg' and 'kh' commands.
    2217  *
    2218  * @returns VBox status.
    2219  * @param   pCmd        Pointer to the command descriptor (as registered).
    2220  * @param   pCmdHlp     Pointer to command helper functions.
    2221  * @param   pVM         Pointer to the current VM (if any).
    2222  * @param   paArgs      Pointer to (readonly) array of arguments.
    2223  * @param   cArgs       Number of arguments in the array.
    2224  */
    2225 static DECLCALLBACK(int) dbgcCmdStack(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2226 {
    2227     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    2228 
    2229     /*
    2230      * Figure which context we're called for.
    2231      */
    2232     bool fGuest = pCmd->pszCmd[1] == 'g'
    2233                || (!pCmd->pszCmd[1] && pDbgc->fRegCtxGuest);
    2234 
    2235 
    2236     DBGFSTACKFRAME Frame;
    2237     memset(&Frame, 0, sizeof(Frame));
    2238     int rc;
    2239     if (fGuest)
    2240         rc = DBGFR3StackWalkBeginGuest(pVM, &Frame);
    2241     else
    2242         rc = DBGFR3StackWalkBeginHyper(pVM, &Frame);
    2243     if (VBOX_FAILURE(rc))
    2244         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Failed to begin stack walk, rc=%Vrc\n", rc);
    2245 
    2246     /*
    2247      * Print header.
    2248      *                                      12345678 12345678 0023:87654321 12345678 87654321 12345678 87654321 symbol
    2249      */
    2250     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "EBP      Ret EBP  Ret CS:EIP    Arg0     Arg1     Arg2     Arg3     CS:EIP / Symbol [line]\n");
    2251     if (VBOX_FAILURE(rc))
    2252         return rc;
    2253     do
    2254     {
    2255         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
    2256                                 (uint32_t)Frame.AddrFrame.off,
    2257                                 (uint32_t)Frame.AddrReturnFrame.off,
    2258                                 (uint32_t)Frame.AddrReturnPC.Sel,
    2259                                 (uint32_t)Frame.AddrReturnPC.off,
    2260                                 Frame.Args.au32[0],
    2261                                 Frame.Args.au32[1],
    2262                                 Frame.Args.au32[2],
    2263                                 Frame.Args.au32[3]);
    2264         if (VBOX_FAILURE(rc))
    2265             return rc;
    2266         if (!Frame.pSymPC)
    2267             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " %RTsel:%08RGv", Frame.AddrPC.Sel, Frame.AddrPC.off);
    2268         else
    2269         {
    2270             RTGCINTPTR offDisp = Frame.AddrPC.FlatPtr - Frame.pSymPC->Value; /** @todo this isn't 100% correct for segemnted stuff. */
    2271             if (offDisp > 0)
    2272                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " %s+%llx", Frame.pSymPC->szName, (int64_t)offDisp);
    2273             else if (offDisp < 0)
    2274                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " %s-%llx", Frame.pSymPC->szName, -(int64_t)offDisp);
    2275             else
    2276                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " %s", Frame.pSymPC->szName);
    2277         }
    2278         if (VBOX_SUCCESS(rc) && Frame.pLinePC)
    2279             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " [%s @ 0i%d]", Frame.pLinePC->szFilename, Frame.pLinePC->uLineNo);
    2280         if (VBOX_SUCCESS(rc))
    2281             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\n");
    2282         if (VBOX_FAILURE(rc))
    2283             return rc;
    2284 
    2285         /* next */
    2286         rc = DBGFR3StackWalkNext(pVM, &Frame);
    2287     } while (VBOX_SUCCESS(rc));
    2288 
    2289     NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    2290     return VINF_SUCCESS;
    2291 }
    2292 
    2293 
    2294 static int dbgcCmdDumpDTWorker64(PDBGCCMDHLP /*pCmdHlp*/, PCX86DESC64 /*pDesc*/, unsigned /*iEntry*/, bool /* fHyper */, bool * /*fDblEntry*/)
    2295 {
    2296     /* GUEST64 */
    2297     return VINF_SUCCESS;
    2298 }
    2299 
    2300 
    2301 /**
    2302  * Wroker function that displays one descriptor entry (GDT, LDT, IDT).
    2303  *
    2304  * @returns pfnPrintf status code.
    2305  * @param   pCmdHlp     The DBGC command helpers.
    2306  * @param   pDesc       The descriptor to display.
    2307  * @param   iEntry      The descriptor entry number.
    2308  * @param   fHyper      Whether the selector belongs to the hypervisor or not.
    2309  */
    2310 static int dbgcCmdDumpDTWorker32(PDBGCCMDHLP pCmdHlp, PCX86DESC pDesc, unsigned iEntry, bool fHyper)
    2311 {
    2312     int rc;
    2313 
    2314     const char *pszHyper = fHyper ? " HYPER" : "";
    2315     const char *pszPresent = pDesc->Gen.u1Present ? "P " : "NP";
    2316     if (pDesc->Gen.u1DescType)
    2317     {
    2318         static const char * const s_apszTypes[] =
    2319         {
    2320             "DataRO", /* 0 Read-Only */
    2321             "DataRO", /* 1 Read-Only - Accessed */
    2322             "DataRW", /* 2 Read/Write  */
    2323             "DataRW", /* 3 Read/Write - Accessed  */
    2324             "DownRO", /* 4 Expand-down, Read-Only  */
    2325             "DownRO", /* 5 Expand-down, Read-Only - Accessed */
    2326             "DownRW", /* 6 Expand-down, Read/Write  */
    2327             "DownRO", /* 7 Expand-down, Read/Write - Accessed */
    2328             "CodeEO", /* 8 Execute-Only */
    2329             "CodeEO", /* 9 Execute-Only - Accessed */
    2330             "CodeER", /* A Execute/Readable */
    2331             "CodeER", /* B Execute/Readable - Accessed */
    2332             "ConfE0", /* C Conforming, Execute-Only */
    2333             "ConfE0", /* D Conforming, Execute-Only - Accessed */
    2334             "ConfER", /* E Conforming, Execute/Readable */
    2335             "ConfER"  /* F Conforming, Execute/Readable - Accessed */
    2336         };
    2337         const char *pszAccessed = pDesc->Gen.u4Type & RT_BIT(0) ? "A " : "NA";
    2338         const char *pszGranularity = pDesc->Gen.u1Granularity ? "G" : " ";
    2339         const char *pszBig = pDesc->Gen.u1DefBig ? "BIG" : "   ";
    2340         uint32_t u32Base = pDesc->Gen.u16BaseLow
    2341                          | ((uint32_t)pDesc->Gen.u8BaseHigh1 << 16)
    2342                          | ((uint32_t)pDesc->Gen.u8BaseHigh2 << 24);
    2343         uint32_t cbLimit = pDesc->Gen.u16LimitLow | (pDesc->Gen.u4LimitHigh << 16);
    2344         if (pDesc->Gen.u1Granularity)
    2345             cbLimit <<= PAGE_SHIFT;
    2346 
    2347         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Bas=%08x Lim=%08x DPL=%d %s %s %s %s AVL=%d R=%d%s\n",
    2348                                 iEntry, s_apszTypes[pDesc->Gen.u4Type], u32Base, cbLimit,
    2349                                 pDesc->Gen.u2Dpl, pszPresent, pszAccessed, pszGranularity, pszBig,
    2350                                 pDesc->Gen.u1Available, pDesc->Gen.u1Reserved, pszHyper);
    2351     }
    2352     else
    2353     {
    2354         static const char * const s_apszTypes[] =
    2355         {
    2356             "Ill-0 ", /* 0 0000 Reserved (Illegal) */
    2357             "Tss16A", /* 1 0001 Available 16-bit TSS */
    2358             "LDT   ", /* 2 0010 LDT */
    2359             "Tss16B", /* 3 0011 Busy 16-bit TSS */
    2360             "Call16", /* 4 0100 16-bit Call Gate */
    2361             "TaskG ", /* 5 0101 Task Gate */
    2362             "Int16 ", /* 6 0110 16-bit Interrupt Gate */
    2363             "Trap16", /* 7 0111 16-bit Trap Gate */
    2364             "Ill-8 ", /* 8 1000 Reserved (Illegal) */
    2365             "Tss32A", /* 9 1001 Available 32-bit TSS */
    2366             "Ill-A ", /* A 1010 Reserved (Illegal) */
    2367             "Tss32B", /* B 1011 Busy 32-bit TSS */
    2368             "Call32", /* C 1100 32-bit Call Gate */
    2369             "Ill-D ", /* D 1101 Reserved (Illegal) */
    2370             "Int32 ", /* E 1110 32-bit Interrupt Gate */
    2371             "Trap32"  /* F 1111 32-bit Trap Gate */
    2372         };
    2373         switch (pDesc->Gen.u4Type)
    2374         {
    2375             /* raw */
    2376             case X86_SEL_TYPE_SYS_UNDEFINED:
    2377             case X86_SEL_TYPE_SYS_UNDEFINED2:
    2378             case X86_SEL_TYPE_SYS_UNDEFINED4:
    2379             case X86_SEL_TYPE_SYS_UNDEFINED3:
    2380                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s %.8Rhxs   DPL=%d %s%s\n",
    2381                                         iEntry, s_apszTypes[pDesc->Gen.u4Type], pDesc,
    2382                                         pDesc->Gen.u2Dpl, pszPresent, pszHyper);
    2383                 break;
    2384 
    2385             case X86_SEL_TYPE_SYS_286_TSS_AVAIL:
    2386             case X86_SEL_TYPE_SYS_386_TSS_AVAIL:
    2387             case X86_SEL_TYPE_SYS_286_TSS_BUSY:
    2388             case X86_SEL_TYPE_SYS_386_TSS_BUSY:
    2389             case X86_SEL_TYPE_SYS_LDT:
    2390             {
    2391                 const char *pszGranularity = pDesc->Gen.u1Granularity ? "G" : " ";
    2392                 const char *pszBusy = pDesc->Gen.u4Type & RT_BIT(1) ? "B " : "NB";
    2393                 const char *pszBig = pDesc->Gen.u1DefBig ? "BIG" : "   ";
    2394                 uint32_t u32Base = pDesc->Gen.u16BaseLow
    2395                                  | ((uint32_t)pDesc->Gen.u8BaseHigh1 << 16)
    2396                                  | ((uint32_t)pDesc->Gen.u8BaseHigh2 << 24);
    2397                 uint32_t cbLimit = pDesc->Gen.u16LimitLow | (pDesc->Gen.u4LimitHigh << 16);
    2398                 if (pDesc->Gen.u1Granularity)
    2399                     cbLimit <<= PAGE_SHIFT;
    2400 
    2401                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Bas=%08x Lim=%08x DPL=%d %s %s %s %s AVL=%d R=%d%s\n",
    2402                                         iEntry, s_apszTypes[pDesc->Gen.u4Type], u32Base, cbLimit,
    2403                                         pDesc->Gen.u2Dpl, pszPresent, pszBusy, pszGranularity, pszBig,
    2404                                         pDesc->Gen.u1Available, pDesc->Gen.u1Reserved | (pDesc->Gen.u1DefBig << 1),
    2405                                         pszHyper);
    2406                 break;
    2407             }
    2408 
    2409             case X86_SEL_TYPE_SYS_TASK_GATE:
    2410             {
    2411                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s TSS=%04x                  DPL=%d %s%s\n",
    2412                                         iEntry, s_apszTypes[pDesc->Gen.u4Type], pDesc->au16[1],
    2413                                         pDesc->Gen.u2Dpl, pszPresent, pszHyper);
    2414                 break;
    2415             }
    2416 
    2417             case X86_SEL_TYPE_SYS_286_CALL_GATE:
    2418             case X86_SEL_TYPE_SYS_386_CALL_GATE:
    2419             {
    2420                 unsigned cParams = pDesc->au8[0] & 0x1f;
    2421                 const char *pszCountOf = pDesc->Gen.u4Type & RT_BIT(3) ? "DC" : "WC";
    2422                 RTSEL sel = pDesc->au16[1];
    2423                 uint32_t off = pDesc->au16[0] | ((uint32_t)pDesc->au16[3] << 16);
    2424                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Sel:Off=%04x:%08x     DPL=%d %s %s=%d%s\n",
    2425                                         iEntry, s_apszTypes[pDesc->Gen.u4Type], sel, off,
    2426                                         pDesc->Gen.u2Dpl, pszPresent, pszCountOf, cParams, pszHyper);
    2427                 break;
    2428             }
    2429 
    2430             case X86_SEL_TYPE_SYS_286_INT_GATE:
    2431             case X86_SEL_TYPE_SYS_386_INT_GATE:
    2432             case X86_SEL_TYPE_SYS_286_TRAP_GATE:
    2433             case X86_SEL_TYPE_SYS_386_TRAP_GATE:
    2434             {
    2435                 RTSEL sel = pDesc->au16[1];
    2436                 uint32_t off = pDesc->au16[0] | ((uint32_t)pDesc->au16[3] << 16);
    2437                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Sel:Off=%04x:%08x     DPL=%d %s%s\n",
    2438                                         iEntry, s_apszTypes[pDesc->Gen.u4Type], sel, off,
    2439                                         pDesc->Gen.u2Dpl, pszPresent, pszHyper);
    2440                 break;
    2441             }
    2442 
    2443             /* impossible, just it's necessary to keep gcc happy. */
    2444             default:
    2445                 return VINF_SUCCESS;
    2446         }
    2447     }
    2448     return rc;
    2449 }
    2450 
    2451 
    2452 /**
    2453  * The 'dg', 'dga', 'dl' and 'dla' commands.
    2454  *
    2455  * @returns VBox status.
    2456  * @param   pCmd        Pointer to the command descriptor (as registered).
    2457  * @param   pCmdHlp     Pointer to command helper functions.
    2458  * @param   pVM         Pointer to the current VM (if any).
    2459  * @param   paArgs      Pointer to (readonly) array of arguments.
    2460  * @param   cArgs       Number of arguments in the array.
    2461  */
    2462 static DECLCALLBACK(int) dbgcCmdDumpDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2463 {
    2464     /*
    2465      * Validate input.
    2466      */
    2467     if (!pVM)
    2468         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    2469 
    2470     /*
    2471      * Get the CPU mode, check which command variation this is
    2472      * and fix a default parameter if needed.
    2473      */
    2474     CPUMMODE enmMode = CPUMGetGuestMode(pVM);
    2475     bool fGdt = pCmd->pszCmd[1] == 'g';
    2476     bool fAll = pCmd->pszCmd[2] == 'a';
    2477 
    2478     DBGCVAR Var;
    2479     if (!cArgs)
    2480     {
    2481         cArgs = 1;
    2482         paArgs = &Var;
    2483         Var.enmType = DBGCVAR_TYPE_NUMBER;
    2484         Var.u.u64Number = fGdt ? 0 : 4;
    2485         Var.enmRangeType = DBGCVAR_RANGE_ELEMENTS;
    2486         Var.u64Range = 1024;
    2487     }
    2488 
    2489     /*
    2490      * Process the arguments.
    2491      */
    2492     for (unsigned i = 0; i < cArgs; i++)
    2493     {
    2494          /*
    2495           * Retrive the selector value from the argument.
    2496           * The parser may confuse pointers and numbers if more than one
    2497           * argument is given, that that into account.
    2498           */
    2499         /* check that what've got makes sense as we don't trust the parser yet. */
    2500         if (    paArgs[i].enmType != DBGCVAR_TYPE_NUMBER
    2501             &&  !DBGCVAR_ISPOINTER(paArgs[i].enmType))
    2502             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: arg #%u isn't of number or pointer type but %d.\n", i, paArgs[i].enmType);
    2503         uint64_t u64;
    2504         unsigned cSels = 1;
    2505         switch (paArgs[i].enmType)
    2506         {
    2507             case DBGCVAR_TYPE_NUMBER:
    2508                 u64 = paArgs[i].u.u64Number;
    2509                 if (paArgs[i].enmRangeType != DBGCVAR_RANGE_NONE)
    2510                     cSels = RT_MIN(paArgs[i].u64Range, 1024);
    2511                 break;
    2512             case DBGCVAR_TYPE_GC_FAR:   u64 = paArgs[i].u.GCFar.sel; break;
    2513             case DBGCVAR_TYPE_GC_FLAT:  u64 = paArgs[i].u.GCFlat; break;
    2514             case DBGCVAR_TYPE_GC_PHYS:  u64 = paArgs[i].u.GCPhys; break;
    2515             case DBGCVAR_TYPE_HC_FAR:   u64 = paArgs[i].u.HCFar.sel; break;
    2516             case DBGCVAR_TYPE_HC_FLAT:  u64 = (uintptr_t)paArgs[i].u.pvHCFlat; break;
    2517             case DBGCVAR_TYPE_HC_PHYS:  u64 = paArgs[i].u.HCPhys; break;
    2518             default:                    u64 = _64K; break;
    2519         }
    2520         if (u64 < _64K)
    2521         {
    2522             unsigned Sel = (RTSEL)u64;
    2523 
    2524             /*
    2525              * Dump the specified range.
    2526              */
    2527             bool fSingle = cSels == 1;
    2528             while (     cSels-- > 0
    2529                    &&   Sel < _64K)
    2530             {
    2531                 SELMSELINFO SelInfo;
    2532                 int rc = SELMR3GetSelectorInfo(pVM, Sel, &SelInfo);
    2533                 if (RT_SUCCESS(rc))
    2534                 {
    2535                     if (SelInfo.fRealMode)
    2536                         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x RealM   Bas=%04x     Lim=%04x\n",
    2537                                                 Sel, (unsigned)SelInfo.GCPtrBase, (unsigned)SelInfo.cbLimit);
    2538                     else if (fAll || fSingle || SelInfo.Raw.Gen.u1Present)
    2539                     {
    2540                         if (enmMode == CPUMMODE_PROTECTED)
    2541                             rc = dbgcCmdDumpDTWorker32(pCmdHlp, (PX86DESC)&SelInfo.Raw, Sel, SelInfo.fHyper);
    2542                         else
    2543                         {
    2544                             bool fDblSkip = false;
    2545                             rc = dbgcCmdDumpDTWorker64(pCmdHlp, (PX86DESC64)&SelInfo.Raw, Sel, SelInfo.fHyper, &fDblSkip);
    2546                             if (fDblSkip)
    2547                                 Sel += 4;
    2548                         }
    2549                     }
    2550                 }
    2551                 else
    2552                 {
    2553                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %Vrc\n", Sel, rc);
    2554                     if (!fAll)
    2555                         return rc;
    2556                 }
    2557                 if (RT_FAILURE(rc))
    2558                     return rc;
    2559 
    2560                 /* next */
    2561                 Sel += 4;
    2562             }
    2563         }
    2564         else
    2565             pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: %llx is out of bounds\n", u64);
    2566     }
    2567 
    2568     NOREF(pResult);
    2569     return VINF_SUCCESS;
    2570 }
    2571 
    2572 
    2573 /**
    2574  * The 'di' and 'dia' commands.
    2575  *
    2576  * @returns VBox status.
    2577  * @param   pCmd        Pointer to the command descriptor (as registered).
    2578  * @param   pCmdHlp     Pointer to command helper functions.
    2579  * @param   pVM         Pointer to the current VM (if any).
    2580  * @param   paArgs      Pointer to (readonly) array of arguments.
    2581  * @param   cArgs       Number of arguments in the array.
    2582  */
    2583 static DECLCALLBACK(int) dbgcCmdDumpIDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2584 {
    2585     /*
    2586      * Validate input.
    2587      */
    2588     if (!pVM)
    2589         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    2590 
    2591     /*
    2592      * Establish some stuff like the current IDTR and CPU mode,
    2593      * and fix a default parameter.
    2594      */
    2595     uint16_t cbLimit;
    2596     RTGCUINTPTR GCPtrBase = CPUMGetGuestIDTR(pVM, &cbLimit);
    2597     CPUMMODE enmMode = CPUMGetGuestMode(pVM);
    2598     unsigned cbEntry;
    2599     switch (enmMode)
    2600     {
    2601         case CPUMMODE_REAL:         cbEntry = sizeof(RTFAR16); break;
    2602         case CPUMMODE_PROTECTED:    cbEntry = sizeof(X86DESC); break;
    2603         case CPUMMODE_LONG:         cbEntry = sizeof(X86DESC64); break;
    2604         default:
    2605             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid CPU mode %d.\n", enmMode);
    2606     }
    2607 
    2608     bool fAll = pCmd->pszCmd[2] == 'a';
    2609     DBGCVAR Var;
    2610     if (!cArgs)
    2611     {
    2612         cArgs = 1;
    2613         paArgs = &Var;
    2614         Var.enmType = DBGCVAR_TYPE_NUMBER;
    2615         Var.u.u64Number = 0;
    2616         Var.enmRangeType = DBGCVAR_RANGE_ELEMENTS;
    2617         Var.u64Range = 256;
    2618     }
    2619 
    2620     /*
    2621      * Process the arguments.
    2622      */
    2623     for (unsigned i = 0; i < cArgs; i++)
    2624     {
    2625         /* check that what've got makes sense as we don't trust the parser yet. */
    2626         if (paArgs[i].enmType != DBGCVAR_TYPE_NUMBER)
    2627             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: arg #%u isn't of number type but %d.\n", i, paArgs[i].enmType);
    2628         if (paArgs[i].u.u64Number < 256)
    2629         {
    2630             RTGCUINTPTR iInt = (RTGCUINTPTR)paArgs[i].u.u64Number;
    2631             unsigned cInts = paArgs[i].enmRangeType != DBGCVAR_RANGE_NONE
    2632                            ? paArgs[i].u64Range
    2633                            : 1;
    2634             bool fSingle = cInts == 1;
    2635             while (     cInts-- > 0
    2636                    &&   iInt < 256)
    2637             {
    2638                 /*
    2639                  * Try read it.
    2640                  */
    2641                 union
    2642                 {
    2643                     RTFAR16 Real;
    2644                     X86DESC Prot;
    2645                     X86DESC64 Long;
    2646                 } u;
    2647                 if (iInt * cbEntry  + (cbEntry - 1) > cbLimit)
    2648                 {
    2649                     pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x not within the IDT\n", (unsigned)iInt);
    2650                     if (!fAll && !fSingle)
    2651                         return VINF_SUCCESS;
    2652                 }
    2653                 DBGCVAR AddrVar;
    2654                 AddrVar.enmType = DBGCVAR_TYPE_GC_FLAT;
    2655                 AddrVar.u.GCFlat = GCPtrBase + iInt * cbEntry;
    2656                 AddrVar.enmRangeType = DBGCVAR_RANGE_NONE;
    2657                 int rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &u, cbEntry, &AddrVar, NULL);
    2658                 if (VBOX_FAILURE(rc))
    2659                     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Reading IDT entry %#04x.\n", (unsigned)iInt);
    2660 
    2661                 /*
    2662                  * Display it.
    2663                  */
    2664                 switch (enmMode)
    2665                 {
    2666                     case CPUMMODE_REAL:
    2667                         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %RTfp16\n", (unsigned)iInt, u.Real);
    2668                         /** @todo resolve 16:16 IDTE to a symbol */
    2669                         break;
    2670                     case CPUMMODE_PROTECTED:
    2671                         if (fAll || fSingle || u.Prot.Gen.u1Present)
    2672                             rc = dbgcCmdDumpDTWorker32(pCmdHlp, &u.Prot, iInt, false);
    2673                         break;
    2674                     case CPUMMODE_LONG:
    2675                         if (fAll || fSingle || u.Long.Gen.u1Present)
    2676                             rc = dbgcCmdDumpDTWorker64(pCmdHlp, &u.Long, iInt, false, NULL);
    2677                         break;
    2678                     default: break; /* to shut up gcc */
    2679                 }
    2680                 if (RT_FAILURE(rc))
    2681                     return rc;
    2682 
    2683                 /* next */
    2684                 iInt++;
    2685             }
    2686         }
    2687         else
    2688             pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: %llx is out of bounds (max 256)\n", paArgs[i].u.u64Number);
    2689     }
    2690 
    2691     NOREF(pResult);
    2692     return VINF_SUCCESS;
    2693 }
    2694 
    2695 
    2696 /**
    2697  * The 'da', 'dq', 'dd', 'dw' and 'db' commands.
    2698  *
    2699  * @returns VBox status.
    2700  * @param   pCmd        Pointer to the command descriptor (as registered).
    2701  * @param   pCmdHlp     Pointer to command helper functions.
    2702  * @param   pVM         Pointer to the current VM (if any).
    2703  * @param   paArgs      Pointer to (readonly) array of arguments.
    2704  * @param   cArgs       Number of arguments in the array.
    2705  */
    2706 static DECLCALLBACK(int) dbgcCmdDumpMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2707 {
    2708     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    2709 
    2710     /*
    2711      * Validate input.
    2712      */
    2713     if (    cArgs > 1
    2714         ||  (cArgs == 1 && !DBGCVAR_ISPOINTER(paArgs[0].enmType)))
    2715         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: The parser doesn't do its job properly yet.. It might help to use the '%%' operator.\n");
    2716     if (!pVM)
    2717         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    2718 
    2719     /*
    2720      * Figure out the element size.
    2721      */
    2722     unsigned    cbElement;
    2723     bool        fAscii = false;
    2724     switch (pCmd->pszCmd[1])
    2725     {
    2726         default:
    2727         case 'b':   cbElement = 1; break;
    2728         case 'w':   cbElement = 2; break;
    2729         case 'd':   cbElement = 4; break;
    2730         case 'q':   cbElement = 8; break;
    2731         case 'a':
    2732             cbElement = 1;
    2733             fAscii = true;
    2734             break;
    2735         case '\0':
    2736             fAscii = !!(pDbgc->cbDumpElement & 0x80000000);
    2737             cbElement = pDbgc->cbDumpElement & 0x7fffffff;
    2738             if (!cbElement)
    2739                 cbElement = 1;
    2740             break;
    2741     }
    2742 
    2743     /*
    2744      * Find address.
    2745      */
    2746     if (!cArgs)
    2747         pDbgc->DumpPos.enmRangeType = DBGCVAR_RANGE_NONE;
    2748     else
    2749         pDbgc->DumpPos = paArgs[0];
    2750 
    2751     /*
    2752      * Range.
    2753      */
    2754     switch (pDbgc->DumpPos.enmRangeType)
    2755     {
    2756         case DBGCVAR_RANGE_NONE:
    2757             pDbgc->DumpPos.enmRangeType = DBGCVAR_RANGE_BYTES;
    2758             pDbgc->DumpPos.u64Range     = 0x60;
    2759             break;
    2760 
    2761         case DBGCVAR_RANGE_ELEMENTS:
    2762             if (pDbgc->DumpPos.u64Range > 2048)
    2763                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Too many elements requested. Max is 2048 elements.\n");
    2764             pDbgc->DumpPos.enmRangeType = DBGCVAR_RANGE_BYTES;
    2765             pDbgc->DumpPos.u64Range     = (cbElement ? cbElement : 1) * pDbgc->DumpPos.u64Range;
    2766             break;
    2767 
    2768         case DBGCVAR_RANGE_BYTES:
    2769             if (pDbgc->DumpPos.u64Range > 65536)
    2770                 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The requested range is too big. Max is 64KB.\n");
    2771             break;
    2772 
    2773         default:
    2774             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: Unknown range type %d.\n", pDbgc->DumpPos.enmRangeType);
    2775     }
    2776 
    2777     /*
    2778      * Do the dumping.
    2779      */
    2780     pDbgc->cbDumpElement = cbElement | (fAscii << 31);
    2781     int     cbLeft = (int)pDbgc->DumpPos.u64Range;
    2782     uint8_t u8Prev = '\0';
    2783     for (;;)
    2784     {
    2785         /*
    2786          * Read memory.
    2787          */
    2788         char    achBuffer[16];
    2789         size_t  cbReq = RT_MIN((int)sizeof(achBuffer), cbLeft);
    2790         size_t  cb = RT_MIN((int)sizeof(achBuffer), cbLeft);
    2791         int rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &achBuffer, cbReq, &pDbgc->DumpPos, &cb);
    2792         if (VBOX_FAILURE(rc))
    2793         {
    2794             if (u8Prev && u8Prev != '\n')
    2795                 pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\n");
    2796             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Reading memory at %DV.\n", &pDbgc->DumpPos);
    2797         }
    2798 
    2799         /*
    2800          * Display it.
    2801          */
    2802         memset(&achBuffer[cb], 0, sizeof(achBuffer) - cb);
    2803         if (!fAscii)
    2804         {
    2805             pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%DV:", &pDbgc->DumpPos);
    2806             unsigned i;
    2807             for (i = 0; i < cb; i += cbElement)
    2808             {
    2809                 const char *pszSpace = " ";
    2810                 if (cbElement <= 2 && i == 8 && !fAscii)
    2811                     pszSpace = "-";
    2812                 switch (cbElement)
    2813                 {
    2814                     case 1: pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%s%02x",    pszSpace, *(uint8_t *)&achBuffer[i]); break;
    2815                     case 2: pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%s%04x",    pszSpace, *(uint16_t *)&achBuffer[i]); break;
    2816                     case 4: pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%s%08x",    pszSpace, *(uint32_t *)&achBuffer[i]); break;
    2817                     case 8: pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%s%016llx", pszSpace, *(uint64_t *)&achBuffer[i]); break;
    2818                 }
    2819             }
    2820 
    2821             /* chars column */
    2822             if (pDbgc->cbDumpElement == 1)
    2823             {
    2824                 while (i++ < sizeof(achBuffer))
    2825                     pCmdHlp->pfnPrintf(pCmdHlp, NULL, "   ");
    2826                 pCmdHlp->pfnPrintf(pCmdHlp, NULL, "  ");
    2827                 for (i = 0; i < cb; i += cbElement)
    2828                 {
    2829                     uint8_t u8 = *(uint8_t *)&achBuffer[i];
    2830                     if (isprint(u8) && u8 < 127)
    2831                         pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%c", u8);
    2832                     else
    2833                         pCmdHlp->pfnPrintf(pCmdHlp, NULL, ".");
    2834                 }
    2835             }
    2836             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\n");
    2837         }
    2838         else
    2839         {
    2840             /*
    2841              * We print up to the first zero and stop there.
    2842              * Only printables + '\t' and '\n' are printed.
    2843              */
    2844             if (!u8Prev)
    2845                 pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%DV:\n", &pDbgc->DumpPos);
    2846             uint8_t u8 = '\0';
    2847             unsigned i;
    2848             for (i = 0; i < cb; i++)
    2849             {
    2850                 u8Prev = u8;
    2851                 u8 = *(uint8_t *)&achBuffer[i];
    2852                 if (    u8 < 127
    2853                     && (    isprint(u8)
    2854                         ||  u8 == '\t'
    2855                         ||  u8 == '\n'))
    2856                     pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%c", u8);
    2857                 else if (!u8)
    2858                     break;
    2859                 else
    2860                     pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\\x%x", u8);
    2861             }
    2862             if (u8 == '\0')
    2863                 cb = cbLeft = i + 1;
    2864             if (cbLeft - cb <= 0 && u8Prev != '\n')
    2865                 pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\n");
    2866         }
    2867 
    2868         /*
    2869          * Advance
    2870          */
    2871         cbLeft -= (int)cb;
    2872         rc = pCmdHlp->pfnEval(pCmdHlp, &pDbgc->DumpPos, "(%Dv) + %x", &pDbgc->DumpPos, cb);
    2873         if (VBOX_FAILURE(rc))
    2874             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Expression: (%Dv) + %x\n", &pDbgc->DumpPos, cb);
    2875         if (cbLeft <= 0)
    2876             break;
    2877     }
    2878 
    2879     NOREF(pCmd); NOREF(pResult);
    2880     return VINF_SUCCESS;
    2881 }
    2882 
    2883 
    2884 /**
    2885  * Best guess at which paging mode currently applies to the guest
    2886  * paging structures.
    2887  *
    2888  * This have to come up with a decent answer even when the guest
    2889  * is in non-paged protected mode or real mode.
    2890  *
    2891  * @returns cr3.
    2892  * @param   pDbgc   The DBGC instance.
    2893  * @param   pfPAE   Where to store the page address extension indicator.
    2894  * @param   pfLME   Where to store the long mode enabled indicator.
    2895  * @param   pfPSE   Where to store the page size extension indicator.
    2896  * @param   pfPGE   Where to store the page global enabled indicator.
    2897  * @param   pfNXE   Where to store the no-execution enabled inidicator.
    2898  */
    2899 static RTGCPHYS dbgcGetGuestPageMode(PDBGC pDbgc, bool *pfPAE, bool *pfLME, bool *pfPSE, bool *pfPGE, bool *pfNXE)
    2900 {
    2901     RTGCUINTREG cr4 = CPUMGetGuestCR4(pDbgc->pVM);
    2902     *pfPSE = !!(cr4 & X86_CR4_PSE);
    2903     *pfPGE = !!(cr4 & X86_CR4_PGE);
    2904     *pfPAE = !!(cr4 & X86_CR4_PAE);
    2905     *pfLME = CPUMGetGuestMode(pDbgc->pVM) == CPUMMODE_LONG;
    2906     *pfNXE = false; /* GUEST64 GUESTNX */
    2907     return CPUMGetGuestCR3(pDbgc->pVM);
    2908 }
    2909 
    2910 
    2911 /**
    2912  * Determin the shadow paging mode.
    2913  *
    2914  * @returns cr3.
    2915  * @param   pDbgc   The DBGC instance.
    2916  * @param   pfPAE   Where to store the page address extension indicator.
    2917  * @param   pfLME   Where to store the long mode enabled indicator.
    2918  * @param   pfPSE   Where to store the page size extension indicator.
    2919  * @param   pfPGE   Where to store the page global enabled indicator.
    2920  * @param   pfNXE   Where to store the no-execution enabled inidicator.
    2921  */
    2922 static RTHCPHYS dbgcGetShadowPageMode(PDBGC pDbgc, bool *pfPAE, bool *pfLME, bool *pfPSE, bool *pfPGE, bool *pfNXE)
    2923 {
    2924     *pfPSE = true;
    2925     *pfPGE = false;
    2926     switch (PGMGetShadowMode(pDbgc->pVM))
    2927     {
    2928         default:
    2929         case PGMMODE_32_BIT:
    2930             *pfPAE = *pfLME = *pfNXE = false;
    2931             break;
    2932         case PGMMODE_PAE:
    2933             *pfLME = *pfNXE = false;
    2934             *pfPAE = true;
    2935             break;
    2936         case PGMMODE_PAE_NX:
    2937             *pfLME = false;
    2938             *pfPAE = *pfNXE = true;
    2939             break;
    2940         case PGMMODE_AMD64:
    2941             *pfNXE = false;
    2942             *pfPAE = *pfLME = true;
    2943             break;
    2944         case PGMMODE_AMD64_NX:
    2945             *pfPAE = *pfLME = *pfNXE = true;
    2946             break;
    2947     }
    2948     return PGMGetHyperCR3(pDbgc->pVM);
    2949 }
    2950 
    2951 
    2952 /**
    2953  * The 'dpd', 'dpda', 'dpdb', 'dpdg' and 'dpdh' commands.
    2954  *
    2955  * @returns VBox status.
    2956  * @param   pCmd        Pointer to the command descriptor (as registered).
    2957  * @param   pCmdHlp     Pointer to command helper functions.
    2958  * @param   pVM         Pointer to the current VM (if any).
    2959  * @param   paArgs      Pointer to (readonly) array of arguments.
    2960  * @param   cArgs       Number of arguments in the array.
    2961  */
    2962 static DECLCALLBACK(int) dbgcCmdDumpPageDir(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    2963 {
    2964     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    2965 
    2966     /*
    2967      * Validate input.
    2968      */
    2969     if (    cArgs > 1
    2970         ||  (cArgs == 1 && pCmd->pszCmd[3] == 'a' && !DBGCVAR_ISPOINTER(paArgs[0].enmType))
    2971         ||  (cArgs == 1 && pCmd->pszCmd[3] != 'a' && !(paArgs[0].enmType == DBGCVAR_TYPE_NUMBER || DBGCVAR_ISPOINTER(paArgs[0].enmType)))
    2972         )
    2973         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: The parser doesn't do its job properly yet.. It might help to use the '%%' operator.\n");
    2974     if (!pVM)
    2975         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    2976 
    2977     /*
    2978      * Guest or shadow page directories? Get the paging parameters.
    2979      */
    2980     bool fGuest = pCmd->pszCmd[3] != 'h';
    2981     if (!pCmd->pszCmd[3] || pCmd->pszCmd[3] == 'a')
    2982         fGuest = paArgs[0].enmType == DBGCVAR_TYPE_NUMBER
    2983                ? pDbgc->fRegCtxGuest
    2984                : DBGCVAR_ISGCPOINTER(paArgs[0].enmType);
    2985 
    2986     bool fPAE, fLME, fPSE, fPGE, fNXE;
    2987     uint64_t cr3 = fGuest
    2988                  ? dbgcGetGuestPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE)
    2989                  : dbgcGetShadowPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE);
    2990     const unsigned cbEntry = fPAE ? sizeof(X86PTEPAE) : sizeof(X86PTE);
    2991 
    2992     /*
    2993      * Setup default arugment if none was specified.
    2994      * Fix address / index confusion.
    2995      */
    2996     DBGCVAR VarDefault;
    2997     if (!cArgs)
    2998     {
    2999         if (pCmd->pszCmd[3] == 'a')
    3000         {
    3001             if (fLME || fPAE)
    3002                 return DBGCCmdHlpPrintf(pCmdHlp, "Default argument for 'dpda' hasn't been fully implemented yet. Try with an address or use one of the other commands.\n");
    3003             if (fGuest)
    3004                 DBGCVAR_INIT_GC_PHYS(&VarDefault, cr3);
    3005             else
    3006                 DBGCVAR_INIT_HC_PHYS(&VarDefault, cr3);
    3007         }
    3008         else
    3009             DBGCVAR_INIT_GC_FLAT(&VarDefault, 0);
    3010         paArgs = &VarDefault;
    3011         cArgs = 1;
    3012     }
    3013     else if (paArgs[0].enmType == DBGCVAR_TYPE_NUMBER)
    3014     {
    3015         Assert(pCmd->pszCmd[3] != 'a');
    3016         VarDefault = paArgs[0];
    3017         if (VarDefault.u.u64Number <= 1024)
    3018         {
    3019             if (fPAE)
    3020                 return DBGCCmdHlpPrintf(pCmdHlp, "PDE indexing is only implemented for 32-bit paging.\n");
    3021             if (VarDefault.u.u64Number >= PAGE_SIZE / cbEntry)
    3022                 return DBGCCmdHlpPrintf(pCmdHlp, "PDE index is out of range [0..%d].\n", PAGE_SIZE / cbEntry - 1);
    3023             VarDefault.u.u64Number <<= X86_PD_SHIFT;
    3024         }
    3025         VarDefault.enmType = DBGCVAR_TYPE_GC_FLAT;
    3026         paArgs = &VarDefault;
    3027     }
    3028 
    3029     /*
    3030      * Locate the PDE to start displaying at.
    3031      *
    3032      * The 'dpda' command takes the address of a PDE, while the others are guest
    3033      * virtual address which PDEs should be displayed. So, 'dpda' is rather simple
    3034      * while the others require us to do all the tedious walking thru the paging
    3035      * hierarchy to find the intended PDE.
    3036      */
    3037     unsigned    iEntry = ~0U;           /* The page directory index. ~0U for 'dpta'. */
    3038     DBGCVAR     VarGCPtr;               /* The GC address corresponding to the current PDE (iEntry != ~0U). */
    3039     DBGCVAR     VarPDEAddr;             /* The address of the current PDE. */
    3040     unsigned    cEntries;               /* The number of entries to display. */
    3041     unsigned    cEntriesMax;            /* The max number of entries to display. */
    3042     int         rc;
    3043     if (pCmd->pszCmd[3] == 'a')
    3044     {
    3045         VarPDEAddr = paArgs[0];
    3046         switch (VarPDEAddr.enmRangeType)
    3047         {
    3048             case DBGCVAR_RANGE_BYTES:       cEntries = VarPDEAddr.u64Range / cbEntry; break;
    3049             case DBGCVAR_RANGE_ELEMENTS:    cEntries = VarPDEAddr.u64Range; break;
    3050             default:                        cEntries = 10; break;
    3051         }
    3052         cEntriesMax = PAGE_SIZE / cbEntry;
    3053     }
    3054     else
    3055     {
    3056         /*
    3057          * Determin the range.
    3058          */
    3059         switch (paArgs[0].enmRangeType)
    3060         {
    3061             case DBGCVAR_RANGE_BYTES:       cEntries = paArgs[0].u64Range / PAGE_SIZE; break;
    3062             case DBGCVAR_RANGE_ELEMENTS:    cEntries = paArgs[0].u64Range; break;
    3063             default:                        cEntries = 10; break;
    3064         }
    3065 
    3066         /*
    3067          * Normalize the input address, it must be a flat GC address.
    3068          */
    3069         rc = pCmdHlp->pfnEval(pCmdHlp, &VarGCPtr, "%%(%Dv)", &paArgs[0]);
    3070         if (VBOX_FAILURE(rc))
    3071             return DBGCCmdHlpVBoxError(pCmdHlp, rc, "%%(%Dv)", &paArgs[0]);
    3072         if (VarGCPtr.enmType == DBGCVAR_TYPE_HC_FLAT)
    3073         {
    3074             VarGCPtr.u.GCFlat = (uintptr_t)VarGCPtr.u.pvHCFlat;
    3075             VarGCPtr.enmType = DBGCVAR_TYPE_GC_FLAT;
    3076         }
    3077         if (fPAE)
    3078             VarGCPtr.u.GCFlat &= ~(((RTGCPTR)1 << X86_PD_PAE_SHIFT) - 1);
    3079         else
    3080             VarGCPtr.u.GCFlat &= ~(((RTGCPTR)1 << X86_PD_SHIFT) - 1);
    3081 
    3082         /*
    3083          * Do the paging walk until we get to the page directory.
    3084          */
    3085         DBGCVAR VarCur;
    3086         if (fGuest)
    3087             DBGCVAR_INIT_GC_PHYS(&VarCur, cr3);
    3088         else
    3089             DBGCVAR_INIT_HC_PHYS(&VarCur, cr3);
    3090         if (fLME)
    3091         {
    3092             /* Page Map Level 4 Lookup. */
    3093             /* Check if it's a valid address first? */
    3094             VarCur.u.u64Number &= X86_PTE_PAE_PG_MASK;
    3095             VarCur.u.u64Number += (((uint64_t)VarGCPtr.u.GCFlat >> X86_PML4_SHIFT) & X86_PML4_MASK) * sizeof(X86PML4E);
    3096             X86PML4E Pml4e;
    3097             rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pml4e, sizeof(Pml4e), &VarCur, NULL);
    3098             if (VBOX_FAILURE(rc))
    3099                 return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PML4E memory at %DV.\n", &VarCur);
    3100             if (!Pml4e.n.u1Present)
    3101                 return DBGCCmdHlpPrintf(pCmdHlp, "Page directory pointer table is not present for %Dv.\n", &VarGCPtr);
    3102 
    3103             VarCur.u.u64Number = Pml4e.u & X86_PML4E_PG_MASK;
    3104             Assert(fPAE);
    3105         }
    3106         if (fPAE)
    3107         {
    3108             /* Page directory pointer table. */
    3109             X86PDPE Pdpe;
    3110             VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK) * sizeof(Pdpe);
    3111             rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pdpe, sizeof(Pdpe), &VarCur, NULL);
    3112             if (VBOX_FAILURE(rc))
    3113                 return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDPE memory at %DV.\n", &VarCur);
    3114             if (!Pdpe.n.u1Present)
    3115                 return DBGCCmdHlpPrintf(pCmdHlp, "Page directory is not present for %Dv.\n", &VarGCPtr);
    3116 
    3117             iEntry = (VarGCPtr.u.GCFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
    3118             VarPDEAddr = VarCur;
    3119             VarPDEAddr.u.u64Number = Pdpe.u & X86_PDPE_PG_MASK;
    3120             VarPDEAddr.u.u64Number += iEntry * sizeof(X86PDEPAE);
    3121         }
    3122         else
    3123         {
    3124             /* 32-bit legacy - CR3 == page directory. */
    3125             iEntry = (VarGCPtr.u.GCFlat >> X86_PD_SHIFT) & X86_PD_MASK;
    3126             VarPDEAddr = VarCur;
    3127             VarPDEAddr.u.u64Number += iEntry * sizeof(X86PDE);
    3128         }
    3129         cEntriesMax = (PAGE_SIZE - iEntry) / cbEntry;
    3130         iEntry /= cbEntry;
    3131     }
    3132 
    3133     /* adjust cEntries */
    3134     cEntries = RT_MAX(1, cEntries);
    3135     cEntries = RT_MIN(cEntries, cEntriesMax);
    3136 
    3137     /*
    3138      * The display loop.
    3139      */
    3140     DBGCCmdHlpPrintf(pCmdHlp, iEntry != ~0U ? "%DV (index %#x):\n" : "%DV:\n",
    3141                      &VarPDEAddr, iEntry);
    3142     do
    3143     {
    3144         /*
    3145          * Read.
    3146          */
    3147         X86PDEPAE Pde;
    3148         Pde.u = 0;
    3149         rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, cbEntry, &VarPDEAddr, NULL);
    3150         if (VBOX_FAILURE(rc))
    3151             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Reading PDE memory at %DV.\n", &VarPDEAddr);
    3152 
    3153         /*
    3154          * Display.
    3155          */
    3156         if (iEntry != ~0U)
    3157         {
    3158             DBGCCmdHlpPrintf(pCmdHlp, "%03x %DV: ", iEntry, &VarGCPtr);
    3159             iEntry++;
    3160         }
    3161         if (fPSE && Pde.b.u1Size)
    3162             DBGCCmdHlpPrintf(pCmdHlp,
    3163                              fPAE
    3164                              ? "%016llx big phys=%016llx %s %s %s %s %s avl=%02x %s %s %s %s %s"
    3165                              :   "%08llx big phys=%08llx %s %s %s %s %s avl=%02x %s %s %s %s %s",
    3166                              Pde.u,
    3167                              Pde.u & X86_PDE_PAE_PG_MASK,
    3168                              Pde.b.u1Present        ? "p "  : "np",
    3169                              Pde.b.u1Write          ? "w"   : "r",
    3170                              Pde.b.u1User           ? "u"   : "s",
    3171                              Pde.b.u1Accessed       ? "a "  : "na",
    3172                              Pde.b.u1Dirty          ? "d "  : "nd",
    3173                              Pde.b.u3Available,
    3174                              Pde.b.u1Global         ? (fPGE ? "g" : "G") : " ",
    3175                              Pde.b.u1WriteThru      ? "pwt" : "   ",
    3176                              Pde.b.u1CacheDisable   ? "pcd" : "   ",
    3177                              Pde.b.u1PAT            ? "pat" : "",
    3178                              Pde.b.u1NoExecute      ? (fNXE ? "nx" : "NX") : "  ");
    3179         else
    3180             DBGCCmdHlpPrintf(pCmdHlp,
    3181                              fPAE
    3182                              ? "%016llx 4kb phys=%016llx %s %s %s %s %s avl=%02x %s %s %s %s"
    3183                              :   "%08llx 4kb phys=%08llx %s %s %s %s %s avl=%02x %s %s %s %s",
    3184                              Pde.u,
    3185                              Pde.u & X86_PDE_PAE_PG_MASK,
    3186                              Pde.n.u1Present        ? "p "  : "np",
    3187                              Pde.n.u1Write          ? "w"   : "r",
    3188                              Pde.n.u1User           ? "u"   : "s",
    3189                              Pde.n.u1Accessed       ? "a "  : "na",
    3190                              Pde.u & RT_BIT(6)      ? "6 "  : "  ",
    3191                              Pde.n.u3Available,
    3192                              Pde.u & RT_BIT(8)      ? "8"   : " ",
    3193                              Pde.n.u1WriteThru      ? "pwt" : "   ",
    3194                              Pde.n.u1CacheDisable   ? "pcd" : "   ",
    3195                              Pde.u & RT_BIT(7)      ? "7"   : "",
    3196                              Pde.n.u1NoExecute      ? (fNXE ? "nx" : "NX") : "  ");
    3197         if (Pde.u & UINT64_C(0x7fff000000000000))
    3198             DBGCCmdHlpPrintf(pCmdHlp, " weird=%RX64", (Pde.u & UINT64_C(0x7fff000000000000)));
    3199         rc = DBGCCmdHlpPrintf(pCmdHlp, "\n");
    3200         if (VBOX_FAILURE(rc))
    3201             return rc;
    3202 
    3203         /*
    3204          * Advance.
    3205          */
    3206         VarPDEAddr.u.u64Number += cbEntry;
    3207         if (iEntry != ~0U)
    3208             VarGCPtr.u.GCFlat += 1 << (fPAE ? X86_PD_PAE_SHIFT : X86_PD_SHIFT);
    3209     } while (cEntries-- > 0);
    3210 
    3211     NOREF(pResult);
    3212     return VINF_SUCCESS;
    3213 }
    3214 
    3215 
    3216 /**
    3217  * The 'dpdb' command.
    3218  *
    3219  * @returns VBox status.
    3220  * @param   pCmd        Pointer to the command descriptor (as registered).
    3221  * @param   pCmdHlp     Pointer to command helper functions.
    3222  * @param   pVM         Pointer to the current VM (if any).
    3223  * @param   paArgs      Pointer to (readonly) array of arguments.
    3224  * @param   cArgs       Number of arguments in the array.
    3225  */
    3226 static DECLCALLBACK(int) dbgcCmdDumpPageDirBoth(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3227 {
    3228     if (!pVM)
    3229         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    3230     int rc1 = pCmdHlp->pfnExec(pCmdHlp, "dpdg %DV", &paArgs[0]);
    3231     int rc2 = pCmdHlp->pfnExec(pCmdHlp, "dpdh %DV", &paArgs[0]);
    3232     if (VBOX_FAILURE(rc1))
    3233         return rc1;
    3234     NOREF(pCmd); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    3235     return rc2;
    3236 }
    3237 
    3238 
    3239 /**
    3240  * The 'dpg*' commands.
    3241  *
    3242  * @returns VBox status.
    3243  * @param   pCmd        Pointer to the command descriptor (as registered).
    3244  * @param   pCmdHlp     Pointer to command helper functions.
    3245  * @param   pVM         Pointer to the current VM (if any).
    3246  * @param   paArgs      Pointer to (readonly) array of arguments.
    3247  * @param   cArgs       Number of arguments in the array.
    3248  */
    3249 static DECLCALLBACK(int) dbgcCmdDumpPageTable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3250 {
    3251     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    3252 
    3253     /*
    3254      * Validate input.
    3255      */
    3256     if (    cArgs != 1
    3257         ||  (pCmd->pszCmd[3] == 'a' && !DBGCVAR_ISPOINTER(paArgs[0].enmType))
    3258         ||  (pCmd->pszCmd[3] != 'a' && !(paArgs[0].enmType == DBGCVAR_TYPE_NUMBER || DBGCVAR_ISPOINTER(paArgs[0].enmType)))
    3259         )
    3260         return DBGCCmdHlpPrintf(pCmdHlp, "internal error: The parser doesn't do its job properly yet.. It might help to use the '%%' operator.\n");
    3261     if (!pVM)
    3262         return DBGCCmdHlpPrintf(pCmdHlp, "error: No VM.\n");
    3263 
    3264     /*
    3265      * Guest or shadow page tables? Get the paging parameters.
    3266      */
    3267     bool fGuest = pCmd->pszCmd[3] != 'h';
    3268     if (!pCmd->pszCmd[3] || pCmd->pszCmd[3] == 'a')
    3269         fGuest = paArgs[0].enmType == DBGCVAR_TYPE_NUMBER
    3270                ? pDbgc->fRegCtxGuest
    3271                : DBGCVAR_ISGCPOINTER(paArgs[0].enmType);
    3272 
    3273     bool fPAE, fLME, fPSE, fPGE, fNXE;
    3274     uint64_t cr3 = fGuest
    3275                  ? dbgcGetGuestPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE)
    3276                  : dbgcGetShadowPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE);
    3277     const unsigned cbEntry = fPAE ? sizeof(X86PTEPAE) : sizeof(X86PTE);
    3278 
    3279     /*
    3280      * Locate the PTE to start displaying at.
    3281      *
    3282      * The 'dpta' command takes the address of a PTE, while the others are guest
    3283      * virtual address which PTEs should be displayed. So, 'pdta' is rather simple
    3284      * while the others require us to do all the tedious walking thru the paging
    3285      * hierarchy to find the intended PTE.
    3286      */
    3287     unsigned    iEntry = ~0U;           /* The page table index. ~0U for 'dpta'. */
    3288     DBGCVAR     VarGCPtr;               /* The GC address corresponding to the current PTE (iEntry != ~0U). */
    3289     DBGCVAR     VarPTEAddr;             /* The address of the current PTE. */
    3290     unsigned    cEntries;               /* The number of entries to display. */
    3291     unsigned    cEntriesMax;            /* The max number of entries to display. */
    3292     int         rc;
    3293     if (pCmd->pszCmd[3] == 'a')
    3294     {
    3295         VarPTEAddr = paArgs[0];
    3296         switch (VarPTEAddr.enmRangeType)
    3297         {
    3298             case DBGCVAR_RANGE_BYTES:       cEntries = VarPTEAddr.u64Range / cbEntry; break;
    3299             case DBGCVAR_RANGE_ELEMENTS:    cEntries = VarPTEAddr.u64Range; break;
    3300             default:                        cEntries = 10; break;
    3301         }
    3302         cEntriesMax = PAGE_SIZE / cbEntry;
    3303     }
    3304     else
    3305     {
    3306         /*
    3307          * Determin the range.
    3308          */
    3309         switch (paArgs[0].enmRangeType)
    3310         {
    3311             case DBGCVAR_RANGE_BYTES:       cEntries = paArgs[0].u64Range / PAGE_SIZE; break;
    3312             case DBGCVAR_RANGE_ELEMENTS:    cEntries = paArgs[0].u64Range; break;
    3313             default:                        cEntries = 10; break;
    3314         }
    3315 
    3316         /*
    3317          * Normalize the input address, it must be a flat GC address.
    3318          */
    3319         rc = pCmdHlp->pfnEval(pCmdHlp, &VarGCPtr, "%%(%Dv)", &paArgs[0]);
    3320         if (VBOX_FAILURE(rc))
    3321             return DBGCCmdHlpVBoxError(pCmdHlp, rc, "%%(%Dv)", &paArgs[0]);
    3322         if (VarGCPtr.enmType == DBGCVAR_TYPE_HC_FLAT)
    3323         {
    3324             VarGCPtr.u.GCFlat = (uintptr_t)VarGCPtr.u.pvHCFlat;
    3325             VarGCPtr.enmType = DBGCVAR_TYPE_GC_FLAT;
    3326         }
    3327         VarGCPtr.u.GCFlat &= ~(RTGCPTR)PAGE_OFFSET_MASK;
    3328 
    3329         /*
    3330          * Do the paging walk until we get to the page table.
    3331          */
    3332         DBGCVAR VarCur;
    3333         if (fGuest)
    3334             DBGCVAR_INIT_GC_PHYS(&VarCur, cr3);
    3335         else
    3336             DBGCVAR_INIT_HC_PHYS(&VarCur, cr3);
    3337         if (fLME)
    3338         {
    3339             /* Page Map Level 4 Lookup. */
    3340             /* Check if it's a valid address first? */
    3341             VarCur.u.u64Number &= X86_PTE_PAE_PG_MASK;
    3342             VarCur.u.u64Number += (((uint64_t)VarGCPtr.u.GCFlat >> X86_PML4_SHIFT) & X86_PML4_MASK) * sizeof(X86PML4E);
    3343             X86PML4E Pml4e;
    3344             rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pml4e, sizeof(Pml4e), &VarCur, NULL);
    3345             if (VBOX_FAILURE(rc))
    3346                 return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PML4E memory at %DV.\n", &VarCur);
    3347             if (!Pml4e.n.u1Present)
    3348                 return DBGCCmdHlpPrintf(pCmdHlp, "Page directory pointer table is not present for %Dv.\n", &VarGCPtr);
    3349 
    3350             VarCur.u.u64Number = Pml4e.u & X86_PML4E_PG_MASK;
    3351             Assert(fPAE);
    3352         }
    3353         if (fPAE)
    3354         {
    3355             /* Page directory pointer table. */
    3356             X86PDPE Pdpe;
    3357             VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK) * sizeof(Pdpe);
    3358             rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pdpe, sizeof(Pdpe), &VarCur, NULL);
    3359             if (VBOX_FAILURE(rc))
    3360                 return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDPE memory at %DV.\n", &VarCur);
    3361             if (!Pdpe.n.u1Present)
    3362                 return DBGCCmdHlpPrintf(pCmdHlp, "Page directory is not present for %Dv.\n", &VarGCPtr);
    3363 
    3364             VarCur.u.u64Number = Pdpe.u & X86_PDPE_PG_MASK;
    3365 
    3366             /* Page directory (PAE). */
    3367             X86PDEPAE Pde;
    3368             VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK) * sizeof(Pde);
    3369             rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, sizeof(Pde), &VarCur, NULL);
    3370             if (VBOX_FAILURE(rc))
    3371                 return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDE memory at %DV.\n", &VarCur);
    3372             if (!Pde.n.u1Present)
    3373                 return DBGCCmdHlpPrintf(pCmdHlp, "Page table is not present for %Dv.\n", &VarGCPtr);
    3374             if (fPSE && Pde.n.u1Size)
    3375                 return pCmdHlp->pfnExec(pCmdHlp, "dpd%s %Dv L3", &pCmd->pszCmd[3], &VarGCPtr);
    3376 
    3377             iEntry = (VarGCPtr.u.GCFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK;
    3378             VarPTEAddr = VarCur;
    3379             VarPTEAddr.u.u64Number = Pde.u & X86_PDE_PAE_PG_MASK;
    3380             VarPTEAddr.u.u64Number += iEntry * sizeof(X86PTEPAE);
    3381         }
    3382         else
    3383         {
    3384             /* Page directory (legacy). */
    3385             X86PDE Pde;
    3386             VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PD_SHIFT) & X86_PD_MASK) * sizeof(Pde);
    3387             rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, sizeof(Pde), &VarCur, NULL);
    3388             if (VBOX_FAILURE(rc))
    3389                 return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDE memory at %DV.\n", &VarCur);
    3390             if (!Pde.n.u1Present)
    3391                 return DBGCCmdHlpPrintf(pCmdHlp, "Page table is not present for %Dv.\n", &VarGCPtr);
    3392             if (fPSE && Pde.n.u1Size)
    3393                 return pCmdHlp->pfnExec(pCmdHlp, "dpd%s %Dv L3", &pCmd->pszCmd[3], &VarGCPtr);
    3394 
    3395             iEntry = (VarGCPtr.u.GCFlat >> X86_PT_SHIFT) & X86_PT_MASK;
    3396             VarPTEAddr = VarCur;
    3397             VarPTEAddr.u.u64Number = Pde.u & X86_PDE_PG_MASK;
    3398             VarPTEAddr.u.u64Number += iEntry * sizeof(X86PTE);
    3399         }
    3400         cEntriesMax = (PAGE_SIZE - iEntry) / cbEntry;
    3401         iEntry /= cbEntry;
    3402     }
    3403 
    3404     /* adjust cEntries */
    3405     cEntries = RT_MAX(1, cEntries);
    3406     cEntries = RT_MIN(cEntries, cEntriesMax);
    3407 
    3408     /*
    3409      * The display loop.
    3410      */
    3411     DBGCCmdHlpPrintf(pCmdHlp, iEntry != ~0U ? "%DV (base %DV / index %#x):\n" : "%DV:\n",
    3412                      &VarPTEAddr, &VarGCPtr, iEntry);
    3413     do
    3414     {
    3415         /*
    3416          * Read.
    3417          */
    3418         X86PTEPAE Pte;
    3419         Pte.u = 0;
    3420         rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pte, cbEntry, &VarPTEAddr, NULL);
    3421         if (VBOX_FAILURE(rc))
    3422             return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PTE memory at %DV.\n", &VarPTEAddr);
    3423 
    3424         /*
    3425          * Display.
    3426          */
    3427         if (iEntry != ~0U)
    3428         {
    3429             DBGCCmdHlpPrintf(pCmdHlp, "%03x %DV: ", iEntry, &VarGCPtr);
    3430             iEntry++;
    3431         }
    3432         DBGCCmdHlpPrintf(pCmdHlp,
    3433                          fPAE
    3434                          ? "%016llx 4kb phys=%016llx %s %s %s %s %s avl=%02x %s %s %s %s %s"
    3435                          :   "%08llx 4kb phys=%08llx %s %s %s %s %s avl=%02x %s %s %s %s %s",
    3436                          Pte.u,
    3437                          Pte.u & X86_PTE_PAE_PG_MASK,
    3438                          Pte.n.u1Present         ? "p " : "np",
    3439                          Pte.n.u1Write           ? "w" : "r",
    3440                          Pte.n.u1User            ? "u" : "s",
    3441                          Pte.n.u1Accessed        ? "a " : "na",
    3442                          Pte.n.u1Dirty           ? "d " : "nd",
    3443                          Pte.n.u3Available,
    3444                          Pte.n.u1Global          ? (fPGE ? "g" : "G") : " ",
    3445                          Pte.n.u1WriteThru       ? "pwt" : "   ",
    3446                          Pte.n.u1CacheDisable    ? "pcd" : "   ",
    3447                          Pte.n.u1PAT             ? "pat" : "   ",
    3448                          Pte.n.u1NoExecute       ? (fNXE ? "nx" : "NX") : "  "
    3449                          );
    3450         if (Pte.u & UINT64_C(0x7fff000000000000))
    3451             DBGCCmdHlpPrintf(pCmdHlp, " weird=%RX64", (Pte.u & UINT64_C(0x7fff000000000000)));
    3452         rc = DBGCCmdHlpPrintf(pCmdHlp, "\n");
    3453         if (VBOX_FAILURE(rc))
    3454             return rc;
    3455 
    3456         /*
    3457          * Advance.
    3458          */
    3459         VarPTEAddr.u.u64Number += cbEntry;
    3460         if (iEntry != ~0U)
    3461             VarGCPtr.u.GCFlat += PAGE_SIZE;
    3462     } while (cEntries-- > 0);
    3463 
    3464     NOREF(pResult);
    3465     return VINF_SUCCESS;
    3466 }
    3467 
    3468 
    3469 /**
    3470  * The 'dptb' command.
    3471  *
    3472  * @returns VBox status.
    3473  * @param   pCmd        Pointer to the command descriptor (as registered).
    3474  * @param   pCmdHlp     Pointer to command helper functions.
    3475  * @param   pVM         Pointer to the current VM (if any).
    3476  * @param   paArgs      Pointer to (readonly) array of arguments.
    3477  * @param   cArgs       Number of arguments in the array.
    3478  */
    3479 static DECLCALLBACK(int) dbgcCmdDumpPageTableBoth(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3480 {
    3481     if (!pVM)
    3482         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    3483     int rc1 = pCmdHlp->pfnExec(pCmdHlp, "dptg %DV", &paArgs[0]);
    3484     int rc2 = pCmdHlp->pfnExec(pCmdHlp, "dpth %DV", &paArgs[0]);
    3485     if (VBOX_FAILURE(rc1))
    3486         return rc1;
    3487     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    3488     return rc2;
    3489 }
    3490 
    3491 
    3492 /**
    3493  * The 'dt' command.
    3494  *
    3495  * @returns VBox status.
    3496  * @param   pCmd        Pointer to the command descriptor (as registered).
    3497  * @param   pCmdHlp     Pointer to command helper functions.
    3498  * @param   pVM         Pointer to the current VM (if any).
    3499  * @param   paArgs      Pointer to (readonly) array of arguments.
    3500  * @param   cArgs       Number of arguments in the array.
    3501  */
    3502 static DECLCALLBACK(int) dbgcCmdDumpTSS(PCDBGCCMD /*pCmd*/, PDBGCCMDHLP pCmdHlp, PVM /*pVM*/, PCDBGCVAR /*paArgs*/, unsigned /*cArgs*/, PDBGCVAR /*pResult*/)
    3503 {
    3504     /*
    3505      * We can get a TSS selector (number), a far pointer using a TSS selector, or some kind of TSS pointer.
    3506      */
    3507 
    3508     /** @todo */
    3509     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "dt is not implemented yet, feel free to do it. \n");
    3510 }
    3511 
    3512 
    3513 /**
    3514  * The 'm' command.
    3515  *
    3516  * @returns VBox status.
    3517  * @param   pCmd        Pointer to the command descriptor (as registered).
    3518  * @param   pCmdHlp     Pointer to command helper functions.
    3519  * @param   pVM         Pointer to the current VM (if any).
    3520  * @param   paArgs      Pointer to (readonly) array of arguments.
    3521  * @param   cArgs       Number of arguments in the array.
    3522  */
    3523 static DECLCALLBACK(int) dbgcCmdMemoryInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3524 {
    3525     pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Address: %DV\n", &paArgs[0]);
    3526     if (!pVM)
    3527         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    3528     int rc1 = pCmdHlp->pfnExec(pCmdHlp, "dpdg %DV", &paArgs[0]);
    3529     int rc2 = pCmdHlp->pfnExec(pCmdHlp, "dpdh %DV", &paArgs[0]);
    3530     int rc3 = pCmdHlp->pfnExec(pCmdHlp, "dptg %DV", &paArgs[0]);
    3531     int rc4 = pCmdHlp->pfnExec(pCmdHlp, "dpth %DV", &paArgs[0]);
    3532     if (VBOX_FAILURE(rc1))
    3533         return rc1;
    3534     if (VBOX_FAILURE(rc2))
    3535         return rc2;
    3536     if (VBOX_FAILURE(rc3))
    3537         return rc3;
    3538     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    3539     return rc4;
    3540771}
    3541772
     
    3654885    return rc;
    3655886}
    3656 
    3657 
    3658 /**
    3659  * The 's' command.
    3660  *
    3661  * @returns VBox status.
    3662  * @param   pCmd        Pointer to the command descriptor (as registered).
    3663  * @param   pCmdHlp     Pointer to command helper functions.
    3664  * @param   pVM         Pointer to the current VM (if any).
    3665  * @param   paArgs      Pointer to (readonly) array of arguments.
    3666  * @param   cArgs       Number of arguments in the array.
    3667  */
    3668 static DECLCALLBACK(int) dbgcCmdSearchMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    3669 {
    3670     /* check that the parser did what it's supposed to do. */
    3671     if (    cArgs != 1
    3672         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    3673         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "parser error\n");
    3674     return -1;
    3675 }
    3676 
    3677887
    3678888
     
    39501160
    39511161/**
    3952  * List near symbol.
    3953  *
    3954  * @returns VBox status code.
    3955  * @param   pCmdHlp     Pointer to command helper functions.
    3956  * @param   pVM         Pointer to the current VM (if any).
    3957  * @param   pArg        Pointer to the address or symbol to lookup.
    3958  */
    3959 static int dbgcDoListNear(PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR pArg, PDBGCVAR pResult)
    3960 {
    3961     dbgcVarSetGCFlat(pResult, 0);
    3962 
    3963     DBGFSYMBOL  Symbol;
    3964     int         rc;
    3965     if (pArg->enmType == DBGCVAR_TYPE_SYMBOL)
    3966     {
    3967         /*
    3968          * Lookup the symbol address.
    3969          */
    3970         rc = DBGFR3SymbolByName(pVM, pArg->u.pszString, &Symbol);
    3971         if (VBOX_FAILURE(rc))
    3972             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3SymbolByName(, %s,)\n", pArg->u.pszString);
    3973 
    3974         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%VGv %s\n", (RTGCUINTPTR)Symbol.Value, Symbol.szName); /** @todo remove the RTUINGCPTR cast once DBGF got correct interfaces! */
    3975         dbgcVarSetGCFlatByteRange(pResult, Symbol.Value, Symbol.cb);
    3976     }
    3977     else
    3978     {
    3979         /*
    3980          * Convert it to a flat GC address and lookup that address.
    3981          */
    3982         DBGCVAR AddrVar;
    3983         rc = pCmdHlp->pfnEval(pCmdHlp, &AddrVar, "%%(%DV)", pArg);
    3984         if (VBOX_FAILURE(rc))
    3985             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%%(%DV)\n", pArg);
    3986 
    3987         dbgcVarSetVar(pResult, &AddrVar);
    3988 
    3989         RTGCINTPTR offDisp = 0;
    3990         rc = DBGFR3SymbolByAddr(pVM, AddrVar.u.GCFlat, &offDisp, &Symbol);
    3991         if (VBOX_FAILURE(rc))
    3992             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3SymbolByAddr(, %VGv,,)\n", AddrVar.u.GCFlat);
    3993 
    3994         if (!offDisp)
    3995             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%DV %s", &AddrVar, Symbol.szName);
    3996         else if (offDisp > 0)
    3997             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%DV %s + %RGv", &AddrVar, Symbol.szName, offDisp);
    3998         else
    3999             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%DV %s - %RGv", &AddrVar, Symbol.szName, -offDisp);
    4000         if ((RTGCINTPTR)Symbol.cb > -offDisp)
    4001         {
    4002             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " LB %RGv\n", Symbol.cb + offDisp);
    4003             dbgcVarSetByteRange(pResult, Symbol.cb + offDisp);
    4004         }
    4005         else
    4006         {
    4007             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\n");
    4008             dbgcVarSetNoRange(pResult);
    4009         }
    4010     }
    4011 
    4012     return rc;
    4013 }
    4014 
    4015 
    4016 /**
    4017  * The 'ln' (listnear) command.
    4018  *
    4019  * @returns VBox status.
    4020  * @param   pCmd        Pointer to the command descriptor (as registered).
    4021  * @param   pCmdHlp     Pointer to command helper functions.
    4022  * @param   pVM         Pointer to the current VM (if any).
    4023  * @param   paArgs      Pointer to (readonly) array of arguments.
    4024  * @param   cArgs       Number of arguments in the array.
    4025  */
    4026 static DECLCALLBACK(int) dbgcCmdListNear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    4027 {
    4028     dbgcVarSetGCFlat(pResult, 0);
    4029     if (!cArgs)
    4030     {
    4031         /*
    4032          * Current cs:eip symbol.
    4033          */
    4034         DBGCVAR AddrVar;
    4035         int rc = pCmdHlp->pfnEval(pCmdHlp, &AddrVar, "%%(cs:eip)");
    4036         if (VBOX_FAILURE(rc))
    4037             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%%(cs:eip)\n");
    4038         return dbgcDoListNear(pCmdHlp, pVM, &AddrVar, pResult);
    4039     }
    4040 
    4041     /*
    4042      * Iterate arguments.
    4043      */
    4044     for (unsigned iArg = 0; iArg < cArgs; iArg++)
    4045     {
    4046         int rc = dbgcDoListNear(pCmdHlp, pVM, &paArgs[iArg], pResult);
    4047         if (VBOX_FAILURE(rc))
    4048             return rc;
    4049     }
    4050 
    4051     NOREF(pCmd); NOREF(pResult);
    4052     return VINF_SUCCESS;
    4053 }
    4054 
    4055 
    4056 /**
    40571162 * The 'loadsyms' command.
    40581163 *
     
    67343839
    67353840/** @todo move me!*/
    6736 static void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat)
     3841void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat)
    67373842{
    67383843    if (pVar)
     
    67473852
    67483853/** @todo move me!*/
    6749 static void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb)
     3854void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb)
    67503855{
    67513856    if (pVar)
     
    67603865
    67613866/** @todo move me!*/
    6762 static void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2)
     3867void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2)
    67633868{
    67643869    if (pVar)
     
    67783883
    67793884/** @todo move me!*/
    6780 static void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb)
     3885void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb)
    67813886{
    67823887    if (pVar)
     
    67893894
    67903895/** @todo move me!*/
    6791 static void dbgcVarSetNoRange(PDBGCVAR pVar)
     3896void dbgcVarSetNoRange(PDBGCVAR pVar)
    67923897{
    67933898    if (pVar)
     
    68563961 * Adds a breakpoint to the DBGC breakpoint list.
    68573962 */
    6858 static int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
     3963int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
    68593964{
    68603965    /*
     
    68943999 * @param   pszCmd      The new command.
    68954000 */
    6896 static int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
     4001int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
    68974002{
    68984003    /*
     
    69394044 * @param   iBp         The breakpoint to delete.
    69404045 */
    6941 static int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp)
     4046int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp)
    69424047{
    69434048    /*
     
    69724077 * @param   iBp         The breakpoint to get.
    69734078 */
    6974 static PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp)
     4079PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp)
    69754080{
    69764081    /*
     
    69954100 * @param   iBp         The breakpoint to execute.
    69964101 */
    6997 static int dbgcBpExec(PDBGC pDbgc, RTUINT iBp)
     4102int dbgcBpExec(PDBGC pDbgc, RTUINT iBp)
    69984103{
    69994104    /*
     
    72224327 * @param   pszSymbol   The symbol name.
    72234328 */
    7224 static PCDBGCSYM dbgcLookupRegisterSymbol(PDBGC pDbgc, const char *pszSymbol)
     4329PCDBGCSYM dbgcLookupRegisterSymbol(PDBGC pDbgc, const char *pszSymbol)
    72254330{
    72264331    for (unsigned iSym = 0; iSym < ELEMENTS(g_aSyms); iSym++)
     
    88755980    pDbgc->pszEmulation     = "CodeView/WinDbg";
    88765981    pDbgc->paEmulationCmds  = &g_aCmdsCodeView[0];
    8877     pDbgc->cEmulationCmds   = RT_ELEMENTS(g_aCmdsCodeView);
     5982    pDbgc->cEmulationCmds   = g_cCmdsCodeView;
    88785983    //pDbgc->fLog             = false;
    88795984    pDbgc->fRegCtxGuest     = true;
  • trunk/src/VBox/Debugger/Makefile.kmk

    r4071 r5669  
    66#
    77#  Copyright (C) 2006-2007 innotek GmbH
    8 # 
     8#
    99#  This file is part of VirtualBox Open Source Edition (OSE), as
    1010#  available from http://www.virtualbox.org. This file is free software;
     
    3636Debugger_SOURCES   = \
    3737        DBGConsole.cpp \
     38        DBGCEmulateCodeView.cpp \
    3839        DBGCTcp.cpp
    3940
     
    6162VBoxDbg_DEFS = IN_DBG_R3
    6263VBoxDbg_CXXFLAGS.linux = $(TEMPLATE_VBOXQTGUI_CXXFLAGS.linux) -O2
     64VBoxDbg_CXXFLAGS.win = -wd4244
    6365VBoxDbg_INCS = \
    6466        . \
     
    9597        VBoxDbgConsole.cpp \
    9698        VBoxDbgStats.cpp \
    97         DBGConsole.cpp
     99        DBGConsole.cpp \
     100        DBGCEmulateCodeView.cpp
    98101
    99102VBoxDbg_LIBS = $(LIB_VMM)
Note: See TracChangeset for help on using the changeset viewer.

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