diff options
| author | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2011-01-12 14:54:12 +0000 |
|---|---|---|
| committer | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2011-01-12 14:54:12 +0000 |
| commit | 7f07e0a69b95b29b1381e0f74d1314e2b5228332 (patch) | |
| tree | 4669ececf4cff8082cb34e2f02148965dd0b04bf /src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp | |
| parent | 2ea982aa56923ca9e1acfc935aa3588e6121d731 (diff) | |
| download | VirtualBox-svn-7f07e0a69b95b29b1381e0f74d1314e2b5228332.tar.gz | |
VBoxManage: Added the getregisters and setregisters subcommands to debugvm. Document them and other recent debugvm additions.
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@35508 cfe28804-0f27-0410-a406-dd0f0b0b656f
Diffstat (limited to 'src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp')
| -rw-r--r-- | src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp index dd81a8fbdea..914b3489a1f 100644 --- a/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp +++ b/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp @@ -43,6 +43,71 @@ /** + * Handles the getregisters sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * We take a list of register names (case insensitive). If 'all' is + * encountered we'll dump all registers. + */ + ULONG idCpu = 0; + unsigned cRegisters = 0; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, + }; + int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(rc, RTEXITCODE_FAILURE); + + while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (rc) + { + case 'c': + idCpu = ValueUnion.u32; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!RTStrICmp(ValueUnion.psz, "all")) + { + com::SafeArray<BSTR> aBstrNames; + com::SafeArray<BSTR> aBstrValues; + CHECK_ERROR2_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames), ComSafeArrayAsOutParam(aBstrValues)), + RTEXITCODE_FAILURE); + Assert(aBstrNames.size() == aBstrValues.size()); + + for (size_t i = 0; i < aBstrNames.size(); i++) + RTPrintf("%ls = %ls\n", aBstrNames[i], aBstrValues[i]); + } + else + { + com::Bstr bstrName = ValueUnion.psz; + com::Bstr bstrValue; + CHECK_ERROR2_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw()); + } + cRegisters++; + break; + + default: + return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion); + } + } + + if (!cRegisters) + return errorSyntax(USAGE_DEBUGVM, "The getregisters sub-command takes at least one register name"); + return RTEXITCODE_SUCCESS; +} + +/** * Handles the info sub-command. * * @returns Suitable exit code. @@ -178,6 +243,86 @@ static RTEXITCODE handleDebugVM_OSInfo(HandlerArg *a, IMachineDebugger *pDebugge } /** + * Handles the setregisters sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_SetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * We take a list of register assignments, that is register=value. + */ + ULONG idCpu = 0; + com::SafeArray<IN_BSTR> aBstrNames; + com::SafeArray<IN_BSTR> aBstrValues; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, + }; + int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(rc, RTEXITCODE_FAILURE); + + while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (rc) + { + case 'c': + idCpu = ValueUnion.u32; + break; + + case VINF_GETOPT_NOT_OPTION: + { + const char *pszEqual = strchr(ValueUnion.psz, '='); + if (!pszEqual) + return errorSyntax(USAGE_DEBUGVM, "setregisters expects input on the form 'register=value' got '%s'", ValueUnion.psz); + try + { + com::Bstr bstrName(ValueUnion.psz, pszEqual - ValueUnion.psz); + com::Bstr bstrValue(pszEqual + 1); + if ( !aBstrNames.push_back(bstrName.raw()) + || !aBstrValues.push_back(bstrValue.raw())) + throw std::bad_alloc(); + } + catch (std::bad_alloc) + { + RTMsgError("Out of memory\n"); + return RTEXITCODE_FAILURE; + } + break; + } + + default: + return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion); + } + } + + if (!aBstrNames.size()) + return errorSyntax(USAGE_DEBUGVM, "The setregisters sub-command takes at least one register name"); + + /* + * If it is only one register, use the single register method just so + * we expose it and can test it from the command line. + */ + if (aBstrNames.size() == 1) + { + CHECK_ERROR2_RET(pDebugger, SetRegister(idCpu, aBstrNames[0], aBstrValues[0]), RTEXITCODE_FAILURE); + RTPrintf("Successfully set %ls\n", aBstrNames[0]); + } + else + { + CHECK_ERROR2_RET(pDebugger, SetRegisters(idCpu, ComSafeArrayAsInParam(aBstrNames), ComSafeArrayAsInParam(aBstrValues)), RTEXITCODE_FAILURE); + RTPrintf("Successfully set %u registers\n", aBstrNames.size()); + } + + return RTEXITCODE_SUCCESS; +} + +/** * Handles the statistics sub-command. * * @returns Suitable exit code. @@ -282,6 +427,8 @@ int handleDebugVM(HandlerArg *pArgs) const char *pszSubCmd = pArgs->argv[1]; if (!strcmp(pszSubCmd, "dumpguestcore")) rcExit = handleDebugVM_DumpVMCore(pArgs, ptrDebugger); + else if (!strcmp(pszSubCmd, "getregisters")) + rcExit = handleDebugVM_GetRegisters(pArgs, ptrDebugger); else if (!strcmp(pszSubCmd, "info")) rcExit = handleDebugVM_Info(pArgs, ptrDebugger); else if (!strcmp(pszSubCmd, "injectnmi")) @@ -290,6 +437,8 @@ int handleDebugVM(HandlerArg *pArgs) rcExit = handleDebugVM_OSDetect(pArgs, ptrDebugger); else if (!strcmp(pszSubCmd, "osinfo")) rcExit = handleDebugVM_OSInfo(pArgs, ptrDebugger); + else if (!strcmp(pszSubCmd, "setregisters")) + rcExit = handleDebugVM_SetRegisters(pArgs, ptrDebugger); else if (!strcmp(pszSubCmd, "statistics")) rcExit = handleDebugVM_Statistics(pArgs, ptrDebugger); else |
