VBoxManageDebugVM.cpp revision d36016c7e22c0a816c7eae1b6d53f46b7d180589
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync/* $Id$ */
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync/** @file
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * VBoxManage - Implementation of the debugvm command.
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync */
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync/*
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * Copyright (C) 2010 Oracle Corporation
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync *
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
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync/*******************************************************************************
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync* Header Files *
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync*******************************************************************************/
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/com/com.h>
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync#include <VBox/com/string.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/com/Guid.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/com/array.h>
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync#include <VBox/com/ErrorInfo.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/com/errorprint.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/com/EventQueue.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/com/VirtualBox.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <iprt/ctype.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/err.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <iprt/getopt.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <iprt/path.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <iprt/param.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <iprt/stream.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <iprt/string.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <iprt/uuid.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include <VBox/log.h>
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync#include "VBoxManage.h"
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync/**
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * Handles the getregisters sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync *
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pArgs The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync */
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync{
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync /*
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * We take a list of register names (case insensitive). If 'all' is
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * encountered we'll dump all registers.
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync */
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync ULONG idCpu = 0;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync unsigned cRegisters = 0;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTGETOPTSTATE GetState;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTGETOPTUNION ValueUnion;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync static const RTGETOPTDEF s_aOptions[] =
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync };
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync AssertRCReturn(rc, RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync {
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync switch (rc)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync case 'c':
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync idCpu = ValueUnion.u32;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync break;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync case VINF_GETOPT_NOT_OPTION:
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync if (!RTStrICmp(ValueUnion.psz, "all"))
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::SafeArray<BSTR> aBstrNames;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::SafeArray<BSTR> aBstrValues;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync CHECK_ERROR2_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames), ComSafeArrayAsOutParam(aBstrValues)),
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync Assert(aBstrNames.size() == aBstrValues.size());
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync for (size_t i = 0; i < aBstrNames.size(); i++)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTPrintf("%ls = %ls\n", aBstrNames[i], aBstrValues[i]);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync }
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync else
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::Bstr bstrName = ValueUnion.psz;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::Bstr bstrValue;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync CHECK_ERROR2_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw());
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync }
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync cRegisters++;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync break;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync default:
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync if (!cRegisters)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The getregisters sub-command takes at least one register name");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return RTEXITCODE_SUCCESS;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync}
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync/**
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the info sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync *
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param a The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_Info(HandlerArg *a, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync{
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync if (a->argc < 3 || a->argc > 4)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The inject sub-command takes at one or two arguments");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync com::Bstr bstrName(a->argv[2]);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync com::Bstr bstrArgs(a->argv[3]);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync com::Bstr bstrInfo;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, Info(bstrName.raw(), bstrArgs.raw(), bstrInfo.asOutParam()), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTPrintf("%ls", bstrInfo.raw());
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return RTEXITCODE_SUCCESS;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync}
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync/**
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the inject sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync *
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param a The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_InjectNMI(HandlerArg *a, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync{
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync if (a->argc != 2)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The inject sub-command does not take any arguments");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, InjectNMI(), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return RTEXITCODE_SUCCESS;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync}
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync/**
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the inject sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync *
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pArgs The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_DumpVMCore(HandlerArg *pArgs, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync{
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync /*
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Parse arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync const char *pszFilename = NULL;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync const char *pszCompression = NULL;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTGETOPTSTATE GetState;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTGETOPTUNION ValueUnion;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync static const RTGETOPTDEF s_aOptions[] =
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync {
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync { "--filename", 'f', RTGETOPT_REQ_STRING },
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync { "--compression", 'c', RTGETOPT_REQ_STRING }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync };
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync AssertRCReturn(rc, RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync {
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync switch (rc)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync {
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync case 'c':
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync if (pszCompression)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The --compression option has already been given");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync pszCompression = ValueUnion.psz;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync break;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync case 'f':
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync if (pszFilename)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The --filename option has already been given");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync pszFilename = ValueUnion.psz;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync break;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync default:
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync if (!pszFilename)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The --filename option is required");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync /*
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync * Make the filename absolute before handing it on to the API.
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync */
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync char szAbsFilename[RTPATH_MAX];
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync if (RT_FAILURE(rc))
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAbs failed on '%s': %Rrc", pszFilename, rc);
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync
4f8ea4ee25ce290a48389b0d1b09a5aefda26e5evboxsync com::Bstr bstrFilename(szAbsFilename);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync com::Bstr bstrCompression(pszCompression);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, DumpGuestCore(bstrFilename.raw(), bstrCompression.raw()), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return RTEXITCODE_SUCCESS;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync}
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync/**
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * Handles the os sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync *
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param a The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync */
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_OSDetect(HandlerArg *a, IMachineDebugger *pDebugger)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync{
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync if (a->argc != 2)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The osdetect sub-command does not take any arguments");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync com::Bstr bstrName;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, DetectOS(bstrName.asOutParam()), RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTPrintf("Detected: %ls\n", bstrName.raw());
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return RTEXITCODE_SUCCESS;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync}
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync/**
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * Handles the os sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync *
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param a The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync */
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_OSInfo(HandlerArg *a, IMachineDebugger *pDebugger)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync{
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync if (a->argc != 2)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The osinfo sub-command does not take any arguments");
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync com::Bstr bstrName;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, COMGETTER(OSName)(bstrName.asOutParam()), RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync com::Bstr bstrVersion;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync CHECK_ERROR2_RET(pDebugger, COMGETTER(OSVersion)(bstrVersion.asOutParam()), RTEXITCODE_FAILURE);
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTPrintf("Name: %ls\n", bstrName.raw());
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync RTPrintf("Version: %ls\n", bstrVersion.raw());
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return RTEXITCODE_SUCCESS;
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync}
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync/**
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * Handles the setregisters sub-command.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync *
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @returns Suitable exit code.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pArgs The handler arguments.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync * @param pDebugger Pointer to the debugger interface.
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync */
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsyncstatic RTEXITCODE handleDebugVM_SetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger)
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync{
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync /*
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync * We take a list of register assignments, that is register=value.
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync */
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync ULONG idCpu = 0;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::SafeArray<IN_BSTR> aBstrNames;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::SafeArray<IN_BSTR> aBstrValues;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync RTGETOPTSTATE GetState;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync RTGETOPTUNION ValueUnion;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync static const RTGETOPTDEF s_aOptions[] =
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync };
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync AssertRCReturn(rc, RTEXITCODE_FAILURE);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync switch (rc)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync case 'c':
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync idCpu = ValueUnion.u32;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync break;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync case VINF_GETOPT_NOT_OPTION:
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync const char *pszEqual = strchr(ValueUnion.psz, '=');
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync if (!pszEqual)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync return errorSyntax(USAGE_DEBUGVM, "setregisters expects input on the form 'register=value' got '%s'", ValueUnion.psz);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync try
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::Bstr bstrName(ValueUnion.psz, pszEqual - ValueUnion.psz);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync com::Bstr bstrValue(pszEqual + 1);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync if ( !aBstrNames.push_back(bstrName.raw())
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync || !aBstrValues.push_back(bstrValue.raw()))
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync throw std::bad_alloc();
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync }
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync catch (std::bad_alloc)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync RTMsgError("Out of memory\n");
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync return RTEXITCODE_FAILURE;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync }
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync break;
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync }
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync default:
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync }
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync }
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync if (!aBstrNames.size())
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync return errorSyntax(USAGE_DEBUGVM, "The setregisters sub-command takes at least one register name");
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync
acb0ddeac7f624f263afe1c42c8e35655aa59181vboxsync /*
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.
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync */
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync if (aBstrNames.size() == 1)
4d8891c509dc8abc8a8040f347e33afa9c390f8dvboxsync {
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, SetRegister(idCpu, aBstrNames[0], aBstrValues[0]), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTPrintf("Successfully set %ls\n", aBstrNames[0]);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync else
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync {
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, SetRegisters(idCpu, ComSafeArrayAsInParam(aBstrNames), ComSafeArrayAsInParam(aBstrValues)), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTPrintf("Successfully set %u registers\n", aBstrNames.size());
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return RTEXITCODE_SUCCESS;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync}
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync/**
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Handles the statistics sub-command.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync *
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @returns Suitable exit code.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pArgs The handler arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * @param pDebugger Pointer to the debugger interface.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsyncstatic RTEXITCODE handleDebugVM_Statistics(HandlerArg *pArgs, IMachineDebugger *pDebugger)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync{
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync /*
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Parse arguments.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync bool fWithDescriptions = false;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync const char *pszPattern = NULL; /* all */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync bool fReset = false;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTGETOPTSTATE GetState;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync RTGETOPTUNION ValueUnion;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync static const RTGETOPTDEF s_aOptions[] =
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync {
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync { "--descriptions", 'd', RTGETOPT_REQ_NOTHING },
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync { "--pattern", 'p', RTGETOPT_REQ_STRING },
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync { "--reset", 'r', RTGETOPT_REQ_NOTHING },
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync };
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync AssertRCReturn(rc, RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync {
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync switch (rc)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync {
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync case 'd':
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync fWithDescriptions = true;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync break;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync case 'p':
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync if (pszPattern)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "Multiple --pattern options are not permitted");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync pszPattern = ValueUnion.psz;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync break;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync case 'r':
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync fReset = true;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync break;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync default:
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync }
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync if (fReset && fWithDescriptions)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync return errorSyntax(USAGE_DEBUGVM, "The --reset and --descriptions options does not mix");
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync /*
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync * Execute the order.
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync */
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync com::Bstr bstrPattern(pszPattern);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync if (fReset)
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, ResetStats(bstrPattern.raw()), RTEXITCODE_FAILURE);
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync else
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync {
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync com::Bstr bstrStats;
e3ddc294f1a80edb513f054d4c24ab79d7dfd3ddvboxsync CHECK_ERROR2_RET(pDebugger, GetStats(bstrPattern.raw(), fWithDescriptions, bstrStats.asOutParam()),
RTEXITCODE_FAILURE);
/* if (fFormatted)
{ big mess }
else
*/
RTPrintf("%ls\n", bstrStats.raw());
}
return RTEXITCODE_SUCCESS;
}
int handleDebugVM(HandlerArg *pArgs)
{
RTEXITCODE rcExit = RTEXITCODE_FAILURE;
/*
* The first argument is the VM name or UUID. Open a session to it.
*/
if (pArgs->argc < 2)
return errorSyntax(USAGE_DEBUGVM, "Too few parameters");
ComPtr<IMachine> ptrMachine;
CHECK_ERROR2_RET(pArgs->virtualBox, FindMachine(com::Bstr(pArgs->argv[0]).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE);
CHECK_ERROR2_RET(ptrMachine, LockMachine(pArgs->session, LockType_Shared), RTEXITCODE_FAILURE);
/*
* Get the associated console and machine debugger.
*/
HRESULT rc;
ComPtr<IConsole> ptrConsole;
CHECK_ERROR(pArgs->session, COMGETTER(Console)(ptrConsole.asOutParam()));
if (SUCCEEDED(rc))
{
ComPtr<IMachineDebugger> ptrDebugger;
CHECK_ERROR(ptrConsole, COMGETTER(Debugger)(ptrDebugger.asOutParam()));
if (SUCCEEDED(rc))
{
/*
* String switch on the sub-command.
*/
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"))
rcExit = handleDebugVM_InjectNMI(pArgs, ptrDebugger);
else if (!strcmp(pszSubCmd, "osdetect"))
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
errorSyntax(USAGE_DEBUGVM, "Invalid parameter '%s'", pArgs->argv[1]);
}
}
pArgs->session->UnlockMachine();
return rcExit;
}