VBoxManageDebugVM.cpp revision d36016c7e22c0a816c7eae1b6d53f46b7d180589
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * VBoxManage - Implementation of the debugvm command.
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * Copyright (C) 2010 Oracle Corporation
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * available from http://www.virtualbox.org. This file is free software;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * General Public License (GPL) as published by the Free Software
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync/*******************************************************************************
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync* Header Files *
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync*******************************************************************************/
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * Handles the getregisters sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pArgs The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * We take a list of register names (case insensitive). If 'all' is
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * encountered we'll dump all registers.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync unsigned cRegisters = 0;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync CHECK_ERROR2_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames), ComSafeArrayAsOutParam(aBstrValues)),
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTPrintf("%ls = %ls\n", aBstrNames[i], aBstrValues[i]);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync CHECK_ERROR2_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw());
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The getregisters sub-command takes at least one register name");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the info sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param a The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_Info(HandlerArg *a, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The inject sub-command takes at one or two arguments");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, Info(bstrName.raw(), bstrArgs.raw(), bstrInfo.asOutParam()), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the inject sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param a The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_InjectNMI(HandlerArg *a, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The inject sub-command does not take any arguments");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, InjectNMI(), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the inject sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pArgs The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_DumpVMCore(HandlerArg *pArgs, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Parse arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The --compression option has already been given");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The --filename option has already been given");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The --filename option is required");
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync * Make the filename absolute before handing it on to the API.
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAbs failed on '%s': %Rrc", pszFilename, rc);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, DumpGuestCore(bstrFilename.raw(), bstrCompression.raw()), RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * Handles the os sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param a The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_OSDetect(HandlerArg *a, IMachineDebugger *pDebugger)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The osdetect sub-command does not take any arguments");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, DetectOS(bstrName.asOutParam()), RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * Handles the os sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param a The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_OSInfo(HandlerArg *a, IMachineDebugger *pDebugger)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The osinfo sub-command does not take any arguments");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, COMGETTER(OSName)(bstrName.asOutParam()), RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, COMGETTER(OSVersion)(bstrVersion.asOutParam()), RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * Handles the setregisters sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pArgs The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_SetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * We take a list of register assignments, that is register=value.
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync const char *pszEqual = strchr(ValueUnion.psz, '=');
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync return errorSyntax(USAGE_DEBUGVM, "setregisters expects input on the form 'register=value' got '%s'", ValueUnion.psz);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::Bstr bstrName(ValueUnion.psz, pszEqual - ValueUnion.psz);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The setregisters sub-command takes at least one register name");
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * If it is only one register, use the single register method just so
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * we expose it and can test it from the command line.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, SetRegister(idCpu, aBstrNames[0], aBstrValues[0]), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, SetRegisters(idCpu, ComSafeArrayAsInParam(aBstrNames), ComSafeArrayAsInParam(aBstrValues)), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTPrintf("Successfully set %u registers\n", aBstrNames.size());
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the statistics sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pArgs The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_Statistics(HandlerArg *pArgs, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Parse arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync bool fReset = false;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "Multiple --pattern options are not permitted");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The --reset and --descriptions options does not mix");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Execute the order.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, ResetStats(bstrPattern.raw()), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, GetStats(bstrPattern.raw(), fWithDescriptions, bstrStats.asOutParam()),
return RTEXITCODE_SUCCESS;
CHECK_ERROR2_RET(pArgs->virtualBox, FindMachine(com::Bstr(pArgs->argv[0]).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE);
return rcExit;