/** * Make a console instance. * * This will not return until either an 'exit' command is issued or a error code * indicating connection loss is encountered. * * @returns VINF_SUCCESS if console termination caused by the 'exit' command. * @returns The VBox status code causing the console termination. * * @param pUVM The user mode VM handle. * @param pBack Pointer to the backend structure. This must contain * a full set of function pointers to service the console. * @param fFlags Reserved, must be zero. * @remarks A forced termination of the console is easiest done by forcing the * callbacks to return fatal failures. */ DBGDECL(int) DBGCCreate(PUVM pUVM, PDBGCBACK pBack, unsigned fFlags) { /* * Validate input. */ AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE); PVM pVM = NULL; if (pUVM) { pVM = VMR3GetVM(pUVM); AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE); } /* * Allocate and initialize instance data */ PDBGC pDbgc; int rc = dbgcCreate(&pDbgc, pBack, fFlags); if (RT_FAILURE(rc)) return rc; if (!HMR3IsEnabled(pUVM)) pDbgc->hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL; /* * Print welcome message. */ rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Welcome to the VirtualBox Debugger!\n"); /* * Attach to the specified VM. */ if (RT_SUCCESS(rc) && pUVM) { rc = dbgcReadConfig(pDbgc, pUVM); if (RT_SUCCESS(rc)) { rc = DBGFR3Attach(pUVM); if (RT_SUCCESS(rc)) { pDbgc->pVM = pVM; pDbgc->pUVM = pUVM; pDbgc->idCpu = 0; rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Current VM is %08x, CPU #%u\n" /** @todo get and print the VM name! */ , pDbgc->pVM, pDbgc->idCpu); } else rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to attach to VM %p\n", pDbgc->pVM); } else rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "Error reading configuration\n"); } /* * Load plugins. */ if (RT_SUCCESS(rc)) { if (pVM) DBGFR3PlugInLoadAll(pDbgc->pUVM); dbgcEventInit(pDbgc); dbgcRunInitScripts(pDbgc); rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> "); if (RT_SUCCESS(rc)) { /* * Set debug config log callback. */ RTDBGCFG hDbgCfg = DBGFR3AsGetConfig(pUVM); if ( hDbgCfg != NIL_RTDBGCFG && RTDbgCfgRetain(hDbgCfg) != UINT32_MAX) { int rc2 = RTDbgCfgSetLogCallback(hDbgCfg, dbgcDbgCfgLogCallback, pDbgc); if (RT_FAILURE(rc2)) { hDbgCfg = NIL_RTDBGCFG; RTDbgCfgRelease(hDbgCfg); } } else hDbgCfg = NIL_RTDBGCFG; /* * Run the debugger main loop. */ rc = dbgcRun(pDbgc); /* * Remove debug config log callback. */ if (hDbgCfg != NIL_RTDBGCFG) { RTDbgCfgSetLogCallback(hDbgCfg, NULL, NULL); RTDbgCfgRelease(hDbgCfg); } } dbgcEventTerm(pDbgc); } else pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nDBGCCreate error: %Rrc\n", rc); /* * Cleanup console debugger session. */ dbgcDestroy(pDbgc); return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc; }
/** * Make a console instance. * * This will not return until either an 'exit' command is issued or a error code * indicating connection loss is encountered. * * @returns VINF_SUCCESS if console termination caused by the 'exit' command. * @returns The VBox status code causing the console termination. * * @param pVM VM Handle. * @param pBack Pointer to the backend structure. This must contain * a full set of function pointers to service the console. * @param fFlags Reserved, must be zero. * @remark A forced termination of the console is easiest done by forcing the * callbacks to return fatal failures. */ DBGDECL(int) DBGCCreate(PVM pVM, PDBGCBACK pBack, unsigned fFlags) { /* * Validate input. */ AssertPtrNullReturn(pVM, VERR_INVALID_POINTER); /* * Allocate and initialize instance data */ PDBGC pDbgc; int rc = dbgcCreate(&pDbgc, pBack, fFlags); if (RT_FAILURE(rc)) return rc; /* * Print welcome message. */ rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Welcome to the VirtualBox Debugger!\n"); /* * Attach to the specified VM. */ if (RT_SUCCESS(rc) && pVM) { rc = DBGFR3Attach(pVM); if (RT_SUCCESS(rc)) { pDbgc->pVM = pVM; pDbgc->idCpu = 0; rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Current VM is %08x, CPU #%u\n" /** @todo get and print the VM name! */ , pDbgc->pVM, pDbgc->idCpu); } else rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to attach to VM %p\n", pDbgc->pVM); } /* * Load plugins. */ if (RT_SUCCESS(rc)) { if (pVM) dbgcPlugInAutoLoad(pDbgc); rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> "); } else pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nDBGCCreate error: %Rrc\n", rc); /* * Run the debugger main loop. */ if (RT_SUCCESS(rc)) rc = dbgcRun(pDbgc); /* * Cleanup console debugger session. */ dbgcDestroy(pDbgc); return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc; }
int main() { /* * Init. */ int rc = RTTestInitAndCreate("tstDBGCParser", &g_hTest); if (rc) return rc; RTTestBanner(g_hTest); /* * Create a DBGC instance. */ RTTestSub(g_hTest, "dbgcCreate"); PDBGC pDbgc; rc = dbgcCreate(&pDbgc, &g_tstBack, 0); if (RT_SUCCESS(rc)) { rc = dbgcProcessInput(pDbgc, true /* fNoExecute */); tstCompleteOutput(); if (RT_SUCCESS(rc)) { RTTestSub(g_hTest, "basic parsing"); tstTry(pDbgc, "stop\n", VINF_SUCCESS); tstTry(pDbgc, "format 1\n", VINF_SUCCESS); tstTry(pDbgc, "format \n", VERR_PARSE_TOO_FEW_ARGUMENTS); tstTry(pDbgc, "format 0 1 23 4\n", VERR_PARSE_TOO_MANY_ARGUMENTS); tstTry(pDbgc, "sa 3 23 4 'q' \"21123123\" 'b' \n", VINF_SUCCESS); if (RTTestErrorCount(g_hTest) == 0) { RTTestSub(g_hTest, "Operators"); tstNumOp(pDbgc, "1", 1); tstNumOp(pDbgc, "1", 1); tstNumOp(pDbgc, "1", 1); tstNumOp(pDbgc, "+1", 1); tstNumOp(pDbgc, "++++++1", 1); tstNumOp(pDbgc, "-1", UINT64_MAX); tstNumOp(pDbgc, "--1", 1); tstNumOp(pDbgc, "---1", UINT64_MAX); tstNumOp(pDbgc, "----1", 1); tstNumOp(pDbgc, "~0", UINT64_MAX); tstNumOp(pDbgc, "~1", UINT64_MAX-1); tstNumOp(pDbgc, "~~0", 0); tstNumOp(pDbgc, "~~1", 1); tstNumOp(pDbgc, "!1", 0); tstNumOp(pDbgc, "!0", 1); tstNumOp(pDbgc, "!42", 0); tstNumOp(pDbgc, "!!42", 1); tstNumOp(pDbgc, "!!!42", 0); tstNumOp(pDbgc, "!!!!42", 1); tstNumOp(pDbgc, "1 +1", 2); tstNumOp(pDbgc, "1 + 1", 2); tstNumOp(pDbgc, "1+1", 2); tstNumOp(pDbgc, "1+ 1", 2); tstNumOp(pDbgc, "1 - 1", 0); tstNumOp(pDbgc, "99 - 90", 9); tstNumOp(pDbgc, "2 * 2", 4); tstNumOp(pDbgc, "2 / 2", 1); tstNumOp(pDbgc, "2 / 0", UINT64_MAX); tstNumOp(pDbgc, "0i1024 / 0i4", 256); tstNumOp(pDbgc, "1<<1", 2); tstNumOp(pDbgc, "1<<0i32", UINT64_C(0x0000000100000000)); tstNumOp(pDbgc, "1<<0i48", UINT64_C(0x0001000000000000)); tstNumOp(pDbgc, "1<<0i63", UINT64_C(0x8000000000000000)); tstNumOp(pDbgc, "fedcba0987654321>>0i04", UINT64_C(0x0fedcba098765432)); tstNumOp(pDbgc, "fedcba0987654321>>0i32", UINT64_C(0xfedcba09)); tstNumOp(pDbgc, "fedcba0987654321>>0i48", UINT64_C(0x0000fedc)); tstNumOp(pDbgc, "0ef & 4", 4); tstNumOp(pDbgc, "01234567891 & fff", UINT64_C(0x00000000891)); tstNumOp(pDbgc, "01234567891 & ~fff", UINT64_C(0x01234567000)); tstNumOp(pDbgc, "1 | 1", 1); tstNumOp(pDbgc, "0 | 4", 4); tstNumOp(pDbgc, "4 | 0", 4); tstNumOp(pDbgc, "4 | 4", 4); tstNumOp(pDbgc, "1 | 4 | 2", 7); tstNumOp(pDbgc, "1 ^ 1", 0); tstNumOp(pDbgc, "1 ^ 0", 1); tstNumOp(pDbgc, "0 ^ 1", 1); tstNumOp(pDbgc, "3 ^ 1", 2); tstNumOp(pDbgc, "7 ^ 3", 4); tstNumOp(pDbgc, "7 || 3", 1); tstNumOp(pDbgc, "1 || 0", 1); tstNumOp(pDbgc, "0 || 1", 1); tstNumOp(pDbgc, "0 || 0", 0); tstNumOp(pDbgc, "0 && 0", 0); tstNumOp(pDbgc, "1 && 0", 0); tstNumOp(pDbgc, "0 && 1", 0); tstNumOp(pDbgc, "1 && 1", 1); tstNumOp(pDbgc, "4 && 1", 1); } if (RTTestErrorCount(g_hTest) == 0) { RTTestSub(g_hTest, "Odd cases"); tstTry(pDbgc, "r @rax\n", VINF_SUCCESS); tstTry(pDbgc, "r @eax\n", VINF_SUCCESS); tstTry(pDbgc, "r @ah\n", VINF_SUCCESS); } } dbgcDestroy(pDbgc); } /* * Summary */ return RTTestSummaryAndDestroy(g_hTest); }