summaryrefslogtreecommitdiff
path: root/src/VBox/Debugger/DBGConsole.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Debugger/DBGConsole.cpp')
-rw-r--r--src/VBox/Debugger/DBGConsole.cpp1232
1 files changed, 70 insertions, 1162 deletions
diff --git a/src/VBox/Debugger/DBGConsole.cpp b/src/VBox/Debugger/DBGConsole.cpp
index 03115487e..e8804020b 100644
--- a/src/VBox/Debugger/DBGConsole.cpp
+++ b/src/VBox/Debugger/DBGConsole.cpp
@@ -1,10 +1,10 @@
-/* $Id: DBGConsole.cpp $ */
+/* $Id: DBGConsole.cpp 35829 2011-02-03 10:18:53Z vboxsync $ */
/** @file
* DBGC - Debugger Console.
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -133,67 +133,24 @@
#define LOG_GROUP LOG_GROUP_DBGC
#include <VBox/dbg.h>
#include <VBox/vmm/dbgf.h>
-#include <VBox/vmm/vm.h>
-#include <VBox/vmm/vmm.h>
-#include <VBox/vmm/mm.h>
-#include <VBox/vmm/pgm.h>
-#include <VBox/vmm/selm.h>
-#include <VBox/dis.h>
-#include <VBox/param.h>
#include <VBox/err.h>
#include <VBox/log.h>
#include <iprt/asm.h>
-#include <iprt/alloca.h>
#include <iprt/assert.h>
#include <iprt/mem.h>
#include <iprt/string.h>
-#include <iprt/ctype.h>
-
-#include <stdlib.h>
-#include <stdio.h>
#include "DBGCInternal.h"
#include "DBGPlugIns.h"
/*******************************************************************************
-* Global Variables *
-*******************************************************************************/
-/** Bitmap where set bits indicates the characters the may start an operator name. */
-static uint32_t g_bmOperatorChars[256 / (4*8)];
-
-
-/*******************************************************************************
* Internal Functions *
*******************************************************************************/
static int dbgcProcessLog(PDBGC pDbgc);
-
-/**
- * Initializes g_bmOperatorChars.
- */
-static void dbgcInitOpCharBitMap(void)
-{
- memset(g_bmOperatorChars, 0, sizeof(g_bmOperatorChars));
- for (unsigned iOp = 0; iOp < g_cOps; iOp++)
- ASMBitSet(&g_bmOperatorChars[0], (uint8_t)g_aOps[iOp].szName[0]);
-}
-
-
-/**
- * Checks whether the character may be the start of an operator.
- *
- * @returns true/false.
- * @param ch The character.
- */
-DECLINLINE(bool) dbgcIsOpChar(char ch)
-{
- return ASMBitTest(&g_bmOperatorChars[0], (uint8_t)ch);
-}
-
-
/**
* Resolves a symbol (or tries to do so at least).
*
@@ -201,15 +158,18 @@ DECLINLINE(bool) dbgcIsOpChar(char ch)
* @returns VBox status on failure.
* @param pDbgc The debug console instance.
* @param pszSymbol The symbol name.
- * @param enmType The result type.
+ * @param enmType The result type. Specifying DBGCVAR_TYPE_GC_FAR may
+ * cause failure, avoid it.
* @param pResult Where to store the result.
*/
int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGCVAR pResult)
{
+ int rc;
+
/*
* Builtin?
*/
- PCDBGCSYM pSymDesc = dbgcLookupRegisterSymbol(pDbgc, pszSymbol);
+ PCDBGCSYM pSymDesc = dbgcLookupRegisterSymbol(pDbgc, pszSymbol);
if (pSymDesc)
{
if (!pSymDesc->pfnGet)
@@ -217,37 +177,80 @@ int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGC
return pSymDesc->pfnGet(pSymDesc, &pDbgc->CmdHlp, enmType, pResult);
}
+ /*
+ * A typical register? (Guest only)
+ */
+ static const char s_szSixLetterRegisters[] =
+ "rflags;eflags;"
+ ;
+ static const char s_szThreeLetterRegisters[] =
+ "eax;rax;" "r10;" "r8d;r8w;r8b;" "cr0;" "dr0;"
+ "ebx;rbx;" "r11;" "r9d;r9w;r8b;" "dr1;"
+ "ecx;rcx;" "r12;" "cr2;" "dr2;"
+ "edx;rdx;" "r13;" "cr3;" "dr3;"
+ "edi;rdi;dil;" "r14;" "cr4;" "dr4;"
+ "esi;rsi;sil;" "r15;" "cr8;"
+ "ebp;rbp;"
+ "esp;rsp;" "dr6;"
+ "rip;eip;" "dr7;"
+ "efl;"
+ ;
+ static const char s_szTwoLetterRegisters[] =
+ "ax;al;ah;" "r8;"
+ "bx;bl;bh;" "r9;"
+ "cx;cl;ch;" "cs;"
+ "dx;dl;dh;" "ds;"
+ "di;" "es;"
+ "si;" "fs;"
+ "bp;" "gs;"
+ "sp;" "ss;"
+ "ip;"
+ ;
+ size_t const cchSymbol = strlen(pszSymbol);
+ if ( (cchSymbol == 2 && strstr(s_szTwoLetterRegisters, pszSymbol))
+ || (cchSymbol == 3 && strstr(s_szThreeLetterRegisters, pszSymbol))
+ || (cchSymbol == 6 && strstr(s_szSixLetterRegisters, pszSymbol)))
+ {
+ if (!strchr(pszSymbol, ';'))
+ {
+ DBGCVAR Var;
+ DBGCVAR_INIT_STRING(&Var, pszSymbol);
+ rc = dbgcOpRegister(pDbgc, &Var, pResult);
+ if (RT_SUCCESS(rc))
+ return DBGCCmdHlpConvert(&pDbgc->CmdHlp, &Var, enmType, false /*fConvSyms*/, pResult);
+ }
+ }
/*
* Ask PDM.
*/
/** @todo resolve symbols using PDM. */
-
/*
* Ask the debug info manager.
*/
RTDBGSYMBOL Symbol;
- int rc = DBGFR3AsSymbolByName(pDbgc->pVM, pDbgc->hDbgAs, pszSymbol, &Symbol, NULL);
+ rc = DBGFR3AsSymbolByName(pDbgc->pVM, pDbgc->hDbgAs, pszSymbol, &Symbol, NULL);
if (RT_SUCCESS(rc))
{
/*
* Default return is a flat gc address.
*/
- memset(pResult, 0, sizeof(*pResult));
- pResult->enmRangeType = Symbol.cb ? DBGCVAR_RANGE_BYTES : DBGCVAR_RANGE_NONE;
- pResult->u64Range = Symbol.cb;
- pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
- pResult->u.GCFlat = Symbol.Value;
- DBGCVAR VarTmp;
+ DBGCVAR_INIT_GC_FLAT(pResult, Symbol.Value);
+ if (Symbol.cb)
+ DBGCVAR_SET_RANGE(pResult, DBGCVAR_RANGE_BYTES, Symbol.cb);
+
switch (enmType)
{
/* nothing to do. */
case DBGCVAR_TYPE_GC_FLAT:
- case DBGCVAR_TYPE_GC_FAR:
case DBGCVAR_TYPE_ANY:
return VINF_SUCCESS;
+ /* impossible at the moment. */
+ case DBGCVAR_TYPE_GC_FAR:
+ return VERR_PARSE_CONVERSION_FAILED;
+
/* simply make it numeric. */
case DBGCVAR_TYPE_NUMBER:
pResult->enmType = DBGCVAR_TYPE_NUMBER;
@@ -255,19 +258,10 @@ int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGC
return VINF_SUCCESS;
/* cast it. */
-
case DBGCVAR_TYPE_GC_PHYS:
- VarTmp = *pResult;
- return dbgcOpAddrPhys(pDbgc, &VarTmp, pResult);
-
- case DBGCVAR_TYPE_HC_FAR:
case DBGCVAR_TYPE_HC_FLAT:
- VarTmp = *pResult;
- return dbgcOpAddrHost(pDbgc, &VarTmp, pResult);
-
case DBGCVAR_TYPE_HC_PHYS:
- VarTmp = *pResult;
- return dbgcOpAddrHostPhys(pDbgc, &VarTmp, pResult);
+ return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pResult, enmType, false /*fConvSyms*/, pResult);
default:
AssertMsgFailed(("Internal error enmType=%d\n", enmType));
@@ -279,1096 +273,6 @@ int dbgcSymbolGet(PDBGC pDbgc, const char *pszSymbol, DBGCVARTYPE enmType, PDBGC
}
-static int dbgcEvalSubString(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pArg)
-{
- Log2(("dbgcEvalSubString: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
-
- /*
- * Removing any quoting and escapings.
- */
- char ch = *pszExpr;
- if (ch == '"' || ch == '\'' || ch == '`')
- {
- if (pszExpr[--cchExpr] != ch)
- return VERR_PARSE_UNBALANCED_QUOTE;
- cchExpr--;
- pszExpr++;
-
- /** @todo string unescaping. */
- }
- pszExpr[cchExpr] = '\0';
-
- /*
- * Make the argument.
- */
- pArg->pDesc = NULL;
- pArg->pNext = NULL;
- pArg->enmType = DBGCVAR_TYPE_STRING;
- pArg->u.pszString = pszExpr;
- pArg->enmRangeType = DBGCVAR_RANGE_BYTES;
- pArg->u64Range = cchExpr;
-
- NOREF(pDbgc);
- return 0;
-}
-
-
-static int dbgcEvalSubNum(char *pszExpr, unsigned uBase, PDBGCVAR pArg)
-{
- Log2(("dbgcEvalSubNum: uBase=%d pszExpr=%s\n", uBase, pszExpr));
- /*
- * Convert to number.
- */
- uint64_t u64 = 0;
- char ch;
- while ((ch = *pszExpr) != '\0')
- {
- uint64_t u64Prev = u64;
- unsigned u = ch - '0';
- if (u < 10 && u < uBase)
- u64 = u64 * uBase + u;
- else if (ch >= 'a' && (u = ch - ('a' - 10)) < uBase)
- u64 = u64 * uBase + u;
- else if (ch >= 'A' && (u = ch - ('A' - 10)) < uBase)
- u64 = u64 * uBase + u;
- else
- return VERR_PARSE_INVALID_NUMBER;
-
- /* check for overflow - ARG!!! How to detect overflow correctly!?!?!? */
- if (u64Prev != u64 / uBase)
- return VERR_PARSE_NUMBER_TOO_BIG;
-
- /* next */
- pszExpr++;
- }
-
- /*
- * Initialize the argument.
- */
- pArg->pDesc = NULL;
- pArg->pNext = NULL;
- pArg->enmType = DBGCVAR_TYPE_NUMBER;
- pArg->u.u64Number = u64;
- pArg->enmRangeType = DBGCVAR_RANGE_NONE;
- pArg->u64Range = 0;
-
- return 0;
-}
-
-
-/**
- * Match variable and variable descriptor, promoting the variable if necessary.
- *
- * @returns VBox status code.
- * @param pDbgc Debug console instanace.
- * @param pVar Variable.
- * @param pVarDesc Variable descriptor.
- */
-static int dbgcEvalSubMatchVar(PDBGC pDbgc, PDBGCVAR pVar, PCDBGCVARDESC pVarDesc)
-{
- /*
- * (If match or promoted to match, return, else break.)
- */
- switch (pVarDesc->enmCategory)
- {
- /*
- * Anything goes
- */
- case DBGCVAR_CAT_ANY:
- return VINF_SUCCESS;
-
- /*
- * Pointer with and without range.
- * We can try resolve strings and symbols as symbols and
- * promote numbers to flat GC pointers.
- */
- case DBGCVAR_CAT_POINTER_NO_RANGE:
- if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
- return VERR_PARSE_NO_RANGE_ALLOWED;
- /* fallthru */
- case DBGCVAR_CAT_POINTER:
- switch (pVar->enmType)
- {
- 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:
- {
- DBGCVAR Var;
- int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_GC_FLAT, &Var);
- if (RT_SUCCESS(rc))
- {
- /* deal with range */
- if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
- {
- Var.enmRangeType = pVar->enmRangeType;
- Var.u64Range = pVar->u64Range;
- }
- else if (pVarDesc->enmCategory == DBGCVAR_CAT_POINTER_NO_RANGE)
- Var.enmRangeType = DBGCVAR_RANGE_NONE;
- *pVar = Var;
- return rc;
- }
- break;
- }
-
- case DBGCVAR_TYPE_NUMBER:
- {
- RTGCPTR GCPtr = (RTGCPTR)pVar->u.u64Number;
- pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
- pVar->u.GCFlat = GCPtr;
- return VINF_SUCCESS;
- }
-
- default:
- break;
- }
- break;
-
- /*
- * GC pointer with and without range.
- * We can try resolve strings and symbols as symbols and
- * promote numbers to flat GC pointers.
- */
- case DBGCVAR_CAT_GC_POINTER_NO_RANGE:
- if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
- return VERR_PARSE_NO_RANGE_ALLOWED;
- /* fallthru */
- case DBGCVAR_CAT_GC_POINTER:
- switch (pVar->enmType)
- {
- 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:
- {
- DBGCVAR Var;
- int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_GC_FLAT, &Var);
- if (RT_SUCCESS(rc))
- {
- /* deal with range */
- if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
- {
- Var.enmRangeType = pVar->enmRangeType;
- Var.u64Range = pVar->u64Range;
- }
- else if (pVarDesc->enmCategory == DBGCVAR_CAT_POINTER_NO_RANGE)
- Var.enmRangeType = DBGCVAR_RANGE_NONE;
- *pVar = Var;
- return rc;
- }
- break;
- }
-
- case DBGCVAR_TYPE_NUMBER:
- {
- RTGCPTR GCPtr = (RTGCPTR)pVar->u.u64Number;
- pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
- pVar->u.GCFlat = GCPtr;
- return VINF_SUCCESS;
- }
-
- default:
- break;
- }
- break;
-
- /*
- * Number with or without a range.
- * Numbers can be resolved from symbols, but we cannot demote a pointer
- * to a number.
- */
- case DBGCVAR_CAT_NUMBER_NO_RANGE:
- if (pVar->enmRangeType != DBGCVAR_RANGE_NONE)
- return VERR_PARSE_NO_RANGE_ALLOWED;
- /* fallthru */
- case DBGCVAR_CAT_NUMBER:
- switch (pVar->enmType)
- {
- case DBGCVAR_TYPE_NUMBER:
- return VINF_SUCCESS;
-
- case DBGCVAR_TYPE_SYMBOL:
- case DBGCVAR_TYPE_STRING:
- {
- DBGCVAR Var;
- int rc = dbgcSymbolGet(pDbgc, pVar->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
- if (RT_SUCCESS(rc))
- {
- *pVar = Var;
- return rc;
- }
- break;
- }
- default:
- break;
- }
- break;
-
- /*
- * Strings can easily be made from symbols (and of course strings).
- * We could consider reformatting the addresses and numbers into strings later...
- */
- case DBGCVAR_CAT_STRING:
- switch (pVar->enmType)
- {
- case DBGCVAR_TYPE_SYMBOL:
- pVar->enmType = DBGCVAR_TYPE_STRING;
- /* fallthru */
- case DBGCVAR_TYPE_STRING:
- return VINF_SUCCESS;
- default:
- break;
- }
- break;
-
- /*
- * Symol is pretty much the same thing as a string (at least until we actually implement it).
- */
- case DBGCVAR_CAT_SYMBOL:
- switch (pVar->enmType)
- {
- case DBGCVAR_TYPE_STRING:
- pVar->enmType = DBGCVAR_TYPE_SYMBOL;
- /* fallthru */
- case DBGCVAR_TYPE_SYMBOL:
- return VINF_SUCCESS;
- default:
- break;
- }
- break;
-
- /*
- * Anything else is illegal.
- */
- default:
- AssertMsgFailed(("enmCategory=%d\n", pVar->enmType));
- break;
- }
-
- return VERR_PARSE_NO_ARGUMENT_MATCH;
-}
-
-
-/**
- * Matches a set of variables with a description set.
- *
- * This is typically used for routine arguments before a call. The effects in
- * addition to the validation, is that some variables might be propagated to
- * other types in order to match the description. The following transformations
- * are supported:
- * - String reinterpreted as a symbol and resolved to a number or pointer.
- * - Number to a pointer.
- * - Pointer to a number.
- * @returns 0 on success with paVars.
- * @returns VBox error code for match errors.
- */
-static int dbgcEvalSubMatchVars(PDBGC pDbgc, unsigned cVarsMin, unsigned cVarsMax,
- PCDBGCVARDESC paVarDescs, unsigned cVarDescs,
- PDBGCVAR paVars, unsigned cVars)
-{
- /*
- * Just do basic min / max checks first.
- */
- if (cVars < cVarsMin)
- return VERR_PARSE_TOO_FEW_ARGUMENTS;
- if (cVars > cVarsMax)
- return VERR_PARSE_TOO_MANY_ARGUMENTS;
-
- /*
- * Match the descriptors and actual variables.
- */
- PCDBGCVARDESC pPrevDesc = NULL;
- unsigned cCurDesc = 0;
- unsigned iVar = 0;
- unsigned iVarDesc = 0;
- while (iVar < cVars)
- {
- /* walk the descriptors */
- if (iVarDesc >= cVarDescs)
- return VERR_PARSE_TOO_MANY_ARGUMENTS;
- if ( ( paVarDescs[iVarDesc].fFlags & DBGCVD_FLAGS_DEP_PREV
- && &paVarDescs[iVarDesc - 1] != pPrevDesc)
- || cCurDesc >= paVarDescs[iVarDesc].cTimesMax)
- {
- iVarDesc++;
- if (iVarDesc >= cVarDescs)
- return VERR_PARSE_TOO_MANY_ARGUMENTS;
- cCurDesc = 0;
- }
-
- /*
- * Skip thru optional arguments until we find something which matches
- * or can easily be promoted to what the descriptor want.
- */
- for (;;)
- {
- int rc = dbgcEvalSubMatchVar(pDbgc, &paVars[iVar], &paVarDescs[iVarDesc]);
- if (RT_SUCCESS(rc))
- {
- paVars[iVar].pDesc = &paVarDescs[iVarDesc];
- cCurDesc++;
- break;
- }
-
- /* can we advance? */
- if (paVarDescs[iVarDesc].cTimesMin > cCurDesc)
- return VERR_PARSE_ARGUMENT_TYPE_MISMATCH;
- if (++iVarDesc >= cVarDescs)
- return VERR_PARSE_ARGUMENT_TYPE_MISMATCH;
- cCurDesc = 0;
- }
-
- /* next var */
- iVar++;
- }
-
- /*
- * Check that the rest of the descriptors are optional.
- */
- while (iVarDesc < cVarDescs)
- {
- if (paVarDescs[iVarDesc].cTimesMin > cCurDesc)
- return VERR_PARSE_TOO_FEW_ARGUMENTS;
- cCurDesc = 0;
-
- /* next */
- iVarDesc++;
- }
-
- return 0;
-}
-
-
-/**
- * Evaluates one argument with respect to unary operators.
- *
- * @returns 0 on success. pResult contains the result.
- * @returns VBox error code on parse or other evaluation error.
- *
- * @param pDbgc Debugger console instance data.
- * @param pszExpr The expression string.
- * @param pResult Where to store the result of the expression evaluation.
- */
-static int dbgcEvalSubUnary(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult)
-{
- Log2(("dbgcEvalSubUnary: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
-
- /*
- * The state of the expression is now such that it will start by zero or more
- * unary operators and being followed by an expression of some kind.
- * The expression is either plain or in parenthesis.
- *
- * Being in a lazy, recursive mode today, the parsing is done as simple as possible. :-)
- * ASSUME: unary operators are all of equal precedence.
- */
- int rc = 0;
- PCDBGCOP pOp = dbgcOperatorLookup(pDbgc, pszExpr, false, ' ');
- if (pOp)
- {
- /* binary operators means syntax error. */
- if (pOp->fBinary)
- return VERR_PARSE_UNEXPECTED_OPERATOR;
-
- /*
- * If the next expression (the one following the unary operator) is in a
- * parenthesis a full eval is needed. If not the unary eval will suffice.
- */
- /* calc and strip next expr. */
- char *pszExpr2 = pszExpr + pOp->cchName;
- while (RT_C_IS_BLANK(*pszExpr2))
- pszExpr2++;
-
- if (!*pszExpr2)
- rc = VERR_PARSE_EMPTY_ARGUMENT;
- else
- {
- DBGCVAR Arg;
- if (*pszExpr2 == '(')
- rc = dbgcEvalSub(pDbgc, pszExpr2, cchExpr - (pszExpr2 - pszExpr), &Arg);
- else
- rc = dbgcEvalSubUnary(pDbgc, pszExpr2, cchExpr - (pszExpr2 - pszExpr), &Arg);
- if (RT_SUCCESS(rc))
- rc = pOp->pfnHandlerUnary(pDbgc, &Arg, pResult);
- }
- }
- else
- {
- /*
- * Didn't find any operators, so it we have to check if this can be an
- * function call before assuming numeric or string expression.
- *
- * (ASSUMPTIONS:)
- * A function name only contains alphanumerical chars and it can not start
- * with a numerical character.
- * Immediately following the name is a parenthesis which must over
- * the remaining part of the expression.
- */
- bool fExternal = *pszExpr == '.';
- char *pszFun = fExternal ? pszExpr + 1 : pszExpr;
- char *pszFunEnd = NULL;
- if (pszExpr[cchExpr - 1] == ')' && RT_C_IS_ALPHA(*pszFun))
- {
- pszFunEnd = pszExpr + 1;
- while (*pszFunEnd != '(' && RT_C_IS_ALNUM(*pszFunEnd))
- pszFunEnd++;
- if (*pszFunEnd != '(')
- pszFunEnd = NULL;
- }
-
- if (pszFunEnd)
- {
- /*
- * Ok, it's a function call.
- */
- if (fExternal)
- pszExpr++, cchExpr--;
- PCDBGCCMD pFun = dbgcRoutineLookup(pDbgc, pszExpr, pszFunEnd - pszExpr, fExternal);
- if (!pFun)
- return VERR_PARSE_FUNCTION_NOT_FOUND;
- if (!pFun->pResultDesc)
- return VERR_PARSE_NOT_A_FUNCTION;
-
- /*
- * Parse the expression in parenthesis.
- */
- cchExpr -= pszFunEnd - pszExpr;
- pszExpr = pszFunEnd;
- /** @todo implement multiple arguments. */
- DBGCVAR Arg;
- rc = dbgcEvalSub(pDbgc, pszExpr, cchExpr, &Arg);
- if (!rc)
- {
- rc = dbgcEvalSubMatchVars(pDbgc, pFun->cArgsMin, pFun->cArgsMax, pFun->paArgDescs, pFun->cArgDescs, &Arg, 1);
- if (!rc)
- rc = pFun->pfnHandler(pFun, &pDbgc->CmdHlp, pDbgc->pVM, &Arg, 1, pResult);
- }
- else if (rc == VERR_PARSE_EMPTY_ARGUMENT && pFun->cArgsMin == 0)
- rc = pFun->pfnHandler(pFun, &pDbgc->CmdHlp, pDbgc->pVM, NULL, 0, pResult);
- }
- else
- {
- /*
- * Didn't find any operators, so it must be a plain expression.
- * This might be numeric or a string expression.
- */
- char ch = pszExpr[0];
- char ch2 = pszExpr[1];
- if (ch == '0' && (ch2 == 'x' || ch2 == 'X'))
- rc = dbgcEvalSubNum(pszExpr + 2, 16, pResult);
- else if (ch == '0' && (ch2 == 'i' || ch2 == 'i'))
- rc = dbgcEvalSubNum(pszExpr + 2, 10, pResult);
- else if (ch == '0' && (ch2 == 't' || ch2 == 'T'))
- rc = dbgcEvalSubNum(pszExpr + 2, 8, pResult);
- /// @todo 0b doesn't work as a binary prefix, we confuse it with 0bf8:0123 and stuff.
- //else if (ch == '0' && (ch2 == 'b' || ch2 == 'b'))
- // rc = dbgcEvalSubNum(pszExpr + 2, 2, pResult);
- else
- {
- /*
- * Hexadecimal number or a string?
- */
- char *psz = pszExpr;
- while (RT_C_IS_XDIGIT(*psz))
- psz++;
- if (!*psz)
- rc = dbgcEvalSubNum(pszExpr, 16, pResult);
- else if ((*psz == 'h' || *psz == 'H') && !psz[1])
- {
- *psz = '\0';
- rc = dbgcEvalSubNum(pszExpr, 16, pResult);
- }
- else
- rc = dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
- }
- }
- }
-
- return rc;
-}
-
-
-/**
- * Evaluates one argument.
- *
- * @returns 0 on success. pResult contains the result.
- * @returns VBox error code on parse or other evaluation error.
- *
- * @param pDbgc Debugger console instance data.
- * @param pszExpr The expression string.
- * @param pResult Where to store the result of the expression evaluation.
- */
-int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult)
-{
- Log2(("dbgcEvalSub: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr));
- /*
- * First we need to remove blanks in both ends.
- * ASSUMES: There is no quoting unless the entire expression is a string.
- */
-
- /* stripping. */
- while (cchExpr > 0 && RT_C_IS_BLANK(pszExpr[cchExpr - 1]))
- pszExpr[--cchExpr] = '\0';
- while (RT_C_IS_BLANK(*pszExpr))
- pszExpr++, cchExpr--;
- if (!*pszExpr)
- return VERR_PARSE_EMPTY_ARGUMENT;
-
- /* it there is any kind of quoting in the expression, it's string meat. */
- if (strpbrk(pszExpr, "\"'`"))
- return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult);
-
- /*
- * Check if there are any parenthesis which needs removing.
- */
- if (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')')
- {
- do
- {
- unsigned cPar = 1;
- char *psz = pszExpr + 1;
- char ch;
- while ((ch = *psz) != '\0')
- {
- if (ch == '(')
- cPar++;
- else if (ch == ')')
- {
- if (cPar <= 0)
- return VERR_PARSE_UNBALANCED_PARENTHESIS;
- cPar--;
- if (cPar == 0 && psz[1]) /* If not at end, there's nothing to do. */
- break;
- }
- /* next */
- psz++;
- }
- if (ch)
- break;
-
- /* remove the parenthesis. */
- pszExpr++;
- cchExpr -= 2;
- pszExpr[cchExpr] = '\0';
-
- /* strip blanks. */
- while (cchExpr > 0 && RT_C_IS_BLANK(pszExpr[cchExpr - 1]))
- pszExpr[--cchExpr] = '\0';
- while (RT_C_IS_BLANK(*pszExpr))
- pszExpr++, cchExpr--;
- if (!*pszExpr)
- return VERR_PARSE_EMPTY_ARGUMENT;
- } while (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')');
- }
-
- /* tabs to spaces. */
- char *psz = pszExpr;
- while ((psz = strchr(psz, '\t')) != NULL)
- *psz = ' ';
-
- /*
- * Now, we need to look for the binary operator with the lowest precedence.
- *
- * If there are no operators we're left with a simple expression which we
- * evaluate with respect to unary operators
- */
- char *pszOpSplit = NULL;
- PCDBGCOP pOpSplit = NULL;
- unsigned cBinaryOps = 0;
- unsigned cPar = 0;
- char ch;
- char chPrev = ' ';
- bool fBinary = false;
- psz = pszExpr;
-
- while ((ch = *psz) != '\0')
- {
- //Log2(("ch=%c cPar=%d fBinary=%d\n", ch, cPar, fBinary));
- /*
- * Parenthesis.
- */
- if (ch == '(')
- {
- cPar++;
- fBinary = false;
- }
- else if (ch == ')')
- {
- if (cPar <= 0)
- return VERR_PARSE_UNBALANCED_PARENTHESIS;
- cPar--;
- fBinary = true;
- }
- /*
- * Potential operator.
- */
- else if (cPar == 0 && !RT_C_IS_BLANK(ch))
- {
- PCDBGCOP pOp = dbgcIsOpChar(ch)
- ? dbgcOperatorLookup(pDbgc, psz, fBinary, chPrev)
- : NULL;
- if (pOp)
- {
- /* If not the right kind of operator we've got a syntax error. */
- if (pOp->fBinary != fBinary)
- return VERR_PARSE_UNEXPECTED_OPERATOR;
-
- /*
- * Update the parse state and skip the operator.
- */
- if (!pOpSplit)
- {
- pOpSplit = pOp;
- pszOpSplit = psz;
- cBinaryOps = fBinary;
- }
- else if (fBinary)
- {
- cBinaryOps++;
- if (pOp->iPrecedence >= pOpSplit->iPrecedence)
- {
- pOpSplit = pOp;
- pszOpSplit = psz;
- }
- }
-
- psz += pOp->cchName - 1;
- fBinary = false;
- }
- else
- fBinary = true;
- }
-
- /* next */
- psz++;
- chPrev = ch;
- } /* parse loop. */
-
-
- /*
- * Either we found an operator to divide the expression by
- * or we didn't find any. In the first case it's divide and
- * conquer. In the latter it's a single expression which
- * needs dealing with its unary operators if any.
- */
- int rc;
- if ( cBinaryOps
- && pOpSplit->fBinary)
- {
- /* process 1st sub expression. */
- *pszOpSplit = '\0';
- DBGCVAR Arg1;
- rc = dbgcEvalSub(pDbgc, pszExpr, pszOpSplit - pszExpr, &Arg1);
- if (RT_SUCCESS(rc))
- {
- /* process 2nd sub expression. */
- char *psz2 = pszOpSplit + pOpSplit->cchName;
- DBGCVAR Arg2;
- rc = dbgcEvalSub(pDbgc, psz2, cchExpr - (psz2 - pszExpr), &Arg2);
- if (RT_SUCCESS(rc))
- /* apply the operator. */
- rc = pOpSplit->pfnHandlerBinary(pDbgc, &Arg1, &Arg2, pResult);
- }
- }
- else if (cBinaryOps)
- {
- /* process sub expression. */
- pszOpSplit += pOpSplit->cchName;
- DBGCVAR Arg;
- rc = dbgcEvalSub(pDbgc, pszOpSplit, cchExpr - (pszOpSplit - pszExpr), &Arg);
- if (RT_SUCCESS(rc))
- /* apply the operator. */
- rc = pOpSplit->pfnHandlerUnary(pDbgc, &Arg, pResult);
- }
- else
- /* plain expression or using unary operators perhaps with parentheses. */
- rc = dbgcEvalSubUnary(pDbgc, pszExpr, cchExpr, pResult);
-
- return rc;
-}
-
-
-/**
- * Parses the arguments of one command.
- *
- * @returns 0 on success.
- * @returns VBox error code on parse error with *pcArg containing the argument causing trouble.
- * @param pDbgc Debugger console instance data.
- * @param pCmd Pointer to the command descriptor.
- * @param pszArg Pointer to the arguments to parse.
- * @param paArgs Where to store the parsed arguments.
- * @param cArgs Size of the paArgs array.
- * @param pcArgs Where to store the number of arguments.
- * In the event of an error this is used to store the index of the offending argument.
- */
-static int dbgcProcessArguments(PDBGC pDbgc, PCDBGCCMD pCmd, char *pszArgs, PDBGCVAR paArgs, unsigned cArgs, unsigned *pcArgs)
-{
- Log2(("dbgcProcessArguments: pCmd=%s pszArgs='%s'\n", pCmd->pszCmd, pszArgs));
- /*
- * Check if we have any argument and if the command takes any.
- */
- *pcArgs = 0;
- /* strip leading blanks. */
- while (*pszArgs && RT_C_IS_BLANK(*pszArgs))
- pszArgs++;
- if (!*pszArgs)
- {
- if (!pCmd->cArgsMin)
- return 0;
- return VERR_PARSE_TOO_FEW_ARGUMENTS;
- }
- /** @todo fixme - foo() doesn't work. */
- if (!pCmd->cArgsMax)
- return VERR_PARSE_TOO_MANY_ARGUMENTS;
-
- /*
- * This is a hack, it's "temporary" and should go away "when" the parser is
- * modified to match arguments while parsing.
- */
- if ( pCmd->cArgsMax == 1
- && pCmd->cArgsMin == 1
- && pCmd->cArgDescs == 1
- && pCmd->paArgDescs[0].enmCategory == DBGCVAR_CAT_STRING
- && cArgs >= 1)
- {
- *pcArgs = 1;
- RTStrStripR(pszArgs);
- return dbgcEvalSubString(pDbgc, pszArgs, strlen(pszArgs), &paArgs[0]);
- }
-
-
- /*
- * The parse loop.
- */
- PDBGCVAR pArg0 = &paArgs[0];
- PDBGCVAR pArg = pArg0;
- *pcArgs = 0;
- do
- {
- /*
- * Can we have another argument?
- */
- if (*pcArgs >= pCmd->cArgsMax)
- return VERR_PARSE_TOO_MANY_ARGUMENTS;
- if (pArg >= &paArgs[cArgs])
- return VERR_PARSE_ARGUMENT_OVERFLOW;
-
- /*
- * Find the end of the argument.
- */
- int cPar = 0;
- char chQuote = '\0';
- char *pszEnd = NULL;
- char *psz = pszArgs;
- char ch;
- bool fBinary = false;
- for (;;)
- {
- /*
- * Check for the end.
- */
- if ((ch = *psz) == '\0')
- {
- if (chQuote)
- return VERR_PARSE_UNBALANCED_QUOTE;
- if (cPar)
- return VERR_PARSE_UNBALANCED_PARENTHESIS;
- pszEnd = psz;
- break;
- }
- /*
- * When quoted we ignore everything but the quotation char.
- * We use the REXX way of escaping the quotation char, i.e. double occurrence.
- */
- else if (ch == '\'' || ch == '"' || ch == '`')
- {
- if (chQuote)
- {
- /* end quote? */
- if (ch == chQuote)
- {
- if (psz[1] == ch)
- psz++; /* skip the escaped quote char */
- else
- chQuote = '\0'; /* end of quoted string. */
- }
- }
- else
- chQuote = ch; /* open new quote */
- }
- /*
- * Parenthesis can of course be nested.
- */
- else if (ch == '(')
- {
- cPar++;
- fBinary = false;
- }
- else if (ch == ')')
- {
- if (!cPar)
- return VERR_PARSE_UNBALANCED_PARENTHESIS;
- cPar--;
- fBinary = true;
- }
- else if (!chQuote && !cPar)
- {
- /*
- * Encountering blanks may mean the end of it all. A binary operator
- * will force continued parsing.
- */
- if (RT_C_IS_BLANK(*psz))
- {
- pszEnd = psz++; /* just in case. */
- while (RT_C_IS_BLANK(*psz))
- psz++;
- PCDBGCOP pOp = dbgcOperatorLookup(pDbgc, psz, fBinary, ' ');
- if (!pOp || pOp->fBinary != fBinary)
- break; /* the end. */
- psz += pOp->cchName;
- while (RT_C_IS_BLANK(*psz)) /* skip blanks so we don't get here again */
- psz++;
- fBinary = false;
- continue;
- }
-
- /*
- * Look for operators without a space up front.
- */
- if (dbgcIsOpChar(*psz))
- {
- PCDBGCOP pOp = dbgcOperatorLookup(pDbgc, psz, fBinary, ' ');
- if (pOp)
- {
- if (pOp->fBinary != fBinary)
- {
- pszEnd = psz;
- /** @todo this is a parsing error really. */
- break; /* the end. */
- }
- psz += pOp->cchName;
- while (RT_C_IS_BLANK(*psz)) /* skip blanks so we don't get here again */
- psz++;
- fBinary = false;
- continue;
- }
- }
- fBinary = true;
- }
-
- /* next char */
- psz++;
- }
- *pszEnd = '\0';
- /* (psz = next char to process) */
-
- /*
- * Parse and evaluate the argument.
- */
- int rc = dbgcEvalSub(pDbgc, pszArgs, strlen(pszArgs), pArg);
- if (RT_FAILURE(rc))
- return rc;
-
- /*
- * Next.
- */
- pArg++;
- (*pcArgs)++;
- pszArgs = psz;
- while (*pszArgs && RT_C_IS_BLANK(*pszArgs))
- pszArgs++;
- } while (*pszArgs);
-
- /*
- * Match the arguments.
- */
- return dbgcEvalSubMatchVars(pDbgc, pCmd->cArgsMin, pCmd->cArgsMax, pCmd->paArgDescs, pCmd->cArgDescs, pArg0, pArg - pArg0);
-}
-
-
-/**
- * Process one command.
- *
- * @returns VBox status code. Any error indicates the termination of the console session.
- * @param pDbgc Debugger console instance data.
- * @param pszCmd Pointer to the command.
- * @param cchCmd Length of the command.
- * @param fNoExecute Indicates that no commands should actually be executed.
- */
-int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd, bool fNoExecute)
-{
- char *pszCmdInput = pszCmd;
-
- /*
- * Skip blanks.
- */
- while (RT_C_IS_BLANK(*pszCmd))
- pszCmd++, cchCmd--;
-
- /* external command? */
- bool fExternal = *pszCmd == '.';
- if (fExternal)
- pszCmd++, cchCmd--;
-
- /*
- * Find arguments.
- */
- char *pszArgs = pszCmd;
- while (RT_C_IS_ALNUM(*pszArgs))
- pszArgs++;
- if (*pszArgs && (!RT_C_IS_BLANK(*pszArgs) || pszArgs == pszCmd))
- {
- pDbgc->rcCmd = VINF_PARSE_INVALD_COMMAND_NAME;
- pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Syntax error in command '%s'!\n", pszCmdInput);
- return 0;
- }
-
- /*
- * Find the command.
- */
- PCDBGCCMD pCmd = dbgcRoutineLookup(pDbgc, pszCmd, pszArgs - pszCmd, fExternal);
- if (!pCmd || (pCmd->fFlags & DBGCCMD_FLAGS_FUNCTION))
- {
- pDbgc->rcCmd = VINF_PARSE_COMMAND_NOT_FOUND;
- return pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Unknown command '%s'!\n", pszCmdInput);
- }
-
- /*
- * Parse arguments (if any).
- */
- unsigned cArgs;
- int rc = dbgcProcessArguments(pDbgc, pCmd, pszArgs, &pDbgc->aArgs[pDbgc->iArg], RT_ELEMENTS(pDbgc->aArgs) - pDbgc->iArg, &cArgs);
-
- /*
- * Execute the command.
- */
- if (!rc)
- {
- if (!fNoExecute)
- rc = pCmd->pfnHandler(pCmd, &pDbgc->CmdHlp, pDbgc->pVM, &pDbgc->aArgs[0], cArgs, NULL);
- pDbgc->rcCmd = rc;
- if (rc == VERR_DBGC_COMMAND_FAILED)
- rc = VINF_SUCCESS;
- }
- else
- {
- pDbgc->rcCmd = rc;
-
- /* report parse / eval error. */
- switch (rc)
- {
- case VERR_PARSE_TOO_FEW_ARGUMENTS:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: Too few arguments. Minimum is %d for command '%s'.\n", pCmd->cArgsMin, pCmd->pszCmd);
- break;
- case VERR_PARSE_TOO_MANY_ARGUMENTS:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: Too many arguments. Maximum is %d for command '%s'.\n", pCmd->cArgsMax, pCmd->pszCmd);
- break;
- case VERR_PARSE_ARGUMENT_OVERFLOW:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: Too many arguments.\n");
- break;
- case VERR_PARSE_UNBALANCED_QUOTE:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: Unbalanced quote (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_UNBALANCED_PARENTHESIS:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: Unbalanced parenthesis (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_EMPTY_ARGUMENT:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: An argument or subargument contains nothing useful (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_UNEXPECTED_OPERATOR:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: Invalid operator usage (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_INVALID_NUMBER:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Syntax error: Ivalid numeric value (argument %d). If a string was the intention, then quote it.\n", cArgs);
- break;
- case VERR_PARSE_NUMBER_TOO_BIG:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Numeric overflow (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_INVALID_OPERATION:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Invalid operation attempted (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_FUNCTION_NOT_FOUND:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Function not found (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_NOT_A_FUNCTION:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: The function specified is not a function (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_NO_MEMORY:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Out memory in the regular heap! Expect odd stuff to happen...\n", cArgs);
- break;
- case VERR_PARSE_INCORRECT_ARG_TYPE:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Incorrect argument type (argument %d?).\n", cArgs);
- break;
- case VERR_PARSE_VARIABLE_NOT_FOUND:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: An undefined variable was referenced (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_CONVERSION_FAILED:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: A conversion between two types failed (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_NOT_IMPLEMENTED:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: You hit a debugger feature which isn't implemented yet (argument %d).\n", cArgs);
- break;
- case VERR_PARSE_BAD_RESULT_TYPE:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Couldn't satisfy a request for a specific result type (argument %d). (Usually applies to symbols)\n", cArgs);
- break;
- case VERR_PARSE_WRITEONLY_SYMBOL:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Cannot get symbol, it's set only (argument %d).\n", cArgs);
- break;
-
- case VERR_DBGC_COMMAND_FAILED:
- rc = VINF_SUCCESS;
- break;
-
- default:
- rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
- "Error: Unknown error %d!\n", rc);
- return rc;
- }
-
- /*
- * Parse errors are non fatal.
- */
- if (rc >= VERR_PARSE_FIRST && rc < VERR_PARSE_LAST)
- rc = VINF_SUCCESS;
- }
-
- return rc;
-}
-
-
/**
* Process all commands currently in the buffer.
*
@@ -1378,7 +282,9 @@ int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd, bool fNoExecute
*/
static int dbgcProcessCommands(PDBGC pDbgc, bool fNoExecute)
{
- int rc = 0;
+ /** @todo Replace this with a sh/ksh/csh/rexx like toplevel language that
+ * allows doing function, loops, if, cases, and such. */
+ int rc = VINF_SUCCESS;
while (pDbgc->cInputLines)
{
/*
@@ -1432,9 +338,11 @@ static int dbgcProcessCommands(PDBGC pDbgc, bool fNoExecute)
*/
pDbgc->pszScratch = psz;
pDbgc->iArg = 0;
- rc = dbgcProcessCommand(pDbgc, &pDbgc->achScratch[0], psz - &pDbgc->achScratch[0] - 1, fNoExecute);
- if (rc)
+ rc = dbgcEvalCommand(pDbgc, &pDbgc->achScratch[0], psz - &pDbgc->achScratch[0] - 1, fNoExecute);
+ if ( rc == VERR_DBGC_QUIT
+ || rc == VWRN_DBGC_CMD_PENDING)
break;
+ rc = VINF_SUCCESS; /* ignore other statuses */
}
return rc;
@@ -1954,7 +862,7 @@ int dbgcCreate(PDBGC *ppDbgc, PDBGCBACK pBack, unsigned fFlags)
dbgcInitCmdHlp(pDbgc);
pDbgc->pBack = pBack;
pDbgc->pVM = NULL;
- pDbgc->idCpu = NIL_VMCPUID;
+ pDbgc->idCpu = 0;
pDbgc->hDbgAs = DBGF_AS_GLOBAL;
pDbgc->pszEmulation = "CodeView/WinDbg";
pDbgc->paEmulationCmds = &g_aCmdsCodeView[0];
@@ -1990,7 +898,7 @@ int dbgcCreate(PDBGC *ppDbgc, PDBGCBACK pBack, unsigned fFlags)
//pDbgc->rcOutput = 0;
//pDbgc->rcCmd = 0;
- dbgcInitOpCharBitMap();
+ dbgcEvalInit();
*ppDbgc = pDbgc;
return VINF_SUCCESS;
@@ -2068,7 +976,7 @@ DBGDECL(int) DBGCCreate(PVM pVM, PDBGCBACK pBack, unsigned fFlags)
rc = DBGFR3Attach(pVM);
if (RT_SUCCESS(rc))
{
- pDbgc->pVM = pVM;
+ pDbgc->pVM = pVM;
pDbgc->idCpu = 0;
rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
"Current VM is %08x, CPU #%u\n" /** @todo get and print the VM name! */