VirtualBox

Ignore:
Timestamp:
Nov 11, 2007 5:42:00 AM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
26019
Message:

Split out the commands.

File:
1 edited

Legend:

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

    r5674 r5675  
    131131*   Internal Functions                                                         *
    132132*******************************************************************************/
    133 static DECLCALLBACK(int) dbgcCmdHelp(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    134 static DECLCALLBACK(int) dbgcCmdQuit(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    135 static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    136 static DECLCALLBACK(int) dbgcCmdInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    137 static DECLCALLBACK(int) dbgcCmdLog(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    138 static DECLCALLBACK(int) dbgcCmdLogDest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    139 static DECLCALLBACK(int) dbgcCmdLogFlags(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    140 static DECLCALLBACK(int) dbgcCmdFormat(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    141 static DECLCALLBACK(int) dbgcCmdLoadSyms(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    142 static DECLCALLBACK(int) dbgcCmdSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    143 static DECLCALLBACK(int) dbgcCmdUnset(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    144 static DECLCALLBACK(int) dbgcCmdLoadVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    145 static DECLCALLBACK(int) dbgcCmdShowVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    146 static DECLCALLBACK(int) dbgcCmdHarakiri(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    147 static DECLCALLBACK(int) dbgcCmdEcho(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    148 static DECLCALLBACK(int) dbgcCmdRunScript(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    149 
    150133static int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult);
    151134static int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd);
     
    155138*   Global Variables                                                           *
    156139*******************************************************************************/
    157 /**
    158  * Pointer to head of the list of external commands.
    159  */
    160 static PDBGCEXTCMDS     g_pExtCmdsHead;     /** @todo rw protect g_pExtCmdsHead! */
    161 /** Locks the g_pExtCmdsHead list for reading. */
    162 #define DBGCEXTCMDS_LOCK_RD()       do { } while (0)
    163 /** Locks the g_pExtCmdsHead list for writing. */
    164 #define DBGCEXTCMDS_LOCK_WR()       do { } while (0)
    165 /** UnLocks the g_pExtCmdsHead list after reading. */
    166 #define DBGCEXTCMDS_UNLOCK_RD()     do { } while (0)
    167 /** UnLocks the g_pExtCmdsHead list after writing. */
    168 #define DBGCEXTCMDS_UNLOCK_WR()     do { } while (0)
    169 
    170 
    171 /** One argument of any kind. */
    172 static const DBGCVARDESC    g_aArgAny[] =
    173 {
    174     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    175     {  0,           1,          DBGCVAR_CAT_ANY,        0,                              "var",          "Any type of argument." },
    176 };
    177 
    178 /** Multiple string arguments (min 1). */
    179 static const DBGCVARDESC    g_aArgMultiStr[] =
    180 {
    181     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    182     {  1,           ~0,         DBGCVAR_CAT_STRING,     0,                              "strings",      "One or more strings." },
    183 };
    184 
    185 /** Filename string. */
    186 static const DBGCVARDESC    g_aArgFilename[] =
    187 {
    188     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    189     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "path",         "Filename string." },
    190 };
    191 
    192 
    193 /** 'help' arguments. */
    194 static const DBGCVARDESC    g_aArgHelp[] =
    195 {
    196     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    197     {  0,           ~0,         DBGCVAR_CAT_STRING,     0,                              "cmd/op",       "Zero or more command or operator names." },
    198 };
    199 
    200 
    201 /** 'info' arguments. */
    202 static const DBGCVARDESC    g_aArgInfo[] =
    203 {
    204     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    205     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "info",         "The name of the info to display." },
    206     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "args",         "String arguments to the handler." },
    207 };
    208 
    209 
    210 /** loadsyms arguments. */
    211 static const DBGCVARDESC    g_aArgLoadSyms[] =
    212 {
    213     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    214     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "path",         "Filename string." },
    215     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "delta",        "Delta to add to the loaded symbols. (optional)" },
    216     {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "module name",  "Module name." },
    217     {  0,           1,          DBGCVAR_CAT_POINTER,    DBGCVD_FLAGS_DEP_PREV,          "module address", "Module address." },
    218     {  0,           1,          DBGCVAR_CAT_NUMBER,     0,                              "module size",  "The module size. (optional)" },
    219 };
    220 
    221 
    222 /** log arguments. */
    223 static const DBGCVARDESC    g_aArgLog[] =
    224 {
    225     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    226     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "groups",       "Group modifier string (quote it!)." }
    227 };
    228 
    229 
    230 /** logdest arguments. */
    231 static const DBGCVARDESC    g_aArgLogDest[] =
    232 {
    233     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    234     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "dests",        "Destination modifier string (quote it!)." }
    235 };
    236 
    237 
    238 /** logflags arguments. */
    239 static const DBGCVARDESC    g_aArgLogFlags[] =
    240 {
    241     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    242     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "flags",        "Flag modifier string (quote it!)." }
    243 };
    244 
    245 
    246 /** 'set' arguments */
    247 static const DBGCVARDESC    g_aArgSet[] =
    248 {
    249     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
    250     {  1,           1,          DBGCVAR_CAT_STRING,     0,                              "var",          "Variable name." },
    251     {  1,           1,          DBGCVAR_CAT_ANY,        0,                              "value",        "Value to assign to the variable." },
    252 };
    253 
    254 
    255 
    256 
    257 
    258 /** Command descriptors for the basic commands. */
    259 static const DBGCCMD    g_aCmds[] =
    260 {
    261     /* pszCmd,      cArgsMin, cArgsMax, paArgDescs,         cArgDescs,                  pResultDesc,        fFlags,     pfnHandler          pszSyntax,          ....pszDescription */
    262     { "bye",        0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
    263     { "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." },
    264     { "exit",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
    265     { "format",     1,        1,        &g_aArgAny[0],      ELEMENTS(g_aArgAny),        NULL,               0,          dbgcCmdFormat,      "",                     "Evaluates an expression and formats it." },
    266     { "harakiri",   0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdHarakiri,    "",                     "Kills debugger process." },
    267     { "help",       0,        ~0,       &g_aArgHelp[0],     ELEMENTS(g_aArgHelp),       NULL,               0,          dbgcCmdHelp,        "[cmd/op [..]]",        "Display help. For help about info items try 'info help'." },
    268     { "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'." },
    269     { "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." },
    270     { "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." },
    271     { "log",        1,        1,        &g_aArgLog[0],      ELEMENTS(g_aArgLog),        NULL,               0,          dbgcCmdLog,         "<group string>",       "Modifies the logging group settings (VBOX_LOG)" },
    272     { "logdest",    1,        1,        &g_aArgLogDest[0],  ELEMENTS(g_aArgLogDest),    NULL,               0,          dbgcCmdLogDest,     "<dest string>",        "Modifies the logging destination (VBOX_LOG_DEST)." },
    273     { "logflags",   1,        1,        &g_aArgLogFlags[0], ELEMENTS(g_aArgLogFlags),   NULL,               0,          dbgcCmdLogFlags,    "<flags string>",       "Modifies the logging flags (VBOX_LOG_FLAGS)." },
    274     { "quit",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdQuit,        "",                     "Exits the debugger." },
    275     { "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." },
    276     { "set",        2,        2,        &g_aArgSet[0],      ELEMENTS(g_aArgSet),        NULL,               0,          dbgcCmdSet,         "<var> <value>",        "Sets a global variable." },
    277     { "showvars",   0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdShowVars,    "",                     "List all the defined variables." },
    278     { "stop",       0,        0,        NULL,               0,                          NULL,               0,          dbgcCmdStop,        "",                     "Stop execution." },
    279     { "unset",      1,        ~0,       &g_aArgMultiStr[0], ELEMENTS(g_aArgMultiStr),   NULL,               0,          dbgcCmdUnset,       "<var1> [var1..[varN]]", "Unsets (delete) one or more global variables." },
    280 };
    281 
    282 
    283140/** Bitmap where set bits indicates the characters the may start an operator name. */
    284141static uint32_t g_bmOperatorChars[256 / (4*8)];
    285142
    286 
    287 
    288 
    289 
    290 
    291 
    292 
    293 /**
    294  * Prints full command help.
    295  */
    296 static int dbgcPrintHelp(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, bool fExternal)
    297 {
    298     int rc;
    299 
    300     /* the command */
    301     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    302                             "%s%-*s %-30s %s",
    303                             fExternal ? "." : "",
    304                             fExternal ? 10 : 11,
    305                             pCmd->pszCmd,
    306                             pCmd->pszSyntax,
    307                             pCmd->pszDescription);
    308     if (!pCmd->cArgsMin && pCmd->cArgsMin == pCmd->cArgsMax)
    309         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <no args>\n");
    310     else if (pCmd->cArgsMin == pCmd->cArgsMax)
    311         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u args>\n", pCmd->cArgsMin);
    312     else if (pCmd->cArgsMax == ~0U)
    313         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u+ args>\n", pCmd->cArgsMin);
    314     else
    315         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u to %u args>\n", pCmd->cArgsMin, pCmd->cArgsMax);
    316 
    317     /* argument descriptions. */
    318     for (unsigned i = 0; i < pCmd->cArgDescs; i++)
    319     {
    320         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    321                                 "    %-12s %s",
    322                                 pCmd->paArgDescs[i].pszName,
    323                                 pCmd->paArgDescs[i].pszDescription);
    324         if (!pCmd->paArgDescs[i].cTimesMin)
    325         {
    326             if (pCmd->paArgDescs[i].cTimesMax == ~0U)
    327                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <optional+>\n");
    328             else
    329                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <optional-%u>\n", pCmd->paArgDescs[i].cTimesMax);
    330         }
    331         else
    332         {
    333             if (pCmd->paArgDescs[i].cTimesMax == ~0U)
    334                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u+>\n", pCmd->paArgDescs[i].cTimesMin);
    335             else
    336                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u-%u>\n", pCmd->paArgDescs[i].cTimesMin, pCmd->paArgDescs[i].cTimesMax);
    337         }
    338     }
    339     return rc;
    340 }
    341 
    342 
    343 /**
    344  * The 'help' command.
    345  *
    346  * @returns VBox status.
    347  * @param   pCmd        Pointer to the command descriptor (as registered).
    348  * @param   pCmdHlp     Pointer to command helper functions.
    349  * @param   pVM         Pointer to the current VM (if any).
    350  * @param   paArgs      Pointer to (readonly) array of arguments.
    351  * @param   cArgs       Number of arguments in the array.
    352  */
    353 static DECLCALLBACK(int) dbgcCmdHelp(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    354 {
    355     PDBGC       pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    356     int         rc = VINF_SUCCESS;
    357     unsigned    i;
    358 
    359     if (!cArgs)
    360     {
    361         /*
    362          * All the stuff.
    363          */
    364         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    365                                 "VirtualBox Debugger\n"
    366                                 "-------------------\n"
    367                                 "\n"
    368                                 "Commands and Functions:\n");
    369         for (i = 0; i < ELEMENTS(g_aCmds); i++)
    370             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    371                                     "%-11s %-30s %s\n",
    372                                     g_aCmds[i].pszCmd,
    373                                     g_aCmds[i].pszSyntax,
    374                                     g_aCmds[i].pszDescription);
    375         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    376                                 "\n"
    377                                 "Emulation: %s\n", pDbgc->pszEmulation);
    378         PCDBGCCMD pCmd = pDbgc->paEmulationCmds;
    379         for (i = 0; i < pDbgc->cEmulationCmds; i++, pCmd++)
    380             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    381                                     "%-11s %-30s %s\n",
    382                                     pCmd->pszCmd,
    383                                     pCmd->pszSyntax,
    384                                     pCmd->pszDescription);
    385 
    386         if (g_pExtCmdsHead)
    387         {
    388             DBGCEXTCMDS_LOCK_RD();
    389             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    390                                     "\n"
    391                                     "External Commands and Functions:\n");
    392             for (PDBGCEXTCMDS pExtCmd = g_pExtCmdsHead; pExtCmd; pExtCmd = pExtCmd->pNext)
    393                 for (i = 0; i < pExtCmd->cCmds; i++)
    394                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    395                                             ".%-10s %-30s %s\n",
    396                                             pExtCmd->paCmds[i].pszCmd,
    397                                             pExtCmd->paCmds[i].pszSyntax,
    398                                             pExtCmd->paCmds[i].pszDescription);
    399             DBGCEXTCMDS_UNLOCK_RD();
    400         }
    401 
    402         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    403                                 "\n"
    404                                 "Operators:\n");
    405         unsigned iPrecedence = 0;
    406         unsigned cLeft = g_cOps;
    407         while (cLeft > 0)
    408         {
    409             for (i = 0; i < g_cOps; i++)
    410                 if (g_aOps[i].iPrecedence == iPrecedence)
    411                 {
    412                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    413                                             "%-10s  %s  %s\n",
    414                                             g_aOps[i].szName,
    415                                             g_aOps[i].fBinary ? "Binary" : "Unary ",
    416                                             g_aOps[i].pszDescription);
    417                     cLeft--;
    418                 }
    419             iPrecedence++;
    420         }
    421     }
    422     else
    423     {
    424         /*
    425          * Search for the arguments (strings).
    426          */
    427         for (unsigned iArg = 0; iArg < cArgs; iArg++)
    428         {
    429             Assert(paArgs[iArg].enmType == DBGCVAR_TYPE_STRING);
    430             bool fFound = false;
    431 
    432             /* lookup in the emulation command list first */
    433             for (i = 0; i < pDbgc->cEmulationCmds; i++)
    434                 if (!strcmp(pDbgc->paEmulationCmds[i].pszCmd, paArgs[iArg].u.pszString))
    435                 {
    436                     rc = dbgcPrintHelp(pCmdHlp, &pDbgc->paEmulationCmds[i], false);
    437                     fFound = true;
    438                     break;
    439                 }
    440 
    441             /* lookup in the command list (even when found in the emulation) */
    442             for (i = 0; i < ELEMENTS(g_aCmds); i++)
    443                 if (!strcmp(g_aCmds[i].pszCmd, paArgs[iArg].u.pszString))
    444                 {
    445                     rc = dbgcPrintHelp(pCmdHlp, &g_aCmds[i], false);
    446                     fFound = true;
    447                     break;
    448                 }
    449 
    450            /* external commands */
    451            if (     !fFound
    452                &&   g_pExtCmdsHead
    453                &&   paArgs[iArg].u.pszString[0] == '.')
    454            {
    455                DBGCEXTCMDS_LOCK_RD();
    456                for (PDBGCEXTCMDS pExtCmd = g_pExtCmdsHead; pExtCmd; pExtCmd = pExtCmd->pNext)
    457                    for (i = 0; i < pExtCmd->cCmds; i++)
    458                        if (!strcmp(pExtCmd->paCmds[i].pszCmd, paArgs[iArg].u.pszString + 1))
    459                        {
    460                            rc = dbgcPrintHelp(pCmdHlp, &g_aCmds[i], true);
    461                            fFound = true;
    462                            break;
    463                        }
    464                DBGCEXTCMDS_UNLOCK_RD();
    465            }
    466 
    467            /* operators */
    468            if (!fFound && strlen(paArgs[iArg].u.pszString) < sizeof(g_aOps[i].szName))
    469            {
    470                for (i = 0; i < g_cOps; i++)
    471                    if (!strcmp(g_aOps[i].szName, paArgs[iArg].u.pszString))
    472                    {
    473                        rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    474                                                "%-10s  %s  %s\n",
    475                                                g_aOps[i].szName,
    476                                                g_aOps[i].fBinary ? "Binary" : "Unary ",
    477                                                g_aOps[i].pszDescription);
    478                        fFound = true;
    479                        break;
    480                    }
    481            }
    482 
    483            /* found? */
    484            if (!fFound)
    485                rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    486                                        "error: '%s' was not found!\n",
    487                                        paArgs[iArg].u.pszString);
    488         } /* foreach argument */
    489     }
    490 
    491     NOREF(pCmd);
    492     NOREF(pVM);
    493     NOREF(pResult);
    494     return rc;
    495 }
    496 
    497 
    498 /**
    499  * The 'quit', 'exit' and 'bye' commands.
    500  *
    501  * @returns VBox status.
    502  * @param   pCmd        Pointer to the command descriptor (as registered).
    503  * @param   pCmdHlp     Pointer to command helper functions.
    504  * @param   pVM         Pointer to the current VM (if any).
    505  * @param   paArgs      Pointer to (readonly) array of arguments.
    506  * @param   cArgs       Number of arguments in the array.
    507  */
    508 static DECLCALLBACK(int) dbgcCmdQuit(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    509 {
    510     pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Quitting console...\n");
    511     NOREF(pCmd);
    512     NOREF(pVM);
    513     NOREF(paArgs);
    514     NOREF(cArgs);
    515     NOREF(pResult);
    516     return VERR_DBGC_QUIT;
    517 }
    518 
    519 
    520 /**
    521  * The 'stop' command.
    522  *
    523  * @returns VBox status.
    524  * @param   pCmd        Pointer to the command descriptor (as registered).
    525  * @param   pCmdHlp     Pointer to command helper functions.
    526  * @param   pVM         Pointer to the current VM (if any).
    527  * @param   paArgs      Pointer to (readonly) array of arguments.
    528  * @param   cArgs       Number of arguments in the array.
    529  */
    530 static DECLCALLBACK(int) dbgcCmdStop(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    531 {
    532     /*
    533      * Check if the VM is halted or not before trying to halt it.
    534      */
    535     int rc;
    536     if (DBGFR3IsHalted(pVM))
    537         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "warning: The VM is already halted...\n");
    538     else
    539     {
    540         rc = DBGFR3Halt(pVM);
    541         if (VBOX_SUCCESS(rc))
    542             rc = VWRN_DBGC_CMD_PENDING;
    543         else
    544             rc = pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Executing DBGFR3Halt().");
    545     }
    546 
    547     NOREF(pCmd); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    548     return rc;
    549 }
    550 
    551 
    552 /**
    553  * The 'echo' command.
    554  *
    555  * @returns VBox status.
    556  * @param   pCmd        Pointer to the command descriptor (as registered).
    557  * @param   pCmdHlp     Pointer to command helper functions.
    558  * @param   pVM         Pointer to the current VM (if any).
    559  * @param   paArgs      Pointer to (readonly) array of arguments.
    560  * @param   cArgs       Number of arguments in the array.
    561  */
    562 static DECLCALLBACK(int) dbgcCmdEcho(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    563 {
    564     /*
    565      * Loop thru the arguments and print them with one space between.
    566      */
    567     int rc = 0;
    568     for (unsigned i = 0; i < cArgs; i++)
    569     {
    570         if (paArgs[i].enmType == DBGCVAR_TYPE_STRING)
    571             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, i ? " %s" : "%s", paArgs[i].u.pszString);
    572         else
    573             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, i ? " <parser error>" : "<parser error>");
    574         if (VBOX_FAILURE(rc))
    575             return rc;
    576     }
    577     NOREF(pCmd); NOREF(pResult); NOREF(pVM);
    578     return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "\n");
    579 }
    580 
    581 
    582 /**
    583  * The 'runscript' command.
    584  *
    585  * @returns VBox status.
    586  * @param   pCmd        Pointer to the command descriptor (as registered).
    587  * @param   pCmdHlp     Pointer to command helper functions.
    588  * @param   pVM         Pointer to the current VM (if any).
    589  * @param   paArgs      Pointer to (readonly) array of arguments.
    590  * @param   cArgs       Number of arguments in the array.
    591  */
    592 static DECLCALLBACK(int) dbgcCmdRunScript(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    593 {
    594     /* check that the parser did what it's supposed to do. */
    595     if (    cArgs != 1
    596         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    597         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "parser error\n");
    598 
    599     /*
    600      * Try open the script.
    601      */
    602     const char *pszFilename = paArgs[0].u.pszString;
    603     FILE *pFile = fopen(pszFilename, "r");
    604     if (!pFile)
    605         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Failed to open '%s'.\n", pszFilename);
    606 
    607     /*
    608      * Execute it line by line.
    609      */
    610     int rc = 0;
    611     unsigned iLine = 0;
    612     char szLine[8192];
    613     while (fgets(szLine, sizeof(szLine), pFile))
    614     {
    615         /* check that the line isn't too long. */
    616         char *pszEnd = strchr(szLine, '\0');
    617         if (pszEnd == &szLine[sizeof(szLine) - 1])
    618         {
    619             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "runscript error: Line #%u is too long\n", iLine);
    620             break;
    621         }
    622         iLine++;
    623 
    624         /* strip leading blanks and check for comment / blank line. */
    625         char *psz = RTStrStripL(szLine);
    626         if (    *psz == '\0'
    627             ||  *psz == '\n'
    628             ||  *psz == '#')
    629             continue;
    630 
    631         /* strip trailing blanks and check for empty line (\r case). */
    632         while (     pszEnd > psz
    633                &&   isspace(pszEnd[-1])) /* isspace includes \n and \r normally. */
    634             *--pszEnd = '\0';
    635 
    636         /** @todo check for Control-C / Cancel at this point... */
    637 
    638         /*
    639          * Execute the command.
    640          *
    641          * This is a bit wasteful with scratch space btw., can fix it later.
    642          * The whole return code crap should be fixed too, so that it's possible
    643          * to know whether a command succeeded (VBOX_SUCCESS()) or failed, and
    644          * more importantly why it failed.
    645          */
    646         rc = pCmdHlp->pfnExec(pCmdHlp, "%s", psz);
    647         if (VBOX_FAILURE(rc))
    648         {
    649             if (rc == VERR_BUFFER_OVERFLOW)
    650                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "runscript error: Line #%u is too long (exec overflowed)\n", iLine);
    651             break;
    652         }
    653         if (rc == VWRN_DBGC_CMD_PENDING)
    654         {
    655             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "runscript error: VWRN_DBGC_CMD_PENDING on line #%u, script terminated\n", iLine);
    656             break;
    657         }
    658     }
    659 
    660     fclose(pFile);
    661 
    662     NOREF(pCmd); NOREF(pResult); NOREF(pVM);
    663     return rc;
    664 }
    665 
    666 
    667 /**
    668  * Print formatted string.
    669  *
    670  * @param   pHlp        Pointer to this structure.
    671  * @param   pszFormat   The format string.
    672  * @param   ...         Arguments.
    673  */
    674 static DECLCALLBACK(void) dbgcCmdInfo_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
    675 {
    676     PDBGCCMDHLP pCmdHlp = *(PDBGCCMDHLP *)(pHlp + 1);
    677     va_list args;
    678     va_start(args,  pszFormat);
    679     pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
    680     va_end(args);
    681 }
    682 
    683 
    684 /**
    685  * Print formatted string.
    686  *
    687  * @param   pHlp        Pointer to this structure.
    688  * @param   pszFormat   The format string.
    689  * @param   args        Argument list.
    690  */
    691 static DECLCALLBACK(void) dbgcCmdInfo_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
    692 {
    693     PDBGCCMDHLP pCmdHlp = *(PDBGCCMDHLP *)(pHlp + 1);
    694     pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
    695 }
    696 
    697 
    698 /**
    699  * The 'info' command.
    700  *
    701  * @returns VBox status.
    702  * @param   pCmd        Pointer to the command descriptor (as registered).
    703  * @param   pCmdHlp     Pointer to command helper functions.
    704  * @param   pVM         Pointer to the current VM (if any).
    705  * @param   paArgs      Pointer to (readonly) array of arguments.
    706  * @param   cArgs       Number of arguments in the array.
    707  */
    708 static DECLCALLBACK(int) dbgcCmdInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    709 {
    710     /*
    711      * Validate input.
    712      */
    713     if (    cArgs < 1
    714         ||  cArgs > 2
    715         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING
    716         ||  paArgs[cArgs - 1].enmType != DBGCVAR_TYPE_STRING)
    717         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: The parser doesn't do its job properly yet.. quote the string.\n");
    718     if (!pVM)
    719         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    720 
    721     /*
    722      * Dump it.
    723      */
    724     struct
    725     {
    726         DBGFINFOHLP Hlp;
    727         PDBGCCMDHLP pCmdHlp;
    728     } Hlp = { { dbgcCmdInfo_Printf, dbgcCmdInfo_PrintfV }, pCmdHlp };
    729     int rc = DBGFR3Info(pVM, paArgs[0].u.pszString, cArgs == 2 ? paArgs[1].u.pszString : NULL, &Hlp.Hlp);
    730     if (VBOX_FAILURE(rc))
    731         return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3Info()\n");
    732 
    733     NOREF(pCmd); NOREF(pResult);
    734     return 0;
    735 }
    736 
    737 
    738 /**
    739  * The 'log' command.
    740  *
    741  * @returns VBox status.
    742  * @param   pCmd        Pointer to the command descriptor (as registered).
    743  * @param   pCmdHlp     Pointer to command helper functions.
    744  * @param   pVM         Pointer to the current VM (if any).
    745  * @param   paArgs      Pointer to (readonly) array of arguments.
    746  * @param   cArgs       Number of arguments in the array.
    747  */
    748 static DECLCALLBACK(int) dbgcCmdLog(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    749 {
    750     int rc = DBGFR3LogModifyGroups(pVM, paArgs[0].u.pszString);
    751     if (VBOX_SUCCESS(rc))
    752         return VINF_SUCCESS;
    753     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    754     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3LogModifyGroups(%p,'%s')\n", pVM, paArgs[0].u.pszString);
    755 }
    756 
    757 
    758 /**
    759  * The 'logdest' command.
    760  *
    761  * @returns VBox status.
    762  * @param   pCmd        Pointer to the command descriptor (as registered).
    763  * @param   pCmdHlp     Pointer to command helper functions.
    764  * @param   pVM         Pointer to the current VM (if any).
    765  * @param   paArgs      Pointer to (readonly) array of arguments.
    766  * @param   cArgs       Number of arguments in the array.
    767  */
    768 static DECLCALLBACK(int) dbgcCmdLogDest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    769 {
    770     int rc = DBGFR3LogModifyDestinations(pVM, paArgs[0].u.pszString);
    771     if (VBOX_SUCCESS(rc))
    772         return VINF_SUCCESS;
    773     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    774     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3LogModifyDestinations(%p,'%s')\n", pVM, paArgs[0].u.pszString);
    775 }
    776 
    777 
    778 /**
    779  * The 'logflags' command.
    780  *
    781  * @returns VBox status.
    782  * @param   pCmd        Pointer to the command descriptor (as registered).
    783  * @param   pCmdHlp     Pointer to command helper functions.
    784  * @param   pVM         Pointer to the current VM (if any).
    785  * @param   paArgs      Pointer to (readonly) array of arguments.
    786  * @param   cArgs       Number of arguments in the array.
    787  */
    788 static DECLCALLBACK(int) dbgcCmdLogFlags(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    789 {
    790     int rc = DBGFR3LogModifyFlags(pVM, paArgs[0].u.pszString);
    791     if (VBOX_SUCCESS(rc))
    792         return VINF_SUCCESS;
    793     NOREF(pCmd); NOREF(cArgs); NOREF(pResult);
    794     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGFR3LogModifyFlags(%p,'%s')\n", pVM, paArgs[0].u.pszString);
    795 }
    796 
    797 
    798 /**
    799  * The 'format' command.
    800  *
    801  * @returns VBox status.
    802  * @param   pCmd        Pointer to the command descriptor (as registered).
    803  * @param   pCmdHlp     Pointer to command helper functions.
    804  * @param   pVM         Pointer to the current VM (if any).
    805  * @param   paArgs      Pointer to (readonly) array of arguments.
    806  * @param   cArgs       Number of arguments in the array.
    807  */
    808 static DECLCALLBACK(int) dbgcCmdFormat(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    809 {
    810     LogFlow(("dbgcCmdFormat\n"));
    811     static const char *apszRangeDesc[] =
    812     {
    813         "none", "bytes", "elements"
    814     };
    815     int rc;
    816 
    817     for (unsigned iArg = 0; iArg < cArgs; iArg++)
    818     {
    819         switch (paArgs[iArg].enmType)
    820         {
    821             case DBGCVAR_TYPE_UNKNOWN:
    822                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    823                     "Unknown variable type!\n");
    824                 break;
    825             case DBGCVAR_TYPE_GC_FLAT:
    826                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    827                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    828                         "Guest flat address: %%%08x range %lld %s\n",
    829                         paArgs[iArg].u.GCFlat,
    830                         paArgs[iArg].u64Range,
    831                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    832                 else
    833                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    834                         "Guest flat address: %%%08x\n",
    835                         paArgs[iArg].u.GCFlat);
    836                 break;
    837             case DBGCVAR_TYPE_GC_FAR:
    838                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    839                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    840                         "Guest far address: %04x:%08x range %lld %s\n",
    841                         paArgs[iArg].u.GCFar.sel,
    842                         paArgs[iArg].u.GCFar.off,
    843                         paArgs[iArg].u64Range,
    844                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    845                 else
    846                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    847                         "Guest far address: %04x:%08x\n",
    848                         paArgs[iArg].u.GCFar.sel,
    849                         paArgs[iArg].u.GCFar.off);
    850                 break;
    851             case DBGCVAR_TYPE_GC_PHYS:
    852                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    853                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    854                         "Guest physical address: %%%%%08x range %lld %s\n",
    855                         paArgs[iArg].u.GCPhys,
    856                         paArgs[iArg].u64Range,
    857                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    858                 else
    859                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    860                         "Guest physical address: %%%%%08x\n",
    861                         paArgs[iArg].u.GCPhys);
    862                 break;
    863             case DBGCVAR_TYPE_HC_FLAT:
    864                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    865                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    866                         "Host flat address: %%%08x range %lld %s\n",
    867                         paArgs[iArg].u.pvHCFlat,
    868                         paArgs[iArg].u64Range,
    869                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    870                 else
    871                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    872                         "Host flat address: %%%08x\n",
    873                         paArgs[iArg].u.pvHCFlat);
    874                 break;
    875             case DBGCVAR_TYPE_HC_FAR:
    876                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    877                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    878                         "Host far address: %04x:%08x range %lld %s\n",
    879                         paArgs[iArg].u.HCFar.sel,
    880                         paArgs[iArg].u.HCFar.off,
    881                         paArgs[iArg].u64Range,
    882                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    883                 else
    884                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    885                         "Host far address: %04x:%08x\n",
    886                         paArgs[iArg].u.HCFar.sel,
    887                         paArgs[iArg].u.HCFar.off);
    888                 break;
    889             case DBGCVAR_TYPE_HC_PHYS:
    890                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    891                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    892                         "Host physical address: %VHp range %lld %s\n",
    893                         paArgs[iArg].u.HCPhys,
    894                         paArgs[iArg].u64Range,
    895                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    896                 else
    897                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    898                         "Host physical address: %VHp\n",
    899                         paArgs[iArg].u.HCPhys);
    900                 break;
    901 
    902             case DBGCVAR_TYPE_STRING:
    903                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    904                     "String, %lld bytes long: %s\n",
    905                     paArgs[iArg].u64Range,
    906                     paArgs[iArg].u.pszString);
    907                 break;
    908 
    909             case DBGCVAR_TYPE_NUMBER:
    910                 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE)
    911                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    912                         "Number: hex %llx  dec 0i%lld  oct 0t%llo  range %lld %s\n",
    913                         paArgs[iArg].u.u64Number,
    914                         paArgs[iArg].u.u64Number,
    915                         paArgs[iArg].u.u64Number,
    916                         paArgs[iArg].u64Range,
    917                         apszRangeDesc[paArgs[iArg].enmRangeType]);
    918                 else
    919                     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    920                         "Number: hex %llx  dec 0i%lld  oct 0t%llo\n",
    921                         paArgs[iArg].u.u64Number,
    922                         paArgs[iArg].u.u64Number,
    923                         paArgs[iArg].u.u64Number);
    924                 break;
    925 
    926             default:
    927                 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    928                     "Invalid argument type %d\n",
    929                     paArgs[iArg].enmType);
    930                 break;
    931         }
    932     } /* arg loop */
    933 
    934     NOREF(pCmd); NOREF(pVM); NOREF(pResult);
    935     return 0;
    936 }
    937 
    938 
    939 /**
    940  * The 'loadsyms' command.
    941  *
    942  * @returns VBox status.
    943  * @param   pCmd        Pointer to the command descriptor (as registered).
    944  * @param   pCmdHlp     Pointer to command helper functions.
    945  * @param   pVM         Pointer to the current VM (if any).
    946  * @param   paArgs      Pointer to (readonly) array of arguments.
    947  * @param   cArgs       Number of arguments in the array.
    948  */
    949 static DECLCALLBACK(int) dbgcCmdLoadSyms(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    950 {
    951     /*
    952      * Validate the parsing and make sense of the input.
    953      * This is a mess as usual because we don't trust the parser yet.
    954      */
    955     if (    cArgs < 1
    956         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    957     {
    958         AssertMsgFailed(("Parse error, first argument required to be string!\n"));
    959         return VERR_PARSE_INCORRECT_ARG_TYPE;
    960     }
    961     DBGCVAR     AddrVar;
    962     RTGCUINTPTR Delta = 0;
    963     const char *pszModule = NULL;
    964     RTGCUINTPTR ModuleAddress = 0;
    965     unsigned    cbModule = 0;
    966     if (cArgs > 1)
    967     {
    968         unsigned iArg = 1;
    969         if (paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
    970         {
    971             Delta = (RTGCUINTPTR)paArgs[iArg].u.u64Number;
    972             iArg++;
    973         }
    974         if (iArg < cArgs)
    975         {
    976             if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
    977             {
    978                 AssertMsgFailed(("Parse error, module argument required to be string!\n"));
    979                 return VERR_PARSE_INCORRECT_ARG_TYPE;
    980             }
    981             pszModule = paArgs[iArg].u.pszString;
    982             iArg++;
    983             if (iArg < cArgs)
    984             {
    985                 if (DBGCVAR_ISPOINTER(paArgs[iArg].enmType))
    986                 {
    987                     AssertMsgFailed(("Parse error, module argument required to be GC pointer!\n"));
    988                     return VERR_PARSE_INCORRECT_ARG_TYPE;
    989                 }
    990                 int rc = pCmdHlp->pfnEval(pCmdHlp, &AddrVar, "%%(%Dv)", &paArgs[iArg]);
    991                 if (VBOX_FAILURE(rc))
    992                     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Module address cast %%(%Dv) failed.", &paArgs[iArg]);
    993                 ModuleAddress = paArgs[iArg].u.GCFlat;
    994                 iArg++;
    995                 if (iArg < cArgs)
    996                 {
    997                     if (paArgs[iArg].enmType != DBGCVAR_TYPE_NUMBER)
    998                     {
    999                         AssertMsgFailed(("Parse error, module argument required to be an interger!\n"));
    1000                         return VERR_PARSE_INCORRECT_ARG_TYPE;
    1001                     }
    1002                     cbModule = (unsigned)paArgs[iArg].u.u64Number;
    1003                     iArg++;
    1004                     if (iArg < cArgs)
    1005                     {
    1006                         AssertMsgFailed(("Parse error, too many arguments!\n"));
    1007                         return VERR_PARSE_TOO_MANY_ARGUMENTS;
    1008                     }
    1009                 }
    1010             }
    1011         }
    1012     }
    1013 
    1014     /*
    1015      * Call the debug info manager about this loading...
    1016      */
    1017     int rc = DBGFR3ModuleLoad(pVM, paArgs[0].u.pszString, Delta, pszModule, ModuleAddress, cbModule);
    1018     if (VBOX_FAILURE(rc))
    1019         return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "DBGInfoSymbolLoad(, '%s', %VGv, '%s', %VGv, 0)\n",
    1020                                      paArgs[0].u.pszString, Delta, pszModule, ModuleAddress);
    1021 
    1022     NOREF(pCmd); NOREF(pResult);
    1023     return VINF_SUCCESS;
    1024 }
    1025 
    1026 
    1027 /**
    1028  * The 'set' command.
    1029  *
    1030  * @returns VBox status.
    1031  * @param   pCmd        Pointer to the command descriptor (as registered).
    1032  * @param   pCmdHlp     Pointer to command helper functions.
    1033  * @param   pVM         Pointer to the current VM (if any).
    1034  * @param   paArgs      Pointer to (readonly) array of arguments.
    1035  * @param   cArgs       Number of arguments in the array.
    1036  */
    1037 static DECLCALLBACK(int) dbgcCmdSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1038 {
    1039     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1040 
    1041     /* parse sanity check. */
    1042     AssertMsg(paArgs[0].enmType == DBGCVAR_TYPE_STRING, ("expected string not %d as first arg!\n", paArgs[0].enmType));
    1043     if (paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    1044         return VERR_PARSE_INCORRECT_ARG_TYPE;
    1045 
    1046 
    1047     /*
    1048      * A variable must start with an alpha chars and only contain alpha numerical chars.
    1049      */
    1050     const char *pszVar = paArgs[0].u.pszString;
    1051     if (!isalpha(*pszVar) || *pszVar == '_')
    1052         return pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    1053             "syntax error: Invalid variable name '%s'. Variable names must match regex '[_a-zA-Z][_a-zA-Z0-9*'!", paArgs[0].u.pszString);
    1054 
    1055     while (isalnum(*pszVar) || *pszVar == '_')
    1056         *pszVar++;
    1057     if (*pszVar)
    1058         return pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    1059             "syntax error: Invalid variable name '%s'. Variable names must match regex '[_a-zA-Z][_a-zA-Z0-9*]'!", paArgs[0].u.pszString);
    1060 
    1061 
    1062     /*
    1063      * Calc variable size.
    1064      */
    1065     size_t  cbVar = (size_t)paArgs[0].u64Range + sizeof(DBGCNAMEDVAR);
    1066     if (paArgs[1].enmType == DBGCVAR_TYPE_STRING)
    1067         cbVar += 1 + (size_t)paArgs[1].u64Range;
    1068 
    1069     /*
    1070      * Look for existing one.
    1071      */
    1072     pszVar = paArgs[0].u.pszString;
    1073     for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
    1074     {
    1075         if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
    1076         {
    1077             /*
    1078              * Update existing variable.
    1079              */
    1080             void *pv = RTMemRealloc(pDbgc->papVars[iVar], cbVar);
    1081             if (!pv)
    1082                 return VERR_PARSE_NO_MEMORY;
    1083             PDBGCNAMEDVAR pVar = pDbgc->papVars[iVar] = (PDBGCNAMEDVAR)pv;
    1084 
    1085             pVar->Var = paArgs[1];
    1086             memcpy(pVar->szName, paArgs[0].u.pszString, (size_t)paArgs[0].u64Range + 1);
    1087             if (paArgs[1].enmType == DBGCVAR_TYPE_STRING)
    1088                 pVar->Var.u.pszString = (char *)memcpy(&pVar->szName[paArgs[0].u64Range + 1], paArgs[1].u.pszString, (size_t)paArgs[1].u64Range + 1);
    1089             return 0;
    1090         }
    1091     }
    1092 
    1093     /*
    1094      * Allocate another.
    1095      */
    1096     PDBGCNAMEDVAR pVar = (PDBGCNAMEDVAR)RTMemAlloc(cbVar);
    1097 
    1098     pVar->Var = paArgs[1];
    1099     memcpy(pVar->szName, pszVar, (size_t)paArgs[0].u64Range + 1);
    1100     if (paArgs[1].enmType == DBGCVAR_TYPE_STRING)
    1101         pVar->Var.u.pszString = (char *)memcpy(&pVar->szName[paArgs[0].u64Range + 1], paArgs[1].u.pszString, (size_t)paArgs[1].u64Range + 1);
    1102 
    1103     /* need to reallocate the pointer array too? */
    1104     if (!(pDbgc->cVars % 0x20))
    1105     {
    1106         void *pv = RTMemRealloc(pDbgc->papVars, (pDbgc->cVars + 0x20) * sizeof(pDbgc->papVars[0]));
    1107         if (!pv)
    1108         {
    1109             RTMemFree(pVar);
    1110             return VERR_PARSE_NO_MEMORY;
    1111         }
    1112         pDbgc->papVars = (PDBGCNAMEDVAR *)pv;
    1113     }
    1114     pDbgc->papVars[pDbgc->cVars++] = pVar;
    1115 
    1116     NOREF(pCmd); NOREF(pVM); NOREF(cArgs); NOREF(pResult);
    1117     return 0;
    1118 }
    1119 
    1120 
    1121 /**
    1122  * The 'unset' command.
    1123  *
    1124  * @returns VBox status.
    1125  * @param   pCmd        Pointer to the command descriptor (as registered).
    1126  * @param   pCmdHlp     Pointer to command helper functions.
    1127  * @param   pVM         Pointer to the current VM (if any).
    1128  * @param   paArgs      Pointer to (readonly) array of arguments.
    1129  * @param   cArgs       Number of arguments in the array.
    1130  */
    1131 static DECLCALLBACK(int) dbgcCmdUnset(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1132 {
    1133     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1134 
    1135     /*
    1136      * Don't trust the parser.
    1137      */
    1138     for (unsigned  i = 0; i < cArgs; i++)
    1139         if (paArgs[i].enmType != DBGCVAR_TYPE_STRING)
    1140         {
    1141             AssertMsgFailed(("expected strings only. (arg=%d)!\n", i));
    1142             return VERR_PARSE_INCORRECT_ARG_TYPE;
    1143         }
    1144 
    1145     /*
    1146      * Iterate the variables and unset them.
    1147      */
    1148     for (unsigned iArg = 0; iArg < cArgs; iArg++)
    1149     {
    1150         const char *pszVar = paArgs[iArg].u.pszString;
    1151 
    1152         /*
    1153          * Look up the variable.
    1154          */
    1155         for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
    1156         {
    1157             if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
    1158             {
    1159                 /*
    1160                  * Shuffle the array removing this entry.
    1161                  */
    1162                 void *pvFree = pDbgc->papVars[iVar];
    1163                 if (iVar + 1 < pDbgc->cVars)
    1164                     memmove(&pDbgc->papVars[iVar],
    1165                             &pDbgc->papVars[iVar + 1],
    1166                             (pDbgc->cVars - iVar - 1) * sizeof(pDbgc->papVars[0]));
    1167                 pDbgc->papVars[--pDbgc->cVars] = NULL;
    1168 
    1169                 RTMemFree(pvFree);
    1170             }
    1171         } /* lookup */
    1172     } /* arg loop */
    1173 
    1174     NOREF(pCmd); NOREF(pVM); NOREF(pResult);
    1175     return 0;
    1176 }
    1177 
    1178 
    1179 /**
    1180  * The 'loadvars' 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) dbgcCmdLoadVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1190 {
    1191     /*
    1192      * Don't trust the parser.
    1193      */
    1194     if (    cArgs != 1
    1195         ||  paArgs[0].enmType != DBGCVAR_TYPE_STRING)
    1196     {
    1197         AssertMsgFailed(("Expected one string exactly!\n"));
    1198         return VERR_PARSE_INCORRECT_ARG_TYPE;
    1199     }
    1200 
    1201     /*
    1202      * Iterate the variables and unset them.
    1203      */
    1204     FILE *pFile = fopen(paArgs[0].u.pszString, "r");
    1205     if (pFile)
    1206     {
    1207         char szLine[4096];
    1208         while (fgets(szLine, sizeof(szLine), pFile))
    1209         {
    1210             /* Strip it. */
    1211             char *psz = szLine;
    1212             while (isblank(*psz))
    1213                 psz++;
    1214             int i = (int)strlen(psz) - 1;
    1215             while (i >= 0 && isspace(psz[i]))
    1216                 psz[i--] ='\0';
    1217             /* Execute it if not comment or empty line. */
    1218             if (    *psz != '\0'
    1219                 &&  *psz != '#'
    1220                 &&  *psz != ';')
    1221             {
    1222                 pCmdHlp->pfnPrintf(pCmdHlp, NULL, "dbg: set %s", psz);
    1223                 pCmdHlp->pfnExec(pCmdHlp, "set %s", psz);
    1224             }
    1225         }
    1226         fclose(pFile);
    1227     }
    1228     else
    1229         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Failed to open file '%s'.\n", paArgs[0].u.pszString);
    1230 
    1231     NOREF(pCmd); NOREF(pVM); NOREF(pResult);
    1232     return 0;
    1233 }
    1234 
    1235 
    1236 /**
    1237  * The 'showvars' command.
    1238  *
    1239  * @returns VBox status.
    1240  * @param   pCmd        Pointer to the command descriptor (as registered).
    1241  * @param   pCmdHlp     Pointer to command helper functions.
    1242  * @param   pVM         Pointer to the current VM (if any).
    1243  * @param   paArgs      Pointer to (readonly) array of arguments.
    1244  * @param   cArgs       Number of arguments in the array.
    1245  */
    1246 static DECLCALLBACK(int) dbgcCmdShowVars(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1247 {
    1248     PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
    1249 
    1250     for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
    1251     {
    1252         int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%-20s ", &pDbgc->papVars[iVar]->szName);
    1253         if (!rc)
    1254             rc = dbgcCmdFormat(pCmd, pCmdHlp, pVM, &pDbgc->papVars[iVar]->Var, 1, NULL);
    1255         if (rc)
    1256             return rc;
    1257     }
    1258 
    1259     NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    1260     return 0;
    1261 }
    1262 
    1263 
    1264 /**
    1265  * The 'harakiri' command.
    1266  *
    1267  * @returns VBox status.
    1268  * @param   pCmd        Pointer to the command descriptor (as registered).
    1269  * @param   pCmdHlp     Pointer to command helper functions.
    1270  * @param   pVM         Pointer to the current VM (if any).
    1271  * @param   paArgs      Pointer to (readonly) array of arguments.
    1272  * @param   cArgs       Number of arguments in the array.
    1273  */
    1274 static DECLCALLBACK(int) dbgcCmdHarakiri(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
    1275 {
    1276     Log(("dbgcCmdHarakiri\n"));
    1277     for (;;)
    1278         exit(126);
    1279     NOREF(pCmd); NOREF(pCmdHlp); NOREF(pVM); NOREF(paArgs); NOREF(cArgs); NOREF(pResult);
    1280 }
    1281143
    1282144
     
    24781340
    24791341    return VERR_PARSE_NOT_IMPLEMENTED;
    2480 }
    2481 
    2482 
    2483 
    2484 /**
    2485  * Finds a routine.
    2486  *
    2487  * @returns Pointer to the command descriptor.
    2488  *          If the request was for an external command, the caller is responsible for
    2489  *          unlocking the external command list.
    2490  * @returns NULL if not found.
    2491  * @param   pDbgc       The debug console instance.
    2492  * @param   pachName    Pointer to the routine string (not terminated).
    2493  * @param   cchName     Length of the routine name.
    2494  * @param   fExternal   Whether or not the routine is external.
    2495  */
    2496 static PCDBGCCMD dbgcRoutineLookup(PDBGC pDbgc, const char *pachName, size_t cchName, bool fExternal)
    2497 {
    2498     if (!fExternal)
    2499     {
    2500         /* emulation first, so commands can be overloaded (info ++). */
    2501         PCDBGCCMD pCmd = pDbgc->paEmulationCmds;
    2502         unsigned cLeft = pDbgc->cEmulationCmds;
    2503         while (cLeft-- > 0)
    2504         {
    2505             if (    !strncmp(pachName, pCmd->pszCmd, cchName)
    2506                 &&  !pCmd->pszCmd[cchName])
    2507                 return pCmd;
    2508             pCmd++;
    2509         }
    2510 
    2511         for (unsigned iCmd = 0; iCmd < ELEMENTS(g_aCmds); iCmd++)
    2512         {
    2513             if (    !strncmp(pachName, g_aCmds[iCmd].pszCmd, cchName)
    2514                 &&  !g_aCmds[iCmd].pszCmd[cchName])
    2515                 return &g_aCmds[iCmd];
    2516         }
    2517     }
    2518     else
    2519     {
    2520         DBGCEXTCMDS_LOCK_RD();
    2521         for (PDBGCEXTCMDS pExtCmds = g_pExtCmdsHead; pExtCmds; pExtCmds = pExtCmds->pNext)
    2522         {
    2523             for (unsigned iCmd = 0; iCmd < pExtCmds->cCmds; iCmd++)
    2524             {
    2525                 if (    !strncmp(pachName, pExtCmds->paCmds[iCmd].pszCmd, cchName)
    2526                     &&  !pExtCmds->paCmds[iCmd].pszCmd[cchName])
    2527                     return &pExtCmds->paCmds[iCmd];
    2528             }
    2529         }
    2530         DBGCEXTCMDS_UNLOCK_RD();
    2531     }
    2532 
    2533     NOREF(pDbgc);
    2534     return NULL;
    25351342}
    25361343
     
    41192926}
    41202927
    4121 
    4122 
    4123 /**
    4124  * Register one or more external commands.
    4125  *
    4126  * @returns VBox status.
    4127  * @param   paCommands      Pointer to an array of command descriptors.
    4128  *                          The commands must be unique. It's not possible
    4129  *                          to register the same commands more than once.
    4130  * @param   cCommands       Number of commands.
    4131  */
    4132 DBGDECL(int)    DBGCRegisterCommands(PCDBGCCMD paCommands, unsigned cCommands)
    4133 {
    4134     /*
    4135      * Lock the list.
    4136      */
    4137     DBGCEXTCMDS_LOCK_WR();
    4138     PDBGCEXTCMDS pCur = g_pExtCmdsHead;
    4139     while (pCur)
    4140     {
    4141         if (paCommands == pCur->paCmds)
    4142         {
    4143             DBGCEXTCMDS_UNLOCK_WR();
    4144             AssertMsgFailed(("Attempt at re-registering %d command(s)!\n", cCommands));
    4145             return VWRN_DBGC_ALREADY_REGISTERED;
    4146         }
    4147         pCur = pCur->pNext;
    4148     }
    4149 
    4150     /*
    4151      * Allocate new chunk.
    4152      */
    4153     int rc = 0;
    4154     pCur = (PDBGCEXTCMDS)RTMemAlloc(sizeof(*pCur));
    4155     if (pCur)
    4156     {
    4157         pCur->cCmds  = cCommands;
    4158         pCur->paCmds = paCommands;
    4159         pCur->pNext = g_pExtCmdsHead;
    4160         g_pExtCmdsHead = pCur;
    4161     }
    4162     else
    4163         rc = VERR_NO_MEMORY;
    4164     DBGCEXTCMDS_UNLOCK_WR();
    4165 
    4166     return rc;
    4167 }
    4168 
    4169 
    4170 /**
    4171  * Deregister one or more external commands previously registered by
    4172  * DBGCRegisterCommands().
    4173  *
    4174  * @returns VBox status.
    4175  * @param   paCommands      Pointer to an array of command descriptors
    4176  *                          as given to DBGCRegisterCommands().
    4177  * @param   cCommands       Number of commands.
    4178  */
    4179 DBGDECL(int)    DBGCDeregisterCommands(PCDBGCCMD paCommands, unsigned cCommands)
    4180 {
    4181     /*
    4182      * Lock the list.
    4183      */
    4184     DBGCEXTCMDS_LOCK_WR();
    4185     PDBGCEXTCMDS pPrev = NULL;
    4186     PDBGCEXTCMDS pCur = g_pExtCmdsHead;
    4187     while (pCur)
    4188     {
    4189         if (paCommands == pCur->paCmds)
    4190         {
    4191             if (pPrev)
    4192                 pPrev->pNext = pCur->pNext;
    4193             else
    4194                 g_pExtCmdsHead = pCur->pNext;
    4195             DBGCEXTCMDS_UNLOCK_WR();
    4196 
    4197             RTMemFree(pCur);
    4198             return VINF_SUCCESS;
    4199         }
    4200         pPrev = pCur;
    4201         pCur = pCur->pNext;
    4202     }
    4203     DBGCEXTCMDS_UNLOCK_WR();
    4204 
    4205     NOREF(cCommands);
    4206     return VERR_DBGC_COMMANDS_NOT_REGISTERED;
    4207 }
    4208 
Note: See TracChangeset for help on using the changeset viewer.

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