Changeset 5675 in vbox for trunk/src/VBox/Debugger/DBGConsole.cpp
- Timestamp:
- Nov 11, 2007 5:42:00 AM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 26019
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGConsole.cpp
r5674 r5675 131 131 * Internal Functions * 132 132 *******************************************************************************/ 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 150 133 static int dbgcEvalSub(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pResult); 151 134 static int dbgcProcessCommand(PDBGC pDbgc, char *pszCmd, size_t cchCmd); … … 155 138 * Global Variables * 156 139 *******************************************************************************/ 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 283 140 /** Bitmap where set bits indicates the characters the may start an operator name. */ 284 141 static uint32_t g_bmOperatorChars[256 / (4*8)]; 285 142 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 else315 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 else329 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <optional-%u>\n", pCmd->paArgDescs[i].cTimesMax);330 }331 else332 {333 if (pCmd->paArgDescs[i].cTimesMax == ~0U)334 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " <%u+>\n", pCmd->paArgDescs[i].cTimesMin);335 else336 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 else423 {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 ( !fFound452 && g_pExtCmdsHead453 && 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 else539 {540 rc = DBGFR3Halt(pVM);541 if (VBOX_SUCCESS(rc))542 rc = VWRN_DBGC_CMD_PENDING;543 else544 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 else573 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 != 1596 || 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 > psz633 && 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 possible643 * to know whether a command succeeded (VBOX_SUCCESS()) or failed, and644 * 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 < 1714 || cArgs > 2715 || paArgs[0].enmType != DBGCVAR_TYPE_STRING716 || 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 struct725 {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 else833 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 else846 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 else859 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 else871 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 else884 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 else897 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 else919 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 < 1956 || 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 != 11195 || 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 else1229 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 }1281 143 1282 144 … … 2478 1340 2479 1341 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 for2489 * 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 else2519 {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;2535 1342 } 2536 1343 … … 4119 2926 } 4120 2927 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 possible4129 * 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 else4163 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 by4172 * DBGCRegisterCommands().4173 *4174 * @returns VBox status.4175 * @param paCommands Pointer to an array of command descriptors4176 * 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 else4194 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.