VBoxManageDebugVM.cpp revision 1ce069685b24d243eb0464f46d4c56b250c64445
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/* $Id$ */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/** @file
844cd568b34737db015068632c9131c25f9b6578vboxsync * VBoxManage - Implementation of the debugvm command.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/*
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsync * Copyright (C) 2006-2010 Oracle Corporation
3bad884471a4755d52abffc98cc326f153750ca1vboxsync *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * available from http://www.virtualbox.org. This file is free software;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * General Public License (GPL) as published by the Free Software
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync/*******************************************************************************
3bad884471a4755d52abffc98cc326f153750ca1vboxsync* Header Files *
3bad884471a4755d52abffc98cc326f153750ca1vboxsync*******************************************************************************/
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/com.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/string.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/Guid.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/array.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/ErrorInfo.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/errorprint.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/EventQueue.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/com/VirtualBox.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/ctype.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <VBox/err.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/getopt.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/path.h>
3bad884471a4755d52abffc98cc326f153750ca1vboxsync#include <iprt/param.h>
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync#include <iprt/stream.h>
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync#include <iprt/string.h>
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync#include <iprt/uuid.h>
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync#include <VBox/log.h>
4030b8473736055cd02947418ef4f8f9b1945323vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync#include "VBoxManage.h"
4030b8473736055cd02947418ef4f8f9b1945323vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Handles the inject sub-command.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @returns Suitable exit code.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param a The handler arguments.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pDebugger Pointer to the debugger interface.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsyncstatic RTEXITCODE handleDebugVM_InjectNMI(HandlerArg *a, IMachineDebugger *pDebugger)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (a->argc != 2)
0177e4f8d16e61ee5c9858c5ea30ca90e2ed41a3vboxsync return errorSyntax(USAGE_DEBUGVM, "The inject sub-command does not take any arguments");
3bad884471a4755d52abffc98cc326f153750ca1vboxsync CHECK_ERROR2_RET(pDebugger, InjectNMI(), RTEXITCODE_FAILURE);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return RTEXITCODE_SUCCESS;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsync/**
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Handles the inject sub-command.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @returns Suitable exit code.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pArgs The handler arguments.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * @param pDebugger Pointer to the debugger interface.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsyncstatic RTEXITCODE handleDebugVM_DumpVMCore(HandlerArg *pArgs, IMachineDebugger *pDebugger)
4030b8473736055cd02947418ef4f8f9b1945323vboxsync{
4030b8473736055cd02947418ef4f8f9b1945323vboxsync /*
4030b8473736055cd02947418ef4f8f9b1945323vboxsync * Parse arguments.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync const char *pszFilename = NULL;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTGETOPTSTATE GetState;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTGETOPTUNION ValueUnion;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync static const RTGETOPTDEF s_aOptions[] =
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync { "--filename", 'f', RTGETOPT_REQ_STRING }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync };
3bad884471a4755d52abffc98cc326f153750ca1vboxsync int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/);
4030b8473736055cd02947418ef4f8f9b1945323vboxsync AssertRCReturn(rc, RTEXITCODE_FAILURE);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync {
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync switch (rc)
f596d8083ef5681ce0688150d1bc02b66feb0081vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync case 'f':
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (pszFilename)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return errorSyntax(USAGE_DEBUGVM, "The --filename option has already been given");
3bad884471a4755d52abffc98cc326f153750ca1vboxsync pszFilename = ValueUnion.psz;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync break;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync default:
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync }
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (!pszFilename)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return errorSyntax(USAGE_DEBUGVM, "The --filename option is required");
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Make the filename absolute before handing it on to the API.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync char szAbsFilename[RTPATH_MAX];
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (RT_FAILURE(rc))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAbs failed on '%s': %Rrc", pszFilename, rc);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync com::Bstr bstrFilename(szAbsFilename);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync CHECK_ERROR2_RET(pDebugger, DumpGuestCore(bstrFilename.raw()), RTEXITCODE_FAILURE);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return RTEXITCODE_SUCCESS;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsync
c8d782151b3a3e0be03e5dfc8b9b3ebbd8e65eb0vboxsyncint handleDebugVM(HandlerArg *pArgs)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync{
3bad884471a4755d52abffc98cc326f153750ca1vboxsync RTEXITCODE rcExit = RTEXITCODE_FAILURE;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * The first argument is the VM name or UUID. Open a session to it.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (pArgs->argc < 2)
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return errorSyntax(USAGE_DEBUGVM, "Too few parameters");
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ComPtr<IMachine> ptrMachine;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync CHECK_ERROR2_RET(pArgs->virtualBox, FindMachine(com::Bstr(pArgs->argv[0]).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync CHECK_ERROR2_RET(ptrMachine, LockMachine(pArgs->session, LockType_Shared), RTEXITCODE_FAILURE);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * Get the associated console and machine debugger.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync HRESULT rc;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ComPtr<IConsole> ptrConsole;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync CHECK_ERROR(pArgs->session, COMGETTER(Console)(ptrConsole.asOutParam()));
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (SUCCEEDED(rc))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync ComPtr<IMachineDebugger> ptrDebugger;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync CHECK_ERROR(ptrConsole, COMGETTER(Debugger)(ptrDebugger.asOutParam()));
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (SUCCEEDED(rc))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync {
3bad884471a4755d52abffc98cc326f153750ca1vboxsync /*
3bad884471a4755d52abffc98cc326f153750ca1vboxsync * String switch on the sub-command.
3bad884471a4755d52abffc98cc326f153750ca1vboxsync */
3bad884471a4755d52abffc98cc326f153750ca1vboxsync const char *pszSubCmd = pArgs->argv[1];
3bad884471a4755d52abffc98cc326f153750ca1vboxsync if (!strcmp(pszSubCmd, "injectnmi"))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rcExit = handleDebugVM_InjectNMI(pArgs, ptrDebugger);
3bad884471a4755d52abffc98cc326f153750ca1vboxsync else if (!strcmp(pszSubCmd, "dumpguestcore"))
3bad884471a4755d52abffc98cc326f153750ca1vboxsync rcExit = handleDebugVM_DumpVMCore(pArgs, ptrDebugger);
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync else
81631dabcaa76e2e48221548b08c71bd7ed6f2ecvboxsync errorSyntax(USAGE_DEBUGVM, "Invalid parameter '%s'", pArgs->argv[1]);
4030b8473736055cd02947418ef4f8f9b1945323vboxsync }
4030b8473736055cd02947418ef4f8f9b1945323vboxsync }
4030b8473736055cd02947418ef4f8f9b1945323vboxsync
4030b8473736055cd02947418ef4f8f9b1945323vboxsync pArgs->session->UnlockMachine();
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync return rcExit;
3bad884471a4755d52abffc98cc326f153750ca1vboxsync}
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync
3bad884471a4755d52abffc98cc326f153750ca1vboxsync