VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp@ 35306

Last change on this file since 35306 was 35306, checked in by vboxsync, 13 years ago

IMachineDebugger: Implemented Info, DetectOS, OSVersion and OSName. Exposed these via VBoxManage.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.1 KB
Line 
1/* $Id: VBoxManageDebugVM.cpp 35306 2010-12-22 17:30:04Z vboxsync $ */
2/** @file
3 * VBoxManage - Implementation of the debugvm command.
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <VBox/com/com.h>
23#include <VBox/com/string.h>
24#include <VBox/com/Guid.h>
25#include <VBox/com/array.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/errorprint.h>
28#include <VBox/com/EventQueue.h>
29
30#include <VBox/com/VirtualBox.h>
31
32#include <iprt/ctype.h>
33#include <VBox/err.h>
34#include <iprt/getopt.h>
35#include <iprt/path.h>
36#include <iprt/param.h>
37#include <iprt/stream.h>
38#include <iprt/string.h>
39#include <iprt/uuid.h>
40#include <VBox/log.h>
41
42#include "VBoxManage.h"
43
44
45/**
46 * Handles the info sub-command.
47 *
48 * @returns Suitable exit code.
49 * @param a The handler arguments.
50 * @param pDebugger Pointer to the debugger interface.
51 */
52static RTEXITCODE handleDebugVM_Info(HandlerArg *a, IMachineDebugger *pDebugger)
53{
54 if (a->argc < 3 || a->argc > 4)
55 return errorSyntax(USAGE_DEBUGVM, "The inject sub-command takes at one or two arguments");
56
57 com::Bstr bstrName(a->argv[2]);
58 com::Bstr bstrArgs(a->argv[3]);
59 com::Bstr bstrInfo;
60 CHECK_ERROR2_RET(pDebugger, Info(bstrName.raw(), bstrArgs.raw(), bstrInfo.asOutParam()), RTEXITCODE_FAILURE);
61 RTPrintf("%ls", bstrInfo.raw());
62 return RTEXITCODE_SUCCESS;
63}
64
65/**
66 * Handles the inject sub-command.
67 *
68 * @returns Suitable exit code.
69 * @param a The handler arguments.
70 * @param pDebugger Pointer to the debugger interface.
71 */
72static RTEXITCODE handleDebugVM_InjectNMI(HandlerArg *a, IMachineDebugger *pDebugger)
73{
74 if (a->argc != 2)
75 return errorSyntax(USAGE_DEBUGVM, "The inject sub-command does not take any arguments");
76 CHECK_ERROR2_RET(pDebugger, InjectNMI(), RTEXITCODE_FAILURE);
77 return RTEXITCODE_SUCCESS;
78}
79
80/**
81 * Handles the inject sub-command.
82 *
83 * @returns Suitable exit code.
84 * @param pArgs The handler arguments.
85 * @param pDebugger Pointer to the debugger interface.
86 */
87static RTEXITCODE handleDebugVM_DumpVMCore(HandlerArg *pArgs, IMachineDebugger *pDebugger)
88{
89 /*
90 * Parse arguments.
91 */
92 const char *pszFilename = NULL;
93 const char *pszCompression = NULL;
94
95 RTGETOPTSTATE GetState;
96 RTGETOPTUNION ValueUnion;
97 static const RTGETOPTDEF s_aOptions[] =
98 {
99 { "--filename", 'f', RTGETOPT_REQ_STRING },
100 { "--compression", 'c', RTGETOPT_REQ_STRING }
101 };
102 int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/);
103 AssertRCReturn(rc, RTEXITCODE_FAILURE);
104
105 while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
106 {
107 switch (rc)
108 {
109 case 'c':
110 if (pszCompression)
111 return errorSyntax(USAGE_DEBUGVM, "The --compression option has already been given");
112 pszCompression = ValueUnion.psz;
113 break;
114 case 'f':
115 if (pszFilename)
116 return errorSyntax(USAGE_DEBUGVM, "The --filename option has already been given");
117 pszFilename = ValueUnion.psz;
118 break;
119 default:
120 return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
121 }
122 }
123
124 if (!pszFilename)
125 return errorSyntax(USAGE_DEBUGVM, "The --filename option is required");
126
127 /*
128 * Make the filename absolute before handing it on to the API.
129 */
130 char szAbsFilename[RTPATH_MAX];
131 rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
132 if (RT_FAILURE(rc))
133 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAbs failed on '%s': %Rrc", pszFilename, rc);
134
135 com::Bstr bstrFilename(szAbsFilename);
136 com::Bstr bstrCompression(pszCompression);
137 CHECK_ERROR2_RET(pDebugger, DumpGuestCore(bstrFilename.raw(), bstrCompression.raw()), RTEXITCODE_FAILURE);
138 return RTEXITCODE_SUCCESS;
139}
140
141/**
142 * Handles the os sub-command.
143 *
144 * @returns Suitable exit code.
145 * @param a The handler arguments.
146 * @param pDebugger Pointer to the debugger interface.
147 */
148static RTEXITCODE handleDebugVM_OSDetect(HandlerArg *a, IMachineDebugger *pDebugger)
149{
150 if (a->argc != 2)
151 return errorSyntax(USAGE_DEBUGVM, "The osdetect sub-command does not take any arguments");
152
153 com::Bstr bstrName;
154 CHECK_ERROR2_RET(pDebugger, DetectOS(bstrName.asOutParam()), RTEXITCODE_FAILURE);
155 RTPrintf("Detected: %ls\n", bstrName.raw());
156 return RTEXITCODE_SUCCESS;
157}
158
159/**
160 * Handles the os sub-command.
161 *
162 * @returns Suitable exit code.
163 * @param a The handler arguments.
164 * @param pDebugger Pointer to the debugger interface.
165 */
166static RTEXITCODE handleDebugVM_OSInfo(HandlerArg *a, IMachineDebugger *pDebugger)
167{
168 if (a->argc != 2)
169 return errorSyntax(USAGE_DEBUGVM, "The osinfo sub-command does not take any arguments");
170
171 com::Bstr bstrName;
172 CHECK_ERROR2_RET(pDebugger, COMGETTER(OSName)(bstrName.asOutParam()), RTEXITCODE_FAILURE);
173 com::Bstr bstrVersion;
174 CHECK_ERROR2_RET(pDebugger, COMGETTER(OSVersion)(bstrVersion.asOutParam()), RTEXITCODE_FAILURE);
175 RTPrintf("Name: %ls\n", bstrName.raw());
176 RTPrintf("Version: %ls\n", bstrVersion.raw());
177 return RTEXITCODE_SUCCESS;
178}
179
180/**
181 * Handles the statistics sub-command.
182 *
183 * @returns Suitable exit code.
184 * @param pArgs The handler arguments.
185 * @param pDebugger Pointer to the debugger interface.
186 */
187static RTEXITCODE handleDebugVM_Statistics(HandlerArg *pArgs, IMachineDebugger *pDebugger)
188{
189 /*
190 * Parse arguments.
191 */
192 bool fWithDescriptions = false;
193 const char *pszPattern = NULL; /* all */
194 bool fReset = false;
195
196 RTGETOPTSTATE GetState;
197 RTGETOPTUNION ValueUnion;
198 static const RTGETOPTDEF s_aOptions[] =
199 {
200 { "--descriptions", 'd', RTGETOPT_REQ_NOTHING },
201 { "--pattern", 'p', RTGETOPT_REQ_STRING },
202 { "--reset", 'r', RTGETOPT_REQ_NOTHING },
203 };
204 int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/);
205 AssertRCReturn(rc, RTEXITCODE_FAILURE);
206
207 while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
208 {
209 switch (rc)
210 {
211 case 'd':
212 fWithDescriptions = true;
213 break;
214
215 case 'p':
216 if (pszPattern)
217 return errorSyntax(USAGE_DEBUGVM, "Multiple --pattern options are not permitted");
218 pszPattern = ValueUnion.psz;
219 break;
220
221 case 'r':
222 fReset = true;
223 break;
224
225 default:
226 return errorGetOpt(USAGE_DEBUGVM, rc, &ValueUnion);
227 }
228 }
229
230 if (fReset && fWithDescriptions)
231 return errorSyntax(USAGE_DEBUGVM, "The --reset and --descriptions options does not mix");
232
233 /*
234 * Execute the order.
235 */
236 com::Bstr bstrPattern(pszPattern);
237 if (fReset)
238 CHECK_ERROR2_RET(pDebugger, ResetStats(bstrPattern.raw()), RTEXITCODE_FAILURE);
239 else
240 {
241 com::Bstr bstrStats;
242 CHECK_ERROR2_RET(pDebugger, GetStats(bstrPattern.raw(), fWithDescriptions, bstrStats.asOutParam()),
243 RTEXITCODE_FAILURE);
244 /* if (fFormatted)
245 { big mess }
246 else
247 */
248 RTPrintf("%ls\n", bstrStats.raw());
249 }
250
251 return RTEXITCODE_SUCCESS;
252}
253
254int handleDebugVM(HandlerArg *pArgs)
255{
256 RTEXITCODE rcExit = RTEXITCODE_FAILURE;
257
258 /*
259 * The first argument is the VM name or UUID. Open a session to it.
260 */
261 if (pArgs->argc < 2)
262 return errorSyntax(USAGE_DEBUGVM, "Too few parameters");
263 ComPtr<IMachine> ptrMachine;
264 CHECK_ERROR2_RET(pArgs->virtualBox, FindMachine(com::Bstr(pArgs->argv[0]).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE);
265 CHECK_ERROR2_RET(ptrMachine, LockMachine(pArgs->session, LockType_Shared), RTEXITCODE_FAILURE);
266
267 /*
268 * Get the associated console and machine debugger.
269 */
270 HRESULT rc;
271 ComPtr<IConsole> ptrConsole;
272 CHECK_ERROR(pArgs->session, COMGETTER(Console)(ptrConsole.asOutParam()));
273 if (SUCCEEDED(rc))
274 {
275 ComPtr<IMachineDebugger> ptrDebugger;
276 CHECK_ERROR(ptrConsole, COMGETTER(Debugger)(ptrDebugger.asOutParam()));
277 if (SUCCEEDED(rc))
278 {
279 /*
280 * String switch on the sub-command.
281 */
282 const char *pszSubCmd = pArgs->argv[1];
283 if (!strcmp(pszSubCmd, "dumpguestcore"))
284 rcExit = handleDebugVM_DumpVMCore(pArgs, ptrDebugger);
285 else if (!strcmp(pszSubCmd, "info"))
286 rcExit = handleDebugVM_Info(pArgs, ptrDebugger);
287 else if (!strcmp(pszSubCmd, "injectnmi"))
288 rcExit = handleDebugVM_InjectNMI(pArgs, ptrDebugger);
289 else if (!strcmp(pszSubCmd, "osdetect"))
290 rcExit = handleDebugVM_OSDetect(pArgs, ptrDebugger);
291 else if (!strcmp(pszSubCmd, "osinfo"))
292 rcExit = handleDebugVM_OSInfo(pArgs, ptrDebugger);
293 else if (!strcmp(pszSubCmd, "statistics"))
294 rcExit = handleDebugVM_Statistics(pArgs, ptrDebugger);
295 else
296 errorSyntax(USAGE_DEBUGVM, "Invalid parameter '%s'", pArgs->argv[1]);
297 }
298 }
299
300 pArgs->session->UnlockMachine();
301
302 return rcExit;
303}
304
305
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use