VirtualBox

source: vbox/trunk/src/VBox/Main/MachineDebuggerImpl.cpp@ 5190

Last change on this file since 5190 was 5190, checked in by vboxsync, 17 years ago

Added MachineDebugger::getStats.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "MachineDebuggerImpl.h"
19#include "ConsoleImpl.h"
20#include "Logging.h"
21
22#include <VBox/em.h>
23#include <VBox/patm.h>
24#include <VBox/csam.h>
25#include <VBox/vm.h>
26#include <VBox/tm.h>
27#include <VBox/err.h>
28#include <VBox/hwaccm.h>
29
30//
31// defines
32//
33
34
35//
36// globals
37//
38
39
40//
41// constructor / destructor
42//
43
44HRESULT MachineDebugger::FinalConstruct()
45{
46 mParent = NULL;
47 return S_OK;
48}
49
50void MachineDebugger::FinalRelease()
51{
52 if (isReady())
53 uninit();
54}
55
56//
57// public methods
58//
59
60/**
61 * Initializes the machine debugger object.
62 *
63 * @returns COM result indicator
64 * @param parent handle of our parent object
65 */
66HRESULT MachineDebugger::init(Console *parent)
67{
68 LogFlow(("MachineDebugger::init(): isReady=%d\n", isReady()));
69
70 ComAssertRet (parent, E_INVALIDARG);
71
72 AutoLock lock(this);
73 ComAssertRet (!isReady(), E_UNEXPECTED);
74
75 mParent = parent;
76 singlestepQueued = ~0;
77 recompileUserQueued = ~0;
78 recompileSupervisorQueued = ~0;
79 patmEnabledQueued = ~0;
80 csamEnabledQueued = ~0;
81 mLogEnabledQueued = ~0;
82 mVirtualTimeRateQueued = ~0;
83 fFlushMode = false;
84 setReady(true);
85 return S_OK;
86}
87
88/**
89 * Uninitializes the instance and sets the ready flag to FALSE.
90 * Called either from FinalRelease() or by the parent when it gets destroyed.
91 */
92void MachineDebugger::uninit()
93{
94 LogFlow(("MachineDebugger::uninit(): isReady=%d\n", isReady()));
95
96 AutoLock lock(this);
97 AssertReturn (isReady(), (void) 0);
98
99 setReady (false);
100}
101
102/**
103 * Returns the current singlestepping flag.
104 *
105 * @returns COM status code
106 * @param enabled address of result variable
107 */
108STDMETHODIMP MachineDebugger::COMGETTER(Singlestep)(BOOL *enabled)
109{
110 if (!enabled)
111 return E_POINTER;
112 AutoLock lock(this);
113 CHECK_READY();
114 /** @todo */
115 return E_NOTIMPL;
116}
117
118/**
119 * Sets the singlestepping flag.
120 *
121 * @returns COM status code
122 * @param enable new singlestepping flag
123 */
124STDMETHODIMP MachineDebugger::COMSETTER(Singlestep)(BOOL enable)
125{
126 AutoLock lock(this);
127 CHECK_READY();
128 /** @todo */
129 return E_NOTIMPL;
130}
131
132/**
133 * Resets VM statistics.
134 *
135 * @returns COM status code.
136 */
137STDMETHODIMP MachineDebugger::ResetStats()
138{
139 Console::SafeVMPtrQuiet pVM (mParent);
140 if (pVM.isOk())
141 STAMR3Reset(pVM, NULL);
142 return S_OK;
143}
144
145/**
146 * Dumps VM statistics to the log.
147 *
148 * @returns COM status code.
149 */
150STDMETHODIMP MachineDebugger::DumpStats()
151{
152 Console::SafeVMPtrQuiet pVM (mParent);
153 if (pVM.isOk())
154 STAMR3Dump(pVM, NULL);
155 return S_OK;
156}
157
158/**
159 * Get the VM statistics in an XML format.
160 *
161 * @returns COM status code.
162 * @param aPattern The selection pattern. A bit similar to filename globbing.
163 * @param aWithDescriptions Whether to include the descriptions.
164 * @param aStats The XML document containing the statistics.
165 */
166STDMETHODIMP MachineDebugger::GetStats(INPTR BSTR aPattern, BOOL aWithDescriptions, BSTR *aStats)
167{
168 Console::SafeVMPtrQuiet pVM (mParent);
169 if (!pVM.isOk())
170 return E_FAIL;
171
172 char *pszSnapshot;
173 int vrc = STAMR3Snapshot(pVM, Utf8Str(aPattern).raw(), &pszSnapshot, NULL, aWithDescriptions);
174 if (RT_FAILURE(vrc))
175 return vrc == VERR_NO_MEMORY ? E_OUTOFMEMORY : E_FAIL;
176
177 /** @todo this is horribly inefficient! And it's kinda difficult to tell whether it failed...
178 * Must use UTF-8 or ASCII here and completely avoid these two extra copy operations.
179 * Until that's done, this method is kind of useless for debugger statistics GUI because
180 * of the amount statistics in a debug build. */
181 Bstr(pszSnapshot).cloneTo(aStats);
182
183 return S_OK;
184}
185
186/**
187 * Returns the current recompile user mode code flag.
188 *
189 * @returns COM status code
190 * @param enabled address of result variable
191 */
192STDMETHODIMP MachineDebugger::COMGETTER(RecompileUser)(BOOL *enabled)
193{
194 if (!enabled)
195 return E_POINTER;
196 AutoLock lock(this);
197 CHECK_READY();
198 Console::SafeVMPtrQuiet pVM (mParent);
199 if (pVM.isOk())
200 *enabled = !EMIsRawRing3Enabled(pVM.raw());
201 else
202 *enabled = false;
203 return S_OK;
204}
205
206/**
207 * Sets the recompile user mode code flag.
208 *
209 * @returns COM status
210 * @param enable new user mode code recompile flag.
211 */
212STDMETHODIMP MachineDebugger::COMSETTER(RecompileUser)(BOOL enable)
213{
214 LogFlowThisFunc (("enable=%d\n", enable));
215
216 AutoLock lock(this);
217 CHECK_READY();
218
219 if (!fFlushMode)
220 {
221 // check if the machine is running
222 MachineState_T machineState;
223 mParent->COMGETTER(State)(&machineState);
224 if (machineState != MachineState_Running)
225 {
226 // queue the request
227 recompileUserQueued = enable;
228 return S_OK;
229 }
230 }
231
232 Console::SafeVMPtr pVM (mParent);
233 CheckComRCReturnRC (pVM.rc());
234
235 PVMREQ pReq;
236 EMRAWMODE rawModeFlag = enable ? EMRAW_RING3_DISABLE : EMRAW_RING3_ENABLE;
237 int rcVBox = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
238 (PFNRT)EMR3RawSetMode, 2, pVM.raw(), rawModeFlag);
239 if (VBOX_SUCCESS(rcVBox))
240 {
241 rcVBox = pReq->iStatus;
242 VMR3ReqFree(pReq);
243 }
244
245 if (VBOX_SUCCESS(rcVBox))
246 return S_OK;
247
248 AssertMsgFailed(("Could not set raw mode flags to %d, rcVBox = %Vrc\n",
249 rawModeFlag, rcVBox));
250 return E_FAIL;
251}
252
253/**
254 * Returns the current recompile supervisor code flag.
255 *
256 * @returns COM status code
257 * @param enabled address of result variable
258 */
259STDMETHODIMP MachineDebugger::COMGETTER(RecompileSupervisor)(BOOL *enabled)
260{
261 if (!enabled)
262 return E_POINTER;
263 AutoLock lock(this);
264 CHECK_READY();
265 Console::SafeVMPtrQuiet pVM (mParent);
266 if (pVM.isOk())
267 *enabled = !EMIsRawRing0Enabled(pVM.raw());
268 else
269 *enabled = false;
270 return S_OK;
271}
272
273/**
274 * Sets the new recompile supervisor code flag.
275 *
276 * @returns COM status code
277 * @param enable new recompile supervisor code flag
278 */
279STDMETHODIMP MachineDebugger::COMSETTER(RecompileSupervisor)(BOOL enable)
280{
281 LogFlowThisFunc (("enable=%d\n", enable));
282
283 AutoLock lock(this);
284 CHECK_READY();
285
286 if (!fFlushMode)
287 {
288 // check if the machine is running
289 MachineState_T machineState;
290 mParent->COMGETTER(State)(&machineState);
291 if (machineState != MachineState_Running)
292 {
293 // queue the request
294 recompileSupervisorQueued = enable;
295 return S_OK;
296 }
297 }
298
299 Console::SafeVMPtr pVM (mParent);
300 CheckComRCReturnRC (pVM.rc());
301
302 PVMREQ pReq;
303 EMRAWMODE rawModeFlag = enable ? EMRAW_RING0_DISABLE : EMRAW_RING0_ENABLE;
304 int rcVBox = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
305 (PFNRT)EMR3RawSetMode, 2, pVM.raw(), rawModeFlag);
306 if (VBOX_SUCCESS(rcVBox))
307 {
308 rcVBox = pReq->iStatus;
309 VMR3ReqFree(pReq);
310 }
311
312 if (VBOX_SUCCESS(rcVBox))
313 return S_OK;
314
315 AssertMsgFailed(("Could not set raw mode flags to %d, rcVBox = %Vrc\n",
316 rawModeFlag, rcVBox));
317 return E_FAIL;
318}
319
320/**
321 * Returns the current patch manager enabled flag.
322 *
323 * @returns COM status code
324 * @param enabled address of result variable
325 */
326STDMETHODIMP MachineDebugger::COMGETTER(PATMEnabled)(BOOL *enabled)
327{
328 if (!enabled)
329 return E_POINTER;
330 AutoLock lock(this);
331 CHECK_READY();
332 Console::SafeVMPtrQuiet pVM (mParent);
333 if (pVM.isOk())
334 *enabled = PATMIsEnabled(pVM.raw());
335 else
336 *enabled = false;
337 return S_OK;
338}
339
340/**
341 * Set the new patch manager enabled flag.
342 *
343 * @returns COM status code
344 * @param new patch manager enabled flag
345 */
346STDMETHODIMP MachineDebugger::COMSETTER(PATMEnabled)(BOOL enable)
347{
348 AutoLock lock(this);
349 CHECK_READY();
350 LogFlowThisFunc (("enable=%d\n", enable));
351
352 if (!fFlushMode)
353 {
354 // check if the machine is running
355 MachineState_T machineState;
356 mParent->COMGETTER(State)(&machineState);
357 if (machineState != MachineState_Running)
358 {
359 // queue the request
360 patmEnabledQueued = enable;
361 return S_OK;
362 }
363 }
364
365 Console::SafeVMPtr pVM (mParent);
366 CheckComRCReturnRC (pVM.rc());
367
368 PATMR3AllowPatching(pVM, enable);
369 return E_NOTIMPL;
370}
371
372/**
373 * Returns the current code scanner enabled flag.
374 *
375 * @returns COM status code
376 * @param enabled address of result variable
377 */
378STDMETHODIMP MachineDebugger::COMGETTER(CSAMEnabled)(BOOL *enabled)
379{
380 if (!enabled)
381 return E_POINTER;
382 AutoLock lock(this);
383 CHECK_READY();
384 Console::SafeVMPtrQuiet pVM (mParent);
385 if (pVM.isOk())
386 *enabled = CSAMIsEnabled(pVM.raw());
387 else
388 *enabled = false;
389 return S_OK;
390}
391
392/**
393 * Sets the new code scanner enabled flag.
394 *
395 * @returns COM status code
396 * @param enable new code scanner enabled flag
397 */
398STDMETHODIMP MachineDebugger::COMSETTER(CSAMEnabled)(BOOL enable)
399{
400 AutoLock lock(this);
401 CHECK_READY();
402 LogFlowThisFunc (("enable=%d\n", enable));
403
404 if (!fFlushMode)
405 {
406 // check if the machine is running
407 MachineState_T machineState;
408 mParent->COMGETTER(State)(&machineState);
409 if (machineState != MachineState_Running)
410 {
411 // queue the request
412 csamEnabledQueued = enable;
413 return S_OK;
414 }
415 }
416
417 Console::SafeVMPtr pVM (mParent);
418 CheckComRCReturnRC (pVM.rc());
419
420 int vrc;
421 if (enable)
422 vrc = CSAMEnableScanning(pVM);
423 else
424 vrc = CSAMDisableScanning(pVM);
425 if (VBOX_FAILURE(vrc))
426 {
427 /** @todo handle error case */
428 }
429 return S_OK;
430}
431
432/**
433 * Returns the log enabled / disabled status.
434 *
435 * @returns COM status code
436 * @param aEnabled address of result variable
437 */
438STDMETHODIMP MachineDebugger::COMGETTER(LogEnabled)(BOOL *aEnabled)
439{
440 if (!aEnabled)
441 return E_POINTER;
442 AutoLock alock(this);
443 CHECK_READY();
444 PRTLOGGER pLogInstance = RTLogDefaultInstance();
445 *aEnabled = pLogInstance && !(pLogInstance->fFlags & RTLOGFLAGS_DISABLED);
446 return S_OK;
447}
448
449/**
450 * Enables or disables logging.
451 *
452 * @returns COM status code
453 * @param aEnabled The new code log state.
454 */
455STDMETHODIMP MachineDebugger::COMSETTER(LogEnabled)(BOOL aEnabled)
456{
457 AutoLock alock(this);
458
459 CHECK_READY();
460 LogFlowThisFunc (("aEnabled=%d\n", aEnabled));
461
462 if (!fFlushMode)
463 {
464 // check if the machine is running
465 MachineState_T machineState;
466 mParent->COMGETTER(State)(&machineState);
467 if (machineState != MachineState_Running)
468 {
469 // queue the request
470 mLogEnabledQueued = aEnabled;
471 return S_OK;
472 }
473 }
474
475 Console::SafeVMPtr pVM (mParent);
476 CheckComRCReturnRC (pVM.rc());
477
478 int vrc = DBGFR3LogModifyFlags(pVM, aEnabled ? "enabled" : "disabled");
479 if (VBOX_FAILURE(vrc))
480 {
481 /** @todo handle error code. */
482 }
483 return S_OK;
484}
485
486/**
487 * Returns the current hardware virtualization flag.
488 *
489 * @returns COM status code
490 * @param enabled address of result variable
491 */
492STDMETHODIMP MachineDebugger::COMGETTER(HWVirtExEnabled)(BOOL *enabled)
493{
494 if (!enabled)
495 return E_POINTER;
496
497 AutoLock lock(this);
498 CHECK_READY();
499
500 Console::SafeVMPtrQuiet pVM (mParent);
501 if (pVM.isOk())
502 *enabled = HWACCMIsEnabled(pVM.raw());
503 else
504 *enabled = false;
505 return S_OK;
506}
507
508/**
509 * Returns the current virtual time rate.
510 *
511 * @returns COM status code.
512 * @param pct Where to store the rate.
513 */
514STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate)(ULONG *pct)
515{
516 if (!pct)
517 return E_POINTER;
518
519 AutoLock lock(this);
520 CHECK_READY();
521
522 Console::SafeVMPtrQuiet pVM (mParent);
523 if (pVM.isOk())
524 *pct = TMVirtualGetWarpDrive(pVM);
525 else
526 *pct = 100;
527 return S_OK;
528}
529
530/**
531 * Returns the current virtual time rate.
532 *
533 * @returns COM status code.
534 * @param pct Where to store the rate.
535 */
536STDMETHODIMP MachineDebugger::COMSETTER(VirtualTimeRate)(ULONG pct)
537{
538 if (pct < 2 || pct > 20000)
539 return E_INVALIDARG;
540
541 AutoLock lock(this);
542 CHECK_READY();
543
544 if (!fFlushMode)
545 {
546 // check if the machine is running
547 MachineState_T machineState;
548 mParent->COMGETTER(State)(&machineState);
549 if (machineState != MachineState_Running)
550 {
551 // queue the request
552 mVirtualTimeRateQueued = pct;
553 return S_OK;
554 }
555 }
556
557 Console::SafeVMPtr pVM (mParent);
558 CheckComRCReturnRC (pVM.rc());
559
560 int vrc = TMVirtualSetWarpDrive(pVM, pct);
561 if (VBOX_FAILURE(vrc))
562 {
563 /** @todo handle error code. */
564 }
565 return S_OK;
566}
567
568/**
569 * Hack for getting the VM handle.
570 * This is only temporary (promise) while prototyping the debugger.
571 *
572 * @returns COM status code
573 * @param vm Where to store the vm handle.
574 * Since there is no uintptr_t in COM, we're using the max integer.
575 * (No, ULONG is not pointer sized!)
576 */
577STDMETHODIMP MachineDebugger::COMGETTER(VM)(ULONG64 *vm)
578{
579 if (!vm)
580 return E_POINTER;
581
582 AutoLock lock(this);
583 CHECK_READY();
584
585 Console::SafeVMPtr pVM (mParent);
586 CheckComRCReturnRC (pVM.rc());
587
588 *vm = (uintptr_t)pVM.raw();
589
590 /*
591 * Note: pVM protection provided by SafeVMPtr is no more effective
592 * after we return from this method.
593 */
594
595 return S_OK;
596}
597
598//
599// "public-private" methods
600//
601void MachineDebugger::flushQueuedSettings()
602{
603 fFlushMode = true;
604 if (singlestepQueued != ~0)
605 {
606 COMSETTER(Singlestep)(singlestepQueued);
607 singlestepQueued = ~0;
608 }
609 if (recompileUserQueued != ~0)
610 {
611 COMSETTER(RecompileUser)(recompileUserQueued);
612 recompileUserQueued = ~0;
613 }
614 if (recompileSupervisorQueued != ~0)
615 {
616 COMSETTER(RecompileSupervisor)(recompileSupervisorQueued);
617 recompileSupervisorQueued = ~0;
618 }
619 if (patmEnabledQueued != ~0)
620 {
621 COMSETTER(PATMEnabled)(patmEnabledQueued);
622 patmEnabledQueued = ~0;
623 }
624 if (csamEnabledQueued != ~0)
625 {
626 COMSETTER(CSAMEnabled)(csamEnabledQueued);
627 csamEnabledQueued = ~0;
628 }
629 if (mLogEnabledQueued != ~0)
630 {
631 COMSETTER(LogEnabled)(mLogEnabledQueued);
632 mLogEnabledQueued = ~0;
633 }
634 if (mVirtualTimeRateQueued != ~(uint32_t)0)
635 {
636 COMSETTER(VirtualTimeRate)(mVirtualTimeRateQueued);
637 mVirtualTimeRateQueued = ~0;
638 }
639 fFlushMode = false;
640}
641
642//
643// private methods
644//
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette