DBGConsole.cpp revision 9cb5c820d98d18e0e42a98c1357a21fd2eaaa576
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * DBGC - Debugger Console.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Copyright (C) 2006-2007 innotek GmbH
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * This file is part of VirtualBox Open Source Edition (OSE), as
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * available from http://www.virtualbox.org. This file is free software;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * you can redistribute it and/or modify it under the terms of the GNU
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * General Public License as published by the Free Software Foundation,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * distribution. VirtualBox OSE is distributed in the hope that it will
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * be useful, but WITHOUT ANY WARRANTY of any kind.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy/** @page pg_dbgc DBGC - The Debug Console
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * The debugger console is a first attempt to make some interactive
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * debugging facilities for the VirtualBox backend (i.e. the VM). At a later
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * stage we'll make a fancy gui around this, but for the present a telnet (or
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * serial terminal) will have to suffice.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * The debugger is only built into the VM with debug builds or when
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * VBOX_WITH_DEBUGGER is defined. There might be need for \#ifdef'ing on this
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * define to enable special debugger hooks, but the general approach is to
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * make generic interfaces. The individual components also can register
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * external commands, and such code must be within \#ifdef.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * @section sec_dbgc_op Operation (intentions)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * The console will process commands in a manner similar to the OS/2 and
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * windows kernel debuggers. This means ';' is a command separator and
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * that when possible we'll use the same command names as these two uses.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * @subsection sec_dbg_op_numbers Numbers
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Numbers are hexadecimal unless specified with a prefix indicating
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * elsewise. Prefixes:
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - '0x' - hexadecimal.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - '0i' - decimal
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - '0t' - octal.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - '0y' - binary.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * @subsection sec_dbg_op_address Addressing modes
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - Default is flat. For compatability '%' also means flat.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - Segmented addresses are specified selector:offset.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - Physical addresses are specified using '%%'.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * - The default target for the addressing is the guest context, the '#'
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * will override this and set it to the host.
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * @subsection sec_dbg_op_evalution Evaluation
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * As time permits support will be implemented support for a subset of the C
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * binary operators, starting with '+', '-', '*' and '/'. Support for variables
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * are provided thru commands 'set' and 'unset' and the unary operator '$'. The
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * unary '@' operator will indicate function calls. The debugger needs a set of
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * memory read functions, but we might later extend this to allow registration of
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * external functions too.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * A special command '?' will then be added which evalutates a given expression
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * and prints it in all the different formats.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * @subsection sec_dbg_op_registers Registers
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Registers are addressed using their name. Some registers which have several fields
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * (like gdtr) will have separate names indicating the different fields. The default
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * register set is the guest one. To access the hypervisor register one have to
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * prefix the register names with '.'.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * @subsection sec_dbg_op_commands Commands
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * The commands are all lowercase, case sensitive, and starting with a letter. We will
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * later add some special commands ('?' for evaulation) and perhaps command classes ('.', '!')
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * @section sec_dbg_tasks Tasks
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * To implement DBGT and instrument VMM for basic state inspection and log
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * viewing, the follwing task must be executed:
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * -# Basic threading layer in RT.
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * -# Basic tcpip server abstration in RT.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * -# Write DBGC.
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy * -# Write DBCTCP.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * -# Integrate with VMM and the rest.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * -# Start writing DBGF (VMM).
#include <stdlib.h>
#include <stdio.h>
#include "DBGCInternal.h"
static void dbgcInitOpCharBitMap(void)
int rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &pDbgc->achInput[0], sizeof(pDbgc->achInput) - 1, &cbRead);
return rc;
if (psz)
int rc = 0;
if (!cbLeft)
return rc;
while (cbRead-- > 0)
switch (ch)
switch (ch)
return rc;
if (pSymDesc)
return VERR_PARSE_WRITEONLY_SYMBOL;
switch (enmType)
case DBGCVAR_TYPE_GC_FLAT:
case DBGCVAR_TYPE_GC_FAR:
case DBGCVAR_TYPE_ANY:
return VINF_SUCCESS;
case DBGCVAR_TYPE_NUMBER:
return VINF_SUCCESS;
case DBGCVAR_TYPE_GC_PHYS:
case DBGCVAR_TYPE_HC_FAR:
case DBGCVAR_TYPE_HC_FLAT:
case DBGCVAR_TYPE_HC_PHYS:
return VERR_INVALID_PARAMETER;
return VERR_PARSE_NOT_IMPLEMENTED;
return VERR_PARSE_UNBALANCED_QUOTE;
cchExpr--;
pszExpr++;
char ch;
return VERR_PARSE_INVALID_NUMBER;
return VERR_PARSE_NUMBER_TOO_BIG;
pszExpr++;
case DBGCVAR_CAT_ANY:
return VINF_SUCCESS;
return VERR_PARSE_NO_RANGE_ALLOWED;
case DBGCVAR_CAT_POINTER:
case DBGCVAR_TYPE_GC_FLAT:
case DBGCVAR_TYPE_GC_FAR:
case DBGCVAR_TYPE_GC_PHYS:
case DBGCVAR_TYPE_HC_FLAT:
case DBGCVAR_TYPE_HC_FAR:
case DBGCVAR_TYPE_HC_PHYS:
return VINF_SUCCESS;
case DBGCVAR_TYPE_SYMBOL:
case DBGCVAR_TYPE_STRING:
return rc;
case DBGCVAR_TYPE_NUMBER:
return VINF_SUCCESS;
return VERR_PARSE_NO_RANGE_ALLOWED;
case DBGCVAR_CAT_GC_POINTER:
case DBGCVAR_TYPE_GC_FLAT:
case DBGCVAR_TYPE_GC_FAR:
case DBGCVAR_TYPE_GC_PHYS:
return VINF_SUCCESS;
case DBGCVAR_TYPE_HC_FLAT:
case DBGCVAR_TYPE_HC_FAR:
case DBGCVAR_TYPE_HC_PHYS:
return VERR_PARSE_CONVERSION_FAILED;
case DBGCVAR_TYPE_SYMBOL:
case DBGCVAR_TYPE_STRING:
return rc;
case DBGCVAR_TYPE_NUMBER:
return VINF_SUCCESS;
return VERR_PARSE_NO_RANGE_ALLOWED;
case DBGCVAR_CAT_NUMBER:
case DBGCVAR_TYPE_NUMBER:
return VINF_SUCCESS;
case DBGCVAR_TYPE_SYMBOL:
case DBGCVAR_TYPE_STRING:
return rc;
case DBGCVAR_CAT_STRING:
case DBGCVAR_TYPE_SYMBOL:
case DBGCVAR_TYPE_STRING:
return VINF_SUCCESS;
case DBGCVAR_CAT_SYMBOL:
case DBGCVAR_TYPE_STRING:
case DBGCVAR_TYPE_SYMBOL:
return VINF_SUCCESS;
return VERR_PARSE_NO_ARGUMENT_MATCH;
return VERR_PARSE_TOO_FEW_ARGUMENTS;
return VERR_PARSE_TOO_MANY_ARGUMENTS;
unsigned cCurDesc = 0;
unsigned iVar = 0;
unsigned iVarDesc = 0;
return VERR_PARSE_TOO_MANY_ARGUMENTS;
iVarDesc++;
return VERR_PARSE_TOO_MANY_ARGUMENTS;
cCurDesc = 0;
cCurDesc++;
cCurDesc = 0;
iVar++;
return VERR_PARSE_TOO_FEW_ARGUMENTS;
cCurDesc = 0;
iVarDesc++;
int rc = 0;
if (pOp)
return VERR_PARSE_UNEXPECTED_OPERATOR;
pszExpr2++;
if (!*pszExpr2)
pszFunEnd++;
if (pszFunEnd)
if (fExternal)
if (!pFun)
return VERR_PARSE_FUNCTION_NOT_FOUND;
return VERR_PARSE_NOT_A_FUNCTION;
if (!rc)
rc = dbgcEvalSubMatchVars(pDbgc, pFun->cArgsMin, pFun->cArgsMax, pFun->paArgDescs, pFun->cArgDescs, &Arg, 1);
if (!rc)
psz++;
if (!*psz)
return rc;
if (!*pszExpr)
return VERR_PARSE_EMPTY_ARGUMENT;
char ch;
cPar++;
if (cPar <= 0)
cPar--;
psz++;
if (ch)
pszExpr++;
if (!*pszExpr)
return VERR_PARSE_EMPTY_ARGUMENT;
unsigned cBinaryOps = 0;
unsigned cPar = 0;
char ch;
bool fBinary = false;
cPar++;
fBinary = false;
if (cPar <= 0)
cPar--;
fBinary = true;
: NULL;
if (pOp)
return VERR_PARSE_UNEXPECTED_OPERATOR;
if (!pOpSplit)
else if (fBinary)
cBinaryOps++;
fBinary = false;
fBinary = true;
psz++;
int rc;
if ( cBinaryOps
else if (cBinaryOps)
return rc;
static int dbgcProcessArguments(PDBGC pDbgc, PCDBGCCMD pCmd, char *pszArgs, PDBGCVAR paArgs, unsigned cArgs, unsigned *pcArgs)
*pcArgs = 0;
pszArgs++;
if (!*pszArgs)
return VERR_PARSE_TOO_FEW_ARGUMENTS;
return VERR_PARSE_TOO_MANY_ARGUMENTS;
*pcArgs = 0;
return VERR_PARSE_TOO_MANY_ARGUMENTS;
return VERR_PARSE_ARGUMENT_OVERFLOW;
int cPar = 0;
char ch;
bool fBinary = false;
if (chQuote)
return VERR_PARSE_UNBALANCED_QUOTE;
if (cPar)
if (chQuote)
cPar++;
fBinary = false;
if (!cPar)
cPar--;
fBinary = true;
psz++;
psz++;
fBinary = false;
if (pOp)
psz++;
fBinary = false;
fBinary = true;
psz++;
return rc;
pArg++;
(*pcArgs)++;
pszArgs++;
} while (*pszArgs);
return dbgcEvalSubMatchVars(pDbgc, pCmd->cArgsMin, pCmd->cArgsMax, pCmd->paArgDescs, pCmd->cArgDescs, pArg0, pArg - pArg0);
if (fExternal)
pszArgs++;
unsigned cArgs;
int rc = dbgcProcessArguments(pDbgc, pCmd, pszArgs, &pDbgc->aArgs[pDbgc->iArg], ELEMENTS(pDbgc->aArgs) - pDbgc->iArg, &cArgs);
if (!rc)
switch (rc)
"Syntax error: Too few arguments. Minimum is %d for command '%s'.\n", pCmd->cArgsMin, pCmd->pszCmd);
"Syntax error: Too many arguments. Maximum is %d for command '%s'.\n", pCmd->cArgsMax, pCmd->pszCmd);
"Syntax error: Ivalid numeric value (argument %d). If a string was the intention, then quote it.\n", cArgs);
case VERR_PARSE_NO_MEMORY:
"Error: Couldn't satisfy a request for a specific result type (argument %d). (Usually applies to symbols)\n", cArgs);
return rc;
rc = 0;
return rc;
int rc = 0;
char ch;
pszTrg++;
if (rc)
return rc;
return rc;
return rc;
switch (enmCtx)
return rc;
bool fPrintPrompt = true;
case DBGFEVENT_HALT_DONE:
case DBGFEVENT_FATAL_ERROR:
case DBGFEVENT_BREAKPOINT:
switch (rc)
case VERR_DBGC_BP_NOT_FOUND:
case VINF_DBGC_BP_NO_COMMAND:
case VINF_BUFFER_OVERFLOW:
rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Breakpoint %u! Command too long to execute! (%s)\n",
case DBGFEVENT_STEPPED:
case DBGFEVENT_STEPPED_HYPER:
rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf event: Single step! (%s)\n", dbgcGetEventCtx(pEvent->enmCtx));
case DBGFEVENT_DEV_STOP:
case DBGFEVENT_TERMINATING:
rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\ndbgf/dbgc error: Unknown event %d!\n", pEvent->enmType);
return rc;
if (!pDbgc)
return VERR_NO_MEMORY;
goto l_failure;
rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to attach to VM %p\n", pDbgc->pVM);
goto l_failure;
goto l_failure;
for (rc = 0;;)
return rc;