VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/MachineDebuggerImpl.cpp@ 39676

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

LogDbgDestinations: bugfix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.3 KB
Line 
1/* $Id: MachineDebuggerImpl.cpp 39676 2011-12-21 23:50:10Z vboxsync $ */
2/** @file
3 * VBox IMachineDebugger COM class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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#include "MachineDebuggerImpl.h"
19
20#include "Global.h"
21#include "ConsoleImpl.h"
22
23#include "AutoCaller.h"
24#include "Logging.h"
25
26#include <VBox/vmm/em.h>
27#include <VBox/vmm/patm.h>
28#include <VBox/vmm/csam.h>
29#include <VBox/vmm/vm.h>
30#include <VBox/vmm/tm.h>
31#include <VBox/vmm/hwaccm.h>
32#include <VBox/err.h>
33#include <iprt/cpp/utils.h>
34
35// defines
36/////////////////////////////////////////////////////////////////////////////
37
38
39// globals
40/////////////////////////////////////////////////////////////////////////////
41
42
43// constructor / destructor
44/////////////////////////////////////////////////////////////////////////////
45
46MachineDebugger::MachineDebugger()
47 : mParent(NULL)
48{
49}
50
51MachineDebugger::~MachineDebugger()
52{
53}
54
55HRESULT MachineDebugger::FinalConstruct()
56{
57 unconst(mParent) = NULL;
58 return BaseFinalConstruct();
59}
60
61void MachineDebugger::FinalRelease()
62{
63 uninit();
64 BaseFinalRelease();
65}
66
67// public initializer/uninitializer for internal purposes only
68/////////////////////////////////////////////////////////////////////////////
69
70/**
71 * Initializes the machine debugger object.
72 *
73 * @returns COM result indicator
74 * @param aParent handle of our parent object
75 */
76HRESULT MachineDebugger::init (Console *aParent)
77{
78 LogFlowThisFunc(("aParent=%p\n", aParent));
79
80 ComAssertRet(aParent, E_INVALIDARG);
81
82 /* Enclose the state transition NotReady->InInit->Ready */
83 AutoInitSpan autoInitSpan(this);
84 AssertReturn(autoInitSpan.isOk(), E_FAIL);
85
86 unconst(mParent) = aParent;
87
88 mSinglestepQueued = ~0;
89 mRecompileUserQueued = ~0;
90 mRecompileSupervisorQueued = ~0;
91 mPatmEnabledQueued = ~0;
92 mCsamEnabledQueued = ~0;
93 mLogEnabledQueued = ~0;
94 mVirtualTimeRateQueued = ~0;
95 mFlushMode = false;
96
97 /* Confirm a successful initialization */
98 autoInitSpan.setSucceeded();
99
100 return S_OK;
101}
102
103/**
104 * Uninitializes the instance and sets the ready flag to FALSE.
105 * Called either from FinalRelease() or by the parent when it gets destroyed.
106 */
107void MachineDebugger::uninit()
108{
109 LogFlowThisFunc(("\n"));
110
111 /* Enclose the state transition Ready->InUninit->NotReady */
112 AutoUninitSpan autoUninitSpan(this);
113 if (autoUninitSpan.uninitDone())
114 return;
115
116 unconst(mParent) = NULL;
117 mFlushMode = false;
118}
119
120// IMachineDebugger properties
121/////////////////////////////////////////////////////////////////////////////
122
123/**
124 * Returns the current singlestepping flag.
125 *
126 * @returns COM status code
127 * @param aEnabled address of result variable
128 */
129STDMETHODIMP MachineDebugger::COMGETTER(Singlestep) (BOOL *aEnabled)
130{
131 CheckComArgOutPointerValid(aEnabled);
132
133 AutoCaller autoCaller(this);
134 if (FAILED(autoCaller.rc())) return autoCaller.rc();
135
136 /** @todo */
137 ReturnComNotImplemented();
138}
139
140/**
141 * Sets the singlestepping flag.
142 *
143 * @returns COM status code
144 * @param aEnable new singlestepping flag
145 */
146STDMETHODIMP MachineDebugger::COMSETTER(Singlestep) (BOOL aEnable)
147{
148 AutoCaller autoCaller(this);
149 if (FAILED(autoCaller.rc())) return autoCaller.rc();
150
151 /** @todo */
152 ReturnComNotImplemented();
153}
154
155/**
156 * Returns the current recompile user mode code flag.
157 *
158 * @returns COM status code
159 * @param aEnabled address of result variable
160 */
161STDMETHODIMP MachineDebugger::COMGETTER(RecompileUser) (BOOL *aEnabled)
162{
163 CheckComArgOutPointerValid(aEnabled);
164
165 AutoCaller autoCaller(this);
166 if (FAILED(autoCaller.rc())) return autoCaller.rc();
167
168 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
169
170 Console::SafeVMPtrQuiet pVM (mParent);
171
172 if (pVM.isOk())
173 *aEnabled = !EMIsRawRing3Enabled (pVM.raw());
174 else
175 *aEnabled = false;
176
177 return S_OK;
178}
179
180/**
181 * Sets the recompile user mode code flag.
182 *
183 * @returns COM status
184 * @param aEnable new user mode code recompile flag.
185 */
186STDMETHODIMP MachineDebugger::COMSETTER(RecompileUser)(BOOL aEnable)
187{
188 LogFlowThisFunc(("enable=%d\n", aEnable));
189
190 AutoCaller autoCaller(this);
191 HRESULT hrc = autoCaller.rc();
192 if (SUCCEEDED(hrc))
193 {
194 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
195 if (queueSettings())
196 mRecompileUserQueued = aEnable; // queue the request
197 else
198 {
199 Console::SafeVMPtr ptrVM(mParent);
200 hrc = ptrVM.rc();
201 if (SUCCEEDED(hrc))
202 {
203 int vrc = EMR3SetExecutionPolicy(ptrVM.raw(), EMEXECPOLICY_RECOMPILE_RING3, RT_BOOL(aEnable));
204 if (RT_FAILURE(vrc))
205 hrc = setError(VBOX_E_VM_ERROR, tr("EMR3SetExecutionPolicy failed with %Rrc"), vrc);
206 }
207 }
208 }
209 return hrc;
210}
211
212/**
213 * Returns the current recompile supervisor code flag.
214 *
215 * @returns COM status code
216 * @param aEnabled address of result variable
217 */
218STDMETHODIMP MachineDebugger::COMGETTER(RecompileSupervisor) (BOOL *aEnabled)
219{
220 CheckComArgOutPointerValid(aEnabled);
221
222 AutoCaller autoCaller(this);
223 if (FAILED(autoCaller.rc())) return autoCaller.rc();
224
225 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
226
227 Console::SafeVMPtrQuiet pVM (mParent);
228
229 if (pVM.isOk())
230 *aEnabled = !EMIsRawRing0Enabled (pVM.raw());
231 else
232 *aEnabled = false;
233
234 return S_OK;
235}
236
237/**
238 * Sets the new recompile supervisor code flag.
239 *
240 * @returns COM status code
241 * @param aEnable new recompile supervisor code flag
242 */
243STDMETHODIMP MachineDebugger::COMSETTER(RecompileSupervisor)(BOOL aEnable)
244{
245 LogFlowThisFunc(("enable=%d\n", aEnable));
246
247 AutoCaller autoCaller(this);
248 HRESULT hrc = autoCaller.rc();
249 if (SUCCEEDED(hrc))
250 {
251 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
252 if (queueSettings())
253 mRecompileSupervisorQueued = aEnable; // queue the request
254 else
255 {
256 Console::SafeVMPtr ptrVM(mParent);
257 hrc = ptrVM.rc();
258 if (SUCCEEDED(hrc))
259 {
260 int vrc = EMR3SetExecutionPolicy(ptrVM.raw(), EMEXECPOLICY_RECOMPILE_RING0, RT_BOOL(aEnable));
261 if (RT_FAILURE(vrc))
262 hrc = setError(VBOX_E_VM_ERROR, tr("EMR3SetExecutionPolicy failed with %Rrc"), vrc);
263 }
264 }
265 }
266 return hrc;
267}
268
269/**
270 * Returns the current patch manager enabled flag.
271 *
272 * @returns COM status code
273 * @param aEnabled address of result variable
274 */
275STDMETHODIMP MachineDebugger::COMGETTER(PATMEnabled) (BOOL *aEnabled)
276{
277 CheckComArgOutPointerValid(aEnabled);
278
279 AutoCaller autoCaller(this);
280 if (FAILED(autoCaller.rc())) return autoCaller.rc();
281
282 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
283
284 Console::SafeVMPtrQuiet pVM (mParent);
285
286 if (pVM.isOk())
287 *aEnabled = PATMIsEnabled (pVM.raw());
288 else
289 *aEnabled = false;
290
291 return S_OK;
292}
293
294/**
295 * Set the new patch manager enabled flag.
296 *
297 * @returns COM status code
298 * @param aEnable new patch manager enabled flag
299 */
300STDMETHODIMP MachineDebugger::COMSETTER(PATMEnabled) (BOOL aEnable)
301{
302 LogFlowThisFunc(("enable=%d\n", aEnable));
303
304 AutoCaller autoCaller(this);
305 if (FAILED(autoCaller.rc())) return autoCaller.rc();
306
307 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
308
309 if (queueSettings())
310 {
311 // queue the request
312 mPatmEnabledQueued = aEnable;
313 return S_OK;
314 }
315
316 Console::SafeVMPtr pVM(mParent);
317 if (FAILED(pVM.rc())) return pVM.rc();
318
319 PATMR3AllowPatching (pVM, aEnable);
320
321 return S_OK;
322}
323
324/**
325 * Returns the current code scanner enabled flag.
326 *
327 * @returns COM status code
328 * @param aEnabled address of result variable
329 */
330STDMETHODIMP MachineDebugger::COMGETTER(CSAMEnabled) (BOOL *aEnabled)
331{
332 CheckComArgOutPointerValid(aEnabled);
333
334 AutoCaller autoCaller(this);
335 if (FAILED(autoCaller.rc())) return autoCaller.rc();
336
337 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
338
339 Console::SafeVMPtrQuiet pVM (mParent);
340
341 if (pVM.isOk())
342 *aEnabled = CSAMIsEnabled (pVM.raw());
343 else
344 *aEnabled = false;
345
346 return S_OK;
347}
348
349/**
350 * Sets the new code scanner enabled flag.
351 *
352 * @returns COM status code
353 * @param aEnable new code scanner enabled flag
354 */
355STDMETHODIMP MachineDebugger::COMSETTER(CSAMEnabled) (BOOL aEnable)
356{
357 LogFlowThisFunc(("enable=%d\n", aEnable));
358
359 AutoCaller autoCaller(this);
360 if (FAILED(autoCaller.rc())) return autoCaller.rc();
361
362 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
363
364 if (queueSettings())
365 {
366 // queue the request
367 mCsamEnabledQueued = aEnable;
368 return S_OK;
369 }
370
371 Console::SafeVMPtr pVM(mParent);
372 if (FAILED(pVM.rc())) return pVM.rc();
373
374 int vrc;
375 if (aEnable)
376 vrc = CSAMEnableScanning (pVM);
377 else
378 vrc = CSAMDisableScanning (pVM);
379
380 if (RT_FAILURE(vrc))
381 {
382 /** @todo handle error case */
383 }
384
385 return S_OK;
386}
387
388/**
389 * Returns the log enabled / disabled status.
390 *
391 * @returns COM status code
392 * @param aEnabled address of result variable
393 */
394STDMETHODIMP MachineDebugger::COMGETTER(LogEnabled) (BOOL *aEnabled)
395{
396 CheckComArgOutPointerValid(aEnabled);
397
398 AutoCaller autoCaller(this);
399 if (FAILED(autoCaller.rc())) return autoCaller.rc();
400
401#ifdef LOG_ENABLED
402 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
403
404 const PRTLOGGER pLogInstance = RTLogDefaultInstance();
405 *aEnabled = pLogInstance && !(pLogInstance->fFlags & RTLOGFLAGS_DISABLED);
406#else
407 *aEnabled = false;
408#endif
409
410 return S_OK;
411}
412
413/**
414 * Enables or disables logging.
415 *
416 * @returns COM status code
417 * @param aEnabled The new code log state.
418 */
419STDMETHODIMP MachineDebugger::COMSETTER(LogEnabled) (BOOL aEnabled)
420{
421 LogFlowThisFunc(("aEnabled=%d\n", aEnabled));
422
423 AutoCaller autoCaller(this);
424 if (FAILED(autoCaller.rc())) return autoCaller.rc();
425
426 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
427
428 if (queueSettings())
429 {
430 // queue the request
431 mLogEnabledQueued = aEnabled;
432 return S_OK;
433 }
434
435 Console::SafeVMPtr pVM(mParent);
436 if (FAILED(pVM.rc())) return pVM.rc();
437
438#ifdef LOG_ENABLED
439 int vrc = DBGFR3LogModifyFlags (pVM, aEnabled ? "enabled" : "disabled");
440 if (RT_FAILURE(vrc))
441 {
442 /** @todo handle error code. */
443 }
444#endif
445
446 return S_OK;
447}
448
449HRESULT MachineDebugger::logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr,
450 const char *pszLogGetStr, BSTR *a_pbstrSettings)
451{
452 /* Make sure the VM is powered up. */
453 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
454 Console::SafeVMPtr ptrVM(mParent);
455 HRESULT hrc = ptrVM.rc();
456 if (FAILED(hrc))
457 return hrc;
458
459 /* Make sure we've got a logger. */
460 if (!pLogger)
461 {
462 Bstr bstrEmpty;
463 bstrEmpty.cloneTo(a_pbstrSettings);
464 return S_OK;
465 }
466
467 /* Do the job. */
468 size_t cbBuf = _1K;
469 for (;;)
470 {
471 char *pszBuf = (char *)RTMemTmpAlloc(cbBuf);
472 AssertReturn(pszBuf, E_OUTOFMEMORY);
473
474 int rc = pfnLogGetStr(pLogger, pszBuf, cbBuf);
475 if (RT_SUCCESS(rc))
476 {
477 try
478 {
479 Bstr bstrRet(pszBuf);
480 bstrRet.detachTo(a_pbstrSettings);
481 hrc = S_OK;
482 }
483 catch (std::bad_alloc)
484 {
485 hrc = E_OUTOFMEMORY;
486 }
487 RTMemTmpFree(pszBuf);
488 return hrc;
489 }
490 RTMemTmpFree(pszBuf);
491 AssertReturn(rc == VERR_BUFFER_OVERFLOW, setError(VBOX_E_IPRT_ERROR, tr("%s returned %Rrc"), pszLogGetStr, rc));
492
493 /* try again with a bigger buffer. */
494 cbBuf *= 2;
495 AssertReturn(cbBuf <= _256K, setError(E_FAIL, tr("%s returns too much data"), pszLogGetStr));
496 }
497}
498
499
500STDMETHODIMP MachineDebugger::COMGETTER(LogDbgFlags)(BSTR *a_pbstrSettings)
501{
502 CheckComArgOutPointerValid(a_pbstrSettings);
503
504 AutoCaller autoCaller(this);
505 HRESULT hrc = autoCaller.rc();
506 if (SUCCEEDED(hrc))
507 hrc = logStringProps(RTLogGetDefaultInstance(), RTLogGetFlags, "RTGetFlags", a_pbstrSettings);
508
509 return hrc;
510}
511
512STDMETHODIMP MachineDebugger::COMGETTER(LogDbgGroups)(BSTR *a_pbstrSettings)
513{
514 CheckComArgOutPointerValid(a_pbstrSettings);
515
516 AutoCaller autoCaller(this);
517 HRESULT hrc = autoCaller.rc();
518 if (SUCCEEDED(hrc))
519 hrc = logStringProps(RTLogGetDefaultInstance(), RTLogGetGroupSettings, "RTLogGetGroupSettings", a_pbstrSettings);
520
521 return hrc;
522}
523
524STDMETHODIMP MachineDebugger::COMGETTER(LogDbgDestinations)(BSTR *a_pbstrSettings)
525{
526 CheckComArgOutPointerValid(a_pbstrSettings);
527
528 AutoCaller autoCaller(this);
529 HRESULT hrc = autoCaller.rc();
530 if (SUCCEEDED(hrc))
531 hrc = logStringProps(RTLogGetDefaultInstance(), RTLogGetDestinations, "RTLogGetDestinations", a_pbstrSettings);
532
533 return hrc;
534}
535
536
537STDMETHODIMP MachineDebugger::COMGETTER(LogRelFlags)(BSTR *a_pbstrSettings)
538{
539 CheckComArgOutPointerValid(a_pbstrSettings);
540
541 AutoCaller autoCaller(this);
542 HRESULT hrc = autoCaller.rc();
543 if (SUCCEEDED(hrc))
544 hrc = logStringProps(RTLogRelDefaultInstance(), RTLogGetFlags, "RTGetFlags", a_pbstrSettings);
545
546 return hrc;
547}
548
549STDMETHODIMP MachineDebugger::COMGETTER(LogRelGroups)(BSTR *a_pbstrSettings)
550{
551 CheckComArgOutPointerValid(a_pbstrSettings);
552
553 AutoCaller autoCaller(this);
554 HRESULT hrc = autoCaller.rc();
555 if (SUCCEEDED(hrc))
556 hrc = logStringProps(RTLogRelDefaultInstance(), RTLogGetGroupSettings, "RTLogGetGroupSettings", a_pbstrSettings);
557
558 return hrc;
559}
560
561STDMETHODIMP MachineDebugger::COMGETTER(LogRelDestinations)(BSTR *a_pbstrSettings)
562{
563 CheckComArgOutPointerValid(a_pbstrSettings);
564
565 AutoCaller autoCaller(this);
566 HRESULT hrc = autoCaller.rc();
567 if (SUCCEEDED(hrc))
568 hrc = logStringProps(RTLogRelDefaultInstance(), RTLogGetDestinations, "RTLogGetDestinations", a_pbstrSettings);
569
570 return hrc;
571}
572
573/**
574 * Returns the current hardware virtualization flag.
575 *
576 * @returns COM status code
577 * @param aEnabled address of result variable
578 */
579STDMETHODIMP MachineDebugger::COMGETTER(HWVirtExEnabled) (BOOL *aEnabled)
580{
581 CheckComArgOutPointerValid(aEnabled);
582
583 AutoCaller autoCaller(this);
584 if (FAILED(autoCaller.rc())) return autoCaller.rc();
585
586 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
587
588 Console::SafeVMPtrQuiet pVM (mParent);
589
590 if (pVM.isOk())
591 *aEnabled = HWACCMIsEnabled (pVM.raw());
592 else
593 *aEnabled = false;
594
595 return S_OK;
596}
597
598/**
599 * Returns the current nested paging flag.
600 *
601 * @returns COM status code
602 * @param aEnabled address of result variable
603 */
604STDMETHODIMP MachineDebugger::COMGETTER(HWVirtExNestedPagingEnabled) (BOOL *aEnabled)
605{
606 CheckComArgOutPointerValid(aEnabled);
607
608 AutoCaller autoCaller(this);
609 if (FAILED(autoCaller.rc())) return autoCaller.rc();
610
611 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
612
613 Console::SafeVMPtrQuiet pVM (mParent);
614
615 if (pVM.isOk())
616 *aEnabled = HWACCMR3IsNestedPagingActive (pVM.raw());
617 else
618 *aEnabled = false;
619
620 return S_OK;
621}
622
623/**
624 * Returns the current VPID flag.
625 *
626 * @returns COM status code
627 * @param aEnabled address of result variable
628 */
629STDMETHODIMP MachineDebugger::COMGETTER(HWVirtExVPIDEnabled) (BOOL *aEnabled)
630{
631 CheckComArgOutPointerValid(aEnabled);
632
633 AutoCaller autoCaller(this);
634 if (FAILED(autoCaller.rc())) return autoCaller.rc();
635
636 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
637
638 Console::SafeVMPtrQuiet pVM (mParent);
639
640 if (pVM.isOk())
641 *aEnabled = HWACCMR3IsVPIDActive (pVM.raw());
642 else
643 *aEnabled = false;
644
645 return S_OK;
646}
647
648STDMETHODIMP MachineDebugger::COMGETTER(OSName)(BSTR *a_pbstrName)
649{
650 LogFlowThisFunc(("\n"));
651 CheckComArgNotNull(a_pbstrName);
652 AutoCaller autoCaller(this);
653 HRESULT hrc = autoCaller.rc();
654 if (SUCCEEDED(hrc))
655 {
656 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
657 Console::SafeVMPtr ptrVM(mParent);
658 hrc = ptrVM.rc();
659 if (SUCCEEDED(hrc))
660 {
661 /*
662 * Do the job and try convert the name.
663 */
664 char szName[64];
665 int vrc = DBGFR3OSQueryNameAndVersion(ptrVM.raw(), szName, sizeof(szName), NULL, 0);
666 if (RT_SUCCESS(vrc))
667 {
668 try
669 {
670 Bstr bstrName(szName);
671 bstrName.detachTo(a_pbstrName);
672 }
673 catch (std::bad_alloc)
674 {
675 hrc = E_OUTOFMEMORY;
676 }
677 }
678 else
679 hrc = setError(VBOX_E_VM_ERROR, tr("DBGFR3OSQueryNameAndVersion failed with %Rrc"), vrc);
680 }
681 }
682 return hrc;
683}
684
685STDMETHODIMP MachineDebugger::COMGETTER(OSVersion)(BSTR *a_pbstrVersion)
686{
687 LogFlowThisFunc(("\n"));
688 CheckComArgNotNull(a_pbstrVersion);
689 AutoCaller autoCaller(this);
690 HRESULT hrc = autoCaller.rc();
691 if (SUCCEEDED(hrc))
692 {
693 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
694 Console::SafeVMPtr ptrVM(mParent);
695 hrc = ptrVM.rc();
696 if (SUCCEEDED(hrc))
697 {
698 /*
699 * Do the job and try convert the name.
700 */
701 char szVersion[256];
702 int vrc = DBGFR3OSQueryNameAndVersion(ptrVM.raw(), NULL, 0, szVersion, sizeof(szVersion));
703 if (RT_SUCCESS(vrc))
704 {
705 try
706 {
707 Bstr bstrVersion(szVersion);
708 bstrVersion.detachTo(a_pbstrVersion);
709 }
710 catch (std::bad_alloc)
711 {
712 hrc = E_OUTOFMEMORY;
713 }
714 }
715 else
716 hrc = setError(VBOX_E_VM_ERROR, tr("DBGFR3OSQueryNameAndVersion failed with %Rrc"), vrc);
717 }
718 }
719 return hrc;
720}
721
722/**
723 * Returns the current PAE flag.
724 *
725 * @returns COM status code
726 * @param aEnabled address of result variable
727 */
728STDMETHODIMP MachineDebugger::COMGETTER(PAEEnabled) (BOOL *aEnabled)
729{
730 CheckComArgOutPointerValid(aEnabled);
731
732 AutoCaller autoCaller(this);
733 if (FAILED(autoCaller.rc())) return autoCaller.rc();
734
735 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
736
737 Console::SafeVMPtrQuiet pVM (mParent);
738
739 if (pVM.isOk())
740 {
741 uint64_t cr4 = CPUMGetGuestCR4 (VMMGetCpu0(pVM.raw()));
742 *aEnabled = !!(cr4 & X86_CR4_PAE);
743 }
744 else
745 *aEnabled = false;
746
747 return S_OK;
748}
749
750/**
751 * Returns the current virtual time rate.
752 *
753 * @returns COM status code.
754 * @param aPct Where to store the rate.
755 */
756STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate) (ULONG *aPct)
757{
758 CheckComArgOutPointerValid(aPct);
759
760 AutoCaller autoCaller(this);
761 if (FAILED(autoCaller.rc())) return autoCaller.rc();
762
763 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
764
765 Console::SafeVMPtrQuiet pVM (mParent);
766
767 if (pVM.isOk())
768 *aPct = TMGetWarpDrive (pVM);
769 else
770 *aPct = 100;
771
772 return S_OK;
773}
774
775/**
776 * Returns the current virtual time rate.
777 *
778 * @returns COM status code.
779 * @param aPct Where to store the rate.
780 */
781STDMETHODIMP MachineDebugger::COMSETTER(VirtualTimeRate) (ULONG aPct)
782{
783 if (aPct < 2 || aPct > 20000)
784 return E_INVALIDARG;
785
786 AutoCaller autoCaller(this);
787 if (FAILED(autoCaller.rc())) return autoCaller.rc();
788
789 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
790
791 if (queueSettings())
792 {
793 // queue the request
794 mVirtualTimeRateQueued = aPct;
795 return S_OK;
796 }
797
798 Console::SafeVMPtr pVM(mParent);
799 if (FAILED(pVM.rc())) return pVM.rc();
800
801 int vrc = TMR3SetWarpDrive (pVM, aPct);
802 if (RT_FAILURE(vrc))
803 {
804 /** @todo handle error code. */
805 }
806
807 return S_OK;
808}
809
810/**
811 * Hack for getting the VM handle.
812 * This is only temporary (promise) while prototyping the debugger.
813 *
814 * @returns COM status code
815 * @param aVm Where to store the vm handle.
816 * Since there is no uintptr_t in COM, we're using the max integer.
817 * (No, ULONG is not pointer sized!)
818 */
819STDMETHODIMP MachineDebugger::COMGETTER(VM) (LONG64 *aVm)
820{
821 CheckComArgOutPointerValid(aVm);
822
823 AutoCaller autoCaller(this);
824 if (FAILED(autoCaller.rc())) return autoCaller.rc();
825
826 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
827
828 Console::SafeVMPtr pVM(mParent);
829 if (FAILED(pVM.rc())) return pVM.rc();
830
831 *aVm = (intptr_t)pVM.raw();
832
833 /*
834 * Note: pVM protection provided by SafeVMPtr is no more effective
835 * after we return from this method.
836 */
837
838 return S_OK;
839}
840
841// IMachineDebugger methods
842/////////////////////////////////////////////////////////////////////////////
843
844STDMETHODIMP MachineDebugger::DumpGuestCore(IN_BSTR a_bstrFilename, IN_BSTR a_bstrCompression)
845{
846 CheckComArgStrNotEmptyOrNull(a_bstrFilename);
847 Utf8Str strFilename(a_bstrFilename);
848 if (a_bstrCompression && *a_bstrCompression)
849 return setError(E_INVALIDARG, tr("The compression parameter must be empty"));
850
851 AutoCaller autoCaller(this);
852 HRESULT hrc = autoCaller.rc();
853 if (SUCCEEDED(hrc))
854 {
855 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
856 Console::SafeVMPtr ptrVM(mParent);
857 hrc = ptrVM.rc();
858 if (SUCCEEDED(hrc))
859 {
860 int vrc = DBGFR3CoreWrite(ptrVM, strFilename.c_str(), false /*fReplaceFile*/);
861 if (RT_SUCCESS(vrc))
862 hrc = S_OK;
863 else
864 hrc = setError(E_FAIL, tr("DBGFR3CoreWrite failed with %Rrc"), vrc);
865 }
866 }
867
868 return hrc;
869}
870
871STDMETHODIMP MachineDebugger::DumpHostProcessCore(IN_BSTR a_bstrFilename, IN_BSTR a_bstrCompression)
872{
873 ReturnComNotImplemented();
874}
875
876/**
877 * Debug info string buffer formatter.
878 */
879typedef struct MACHINEDEBUGGERINOFHLP
880{
881 /** The core info helper structure. */
882 DBGFINFOHLP Core;
883 /** Pointer to the buffer. */
884 char *pszBuf;
885 /** The size of the buffer. */
886 size_t cbBuf;
887 /** The offset into the buffer */
888 size_t offBuf;
889 /** Indicates an out-of-memory condition. */
890 bool fOutOfMemory;
891} MACHINEDEBUGGERINOFHLP;
892/** Pointer to a Debug info string buffer formatter. */
893typedef MACHINEDEBUGGERINOFHLP *PMACHINEDEBUGGERINOFHLP;
894
895
896/**
897 * @callback_method_impl{FNRTSTROUTPUT}
898 */
899static DECLCALLBACK(size_t) MachineDebuggerInfoOutput(void *pvArg, const char *pachChars, size_t cbChars)
900{
901 PMACHINEDEBUGGERINOFHLP pHlp = (PMACHINEDEBUGGERINOFHLP)pvArg;
902
903 /*
904 * Grow the buffer if required.
905 */
906 size_t const cbRequired = cbChars + pHlp->offBuf + 1;
907 if (cbRequired > pHlp->cbBuf)
908 {
909 if (RT_UNLIKELY(pHlp->fOutOfMemory))
910 return 0;
911
912 size_t cbBufNew = pHlp->cbBuf * 2;
913 if (cbRequired > cbBufNew)
914 cbBufNew = RT_ALIGN_Z(cbRequired, 256);
915 void *pvBufNew = RTMemRealloc(pHlp->pszBuf, cbBufNew);
916 if (RT_UNLIKELY(!pvBufNew))
917 {
918 pHlp->fOutOfMemory = true;
919 RTMemFree(pHlp->pszBuf);
920 pHlp->pszBuf = NULL;
921 pHlp->cbBuf = 0;
922 pHlp->offBuf = 0;
923 return 0;
924 }
925
926 pHlp->pszBuf = (char *)pvBufNew;
927 pHlp->cbBuf = cbBufNew;
928 }
929
930 /*
931 * Copy the bytes into the buffer and terminate it.
932 */
933 memcpy(&pHlp->pszBuf[pHlp->offBuf], pachChars, cbChars);
934 pHlp->offBuf += cbChars;
935 pHlp->pszBuf[pHlp->offBuf] = '\0';
936 Assert(pHlp->offBuf < pHlp->cbBuf);
937 return cbChars;
938}
939
940/**
941 * @interface_method_impl{DBGFINFOHLP, pfnPrintfV}
942 */
943static DECLCALLBACK(void) MachineDebuggerInfoPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list va)
944{
945 RTStrFormatV(MachineDebuggerInfoOutput, (void *)pHlp, NULL, NULL, pszFormat, va);
946}
947
948/**
949 * @interface_method_impl{DBGFINFOHLP, pfnPrintf}
950 */
951static DECLCALLBACK(void) MachineDebuggerInfoPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
952{
953 va_list va;
954 va_start(va, pszFormat);
955 MachineDebuggerInfoPrintfV(pHlp, pszFormat, va);
956 va_end(va);
957}
958
959/**
960 * Initializes the debug info string buffer formatter
961 *
962 * @param pHlp The help structure to init.
963 */
964static void MachineDebuggerInfoInit(PMACHINEDEBUGGERINOFHLP pHlp)
965{
966 pHlp->Core.pfnPrintf = MachineDebuggerInfoPrintf;
967 pHlp->Core.pfnPrintfV = MachineDebuggerInfoPrintfV;
968 pHlp->pszBuf = NULL;
969 pHlp->cbBuf = 0;
970 pHlp->offBuf = 0;
971 pHlp->fOutOfMemory = false;
972}
973
974/**
975 * Deletes the debug info string buffer formatter.
976 * @param pHlp The helper structure to delete.
977 */
978static void MachineDebuggerInfoDelete(PMACHINEDEBUGGERINOFHLP pHlp)
979{
980 RTMemFree(pHlp->pszBuf);
981 pHlp->pszBuf = NULL;
982}
983
984STDMETHODIMP MachineDebugger::Info(IN_BSTR a_bstrName, IN_BSTR a_bstrArgs, BSTR *a_pbstrInfo)
985{
986 LogFlowThisFunc(("\n"));
987
988 /*
989 * Validate and convert input.
990 */
991 CheckComArgStrNotEmptyOrNull(a_bstrName);
992 Utf8Str strName, strArgs;
993 try
994 {
995 strName = a_bstrName;
996 strArgs = a_bstrArgs;
997 }
998 catch (std::bad_alloc)
999 {
1000 return E_OUTOFMEMORY;
1001 }
1002
1003 /*
1004 * Do the autocaller and lock bits.
1005 */
1006 AutoCaller autoCaller(this);
1007 HRESULT hrc = autoCaller.rc();
1008 if (SUCCEEDED(hrc))
1009 {
1010 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1011 Console::SafeVMPtr ptrVM(mParent);
1012 hrc = ptrVM.rc();
1013 if (SUCCEEDED(hrc))
1014 {
1015 /*
1016 * Create a helper and call DBGFR3Info.
1017 */
1018 MACHINEDEBUGGERINOFHLP Hlp;
1019 MachineDebuggerInfoInit(&Hlp);
1020 int vrc = DBGFR3Info(ptrVM.raw(), strName.c_str(), strArgs.c_str(), &Hlp.Core);
1021 if (RT_SUCCESS(vrc))
1022 {
1023 if (!Hlp.fOutOfMemory)
1024 {
1025 /*
1026 * Convert the info string, watching out for allocation errors.
1027 */
1028 try
1029 {
1030 Bstr bstrInfo(Hlp.pszBuf);
1031 bstrInfo.detachTo(a_pbstrInfo);
1032 }
1033 catch (std::bad_alloc)
1034 {
1035 hrc = E_OUTOFMEMORY;
1036 }
1037 }
1038 else
1039 hrc = E_OUTOFMEMORY;
1040 }
1041 else
1042 hrc = setError(VBOX_E_VM_ERROR, tr("DBGFR3Info failed with %Rrc"), vrc);
1043 MachineDebuggerInfoDelete(&Hlp);
1044 }
1045 }
1046 return hrc;
1047}
1048
1049STDMETHODIMP MachineDebugger::InjectNMI()
1050{
1051 LogFlowThisFunc(("\n"));
1052
1053 AutoCaller autoCaller(this);
1054 HRESULT hrc = autoCaller.rc();
1055 if (SUCCEEDED(hrc))
1056 {
1057 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1058 Console::SafeVMPtr ptrVM(mParent);
1059 hrc = ptrVM.rc();
1060 if (SUCCEEDED(hrc))
1061 {
1062 int vrc = HWACCMR3InjectNMI(ptrVM);
1063 if (RT_SUCCESS(vrc))
1064 hrc = S_OK;
1065 else
1066 hrc = setError(E_FAIL, tr("HWACCMR3InjectNMI failed with %Rrc"), vrc);
1067 }
1068 }
1069 return hrc;
1070}
1071
1072STDMETHODIMP MachineDebugger::ModifyLogFlags(IN_BSTR a_bstrSettings)
1073{
1074 CheckComArgStrNotEmptyOrNull(a_bstrSettings);
1075 Utf8Str strSettings(a_bstrSettings);
1076
1077 LogFlowThisFunc(("a_bstrSettings=%s\n", strSettings.c_str()));
1078 AutoCaller autoCaller(this);
1079 HRESULT hrc = autoCaller.rc();
1080 if (SUCCEEDED(hrc))
1081 {
1082 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1083 Console::SafeVMPtr ptrVM(mParent);
1084 hrc = ptrVM.rc();
1085 if (SUCCEEDED(hrc))
1086 {
1087 int vrc = DBGFR3LogModifyFlags(ptrVM, strSettings.c_str());
1088 if (RT_SUCCESS(vrc))
1089 hrc = S_OK;
1090 else
1091 hrc = setError(E_FAIL, tr("DBGFR3LogModifyFlags failed with %Rrc"), vrc);
1092 }
1093 }
1094 return hrc;
1095}
1096
1097STDMETHODIMP MachineDebugger::ModifyLogGroups(IN_BSTR a_bstrSettings)
1098{
1099 CheckComArgStrNotEmptyOrNull(a_bstrSettings);
1100 Utf8Str strSettings(a_bstrSettings);
1101
1102 LogFlowThisFunc(("a_bstrSettings=%s\n", strSettings.c_str()));
1103 AutoCaller autoCaller(this);
1104 HRESULT hrc = autoCaller.rc();
1105 if (SUCCEEDED(hrc))
1106 {
1107 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1108 Console::SafeVMPtr ptrVM(mParent);
1109 hrc = ptrVM.rc();
1110 if (SUCCEEDED(hrc))
1111 {
1112 int vrc = DBGFR3LogModifyGroups(ptrVM, strSettings.c_str());
1113 if (RT_SUCCESS(vrc))
1114 hrc = S_OK;
1115 else
1116 hrc = setError(E_FAIL, tr("DBGFR3LogModifyGroups failed with %Rrc"), vrc);
1117 }
1118 }
1119 return hrc;
1120}
1121
1122STDMETHODIMP MachineDebugger::ModifyLogDestinations(IN_BSTR a_bstrSettings)
1123{
1124 CheckComArgStrNotEmptyOrNull(a_bstrSettings);
1125 Utf8Str strSettings(a_bstrSettings);
1126
1127 LogFlowThisFunc(("a_bstrSettings=%s\n", strSettings.c_str()));
1128 AutoCaller autoCaller(this);
1129 HRESULT hrc = autoCaller.rc();
1130 if (SUCCEEDED(hrc))
1131 {
1132 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1133 Console::SafeVMPtr ptrVM(mParent);
1134 hrc = ptrVM.rc();
1135 if (SUCCEEDED(hrc))
1136 {
1137 int vrc = DBGFR3LogModifyDestinations(ptrVM, strSettings.c_str());
1138 if (RT_SUCCESS(vrc))
1139 hrc = S_OK;
1140 else
1141 hrc = setError(E_FAIL, tr("DBGFR3LogModifyDestinations failed with %Rrc"), vrc);
1142 }
1143 }
1144 return hrc;
1145}
1146
1147STDMETHODIMP MachineDebugger::ReadPhysicalMemory(LONG64 a_Address, ULONG a_cbRead, ComSafeArrayOut(BYTE, a_abData))
1148{
1149 ReturnComNotImplemented();
1150}
1151
1152STDMETHODIMP MachineDebugger::WritePhysicalMemory(LONG64 a_Address, ULONG a_cbRead, ComSafeArrayIn(BYTE, a_abData))
1153{
1154 ReturnComNotImplemented();
1155}
1156
1157STDMETHODIMP MachineDebugger::ReadVirtualMemory(ULONG a_idCpu, LONG64 a_Address, ULONG a_cbRead, ComSafeArrayOut(BYTE, a_abData))
1158{
1159 ReturnComNotImplemented();
1160}
1161
1162STDMETHODIMP MachineDebugger::WriteVirtualMemory(ULONG a_idCpu, LONG64 a_Address, ULONG a_cbRead, ComSafeArrayIn(BYTE, a_abData))
1163{
1164 ReturnComNotImplemented();
1165}
1166
1167STDMETHODIMP MachineDebugger::DetectOS(BSTR *a_pbstrName)
1168{
1169 LogFlowThisFunc(("\n"));
1170 CheckComArgNotNull(a_pbstrName);
1171
1172 /*
1173 * Do the autocaller and lock bits.
1174 */
1175 AutoCaller autoCaller(this);
1176 HRESULT hrc = autoCaller.rc();
1177 if (SUCCEEDED(hrc))
1178 {
1179 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1180 Console::SafeVMPtr ptrVM(mParent);
1181 hrc = ptrVM.rc();
1182 if (SUCCEEDED(hrc))
1183 {
1184 /*
1185 * Do the job and try convert the name.
1186 */
1187/** @todo automatically load the DBGC plugins or this is a waste of time. */
1188 char szName[64];
1189 int vrc = DBGFR3OSDetect(ptrVM.raw(), szName, sizeof(szName));
1190 if (RT_SUCCESS(vrc) && vrc != VINF_DBGF_OS_NOT_DETCTED)
1191 {
1192 try
1193 {
1194 Bstr bstrName(szName);
1195 bstrName.detachTo(a_pbstrName);
1196 }
1197 catch (std::bad_alloc)
1198 {
1199 hrc = E_OUTOFMEMORY;
1200 }
1201 }
1202 else
1203 hrc = setError(VBOX_E_VM_ERROR, tr("DBGFR3OSDetect failed with %Rrc"), vrc);
1204 }
1205 }
1206 return hrc;
1207}
1208
1209/**
1210 * Formats a register value.
1211 *
1212 * This is used by both register getter methods.
1213 *
1214 * @returns
1215 * @param a_pbstr The output Bstr variable.
1216 * @param a_pValue The value to format.
1217 * @param a_enmType The type of the value.
1218 */
1219DECLINLINE(HRESULT) formatRegisterValue(Bstr *a_pbstr, PCDBGFREGVAL a_pValue, DBGFREGVALTYPE a_enmType)
1220{
1221 char szHex[160];
1222 ssize_t cch = DBGFR3RegFormatValue(szHex, sizeof(szHex), a_pValue, a_enmType, true /*fSpecial*/);
1223 if (RT_UNLIKELY(cch <= 0))
1224 return E_UNEXPECTED;
1225 *a_pbstr = szHex;
1226 return S_OK;
1227}
1228
1229STDMETHODIMP MachineDebugger::GetRegister(ULONG a_idCpu, IN_BSTR a_bstrName, BSTR *a_pbstrValue)
1230{
1231 /*
1232 * Validate and convert input.
1233 */
1234 CheckComArgStrNotEmptyOrNull(a_bstrName);
1235 CheckComArgNotNull(a_pbstrValue);
1236 Utf8Str strName;
1237 try
1238 {
1239 strName = a_bstrName;
1240 }
1241 catch (std::bad_alloc)
1242 {
1243 return E_OUTOFMEMORY;
1244 }
1245
1246 /*
1247 * The prologue.
1248 */
1249 LogFlowThisFunc(("\n"));
1250 AutoCaller autoCaller(this);
1251 HRESULT hrc = autoCaller.rc();
1252 if (SUCCEEDED(hrc))
1253 {
1254 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1255 Console::SafeVMPtr ptrVM(mParent);
1256 hrc = ptrVM.rc();
1257 if (SUCCEEDED(hrc))
1258 {
1259 /*
1260 * Real work.
1261 */
1262 DBGFREGVAL Value;
1263 DBGFREGVALTYPE enmType;
1264 int vrc = DBGFR3RegNmQuery(ptrVM.raw(), a_idCpu, strName.c_str(), &Value, &enmType);
1265 if (RT_SUCCESS(vrc))
1266 {
1267 try
1268 {
1269 Bstr bstrValue;
1270 hrc = formatRegisterValue(&bstrValue, &Value, enmType);
1271 if (SUCCEEDED(hrc))
1272 bstrValue.detachTo(a_pbstrValue);
1273 }
1274 catch (std::bad_alloc)
1275 {
1276 hrc = E_OUTOFMEMORY;
1277 }
1278 }
1279 else if (vrc == VERR_DBGF_REGISTER_NOT_FOUND)
1280 hrc = setError(E_FAIL, tr("Register '%s' was not found"), strName.c_str());
1281 else if (vrc == VERR_INVALID_CPU_ID)
1282 hrc = setError(E_FAIL, tr("Invalid CPU ID: %u"), a_idCpu);
1283 else
1284 hrc = setError(VBOX_E_VM_ERROR,
1285 tr("DBGFR3RegNmQuery failed with rc=%Rrc querying register '%s' with default cpu set to %u"),
1286 vrc, strName.c_str(), a_idCpu);
1287 }
1288 }
1289
1290 return hrc;
1291}
1292
1293STDMETHODIMP MachineDebugger::GetRegisters(ULONG a_idCpu, ComSafeArrayOut(BSTR, a_bstrNames), ComSafeArrayOut(BSTR, a_bstrValues))
1294{
1295 /*
1296 * The prologue.
1297 */
1298 LogFlowThisFunc(("\n"));
1299 AutoCaller autoCaller(this);
1300 HRESULT hrc = autoCaller.rc();
1301 if (SUCCEEDED(hrc))
1302 {
1303 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1304 Console::SafeVMPtr ptrVM(mParent);
1305 hrc = ptrVM.rc();
1306 if (SUCCEEDED(hrc))
1307 {
1308 /*
1309 * Real work.
1310 */
1311 size_t cRegs;
1312 int vrc = DBGFR3RegNmQueryAllCount(ptrVM.raw(), &cRegs);
1313 if (RT_SUCCESS(vrc))
1314 {
1315 PDBGFREGENTRYNM paRegs = (PDBGFREGENTRYNM)RTMemAllocZ(sizeof(paRegs[0]) * cRegs);
1316 if (paRegs)
1317 {
1318 vrc = DBGFR3RegNmQueryAll(ptrVM.raw(), paRegs, cRegs);
1319 if (RT_SUCCESS(vrc))
1320 {
1321 try
1322 {
1323 com::SafeArray<BSTR> abstrNames(cRegs);
1324 com::SafeArray<BSTR> abstrValues(cRegs);
1325
1326 for (uint32_t iReg = 0; iReg < cRegs; iReg++)
1327 {
1328 char szHex[128];
1329 Bstr bstrValue;
1330
1331 hrc = formatRegisterValue(&bstrValue, &paRegs[iReg].Val, paRegs[iReg].enmType);
1332 AssertComRC(hrc);
1333 bstrValue.detachTo(&abstrValues[iReg]);
1334
1335 Bstr bstrName(paRegs[iReg].pszName);
1336 bstrName.detachTo(&abstrNames[iReg]);
1337 }
1338
1339 abstrNames.detachTo(ComSafeArrayOutArg(a_bstrNames));
1340 abstrValues.detachTo(ComSafeArrayOutArg(a_bstrValues));
1341 }
1342 catch (std::bad_alloc)
1343 {
1344 hrc = E_OUTOFMEMORY;
1345 }
1346 }
1347 else
1348 hrc = setError(E_FAIL, tr("DBGFR3RegNmQueryAll failed with %Rrc"), vrc);
1349
1350 RTMemFree(paRegs);
1351 }
1352 else
1353 hrc = E_OUTOFMEMORY;
1354 }
1355 else
1356 hrc = setError(E_FAIL, tr("DBGFR3RegNmQueryAllCount failed with %Rrc"), vrc);
1357 }
1358 }
1359 return hrc;
1360}
1361
1362STDMETHODIMP MachineDebugger::SetRegister(ULONG a_idCpu, IN_BSTR a_bstrName, IN_BSTR a_bstrValue)
1363{
1364 ReturnComNotImplemented();
1365}
1366
1367STDMETHODIMP MachineDebugger::SetRegisters(ULONG a_idCpu, ComSafeArrayIn(IN_BSTR, a_bstrNames), ComSafeArrayIn(IN_BSTR, a_bstrValues))
1368{
1369 ReturnComNotImplemented();
1370}
1371
1372STDMETHODIMP MachineDebugger::DumpGuestStack(ULONG a_idCpu, BSTR *a_pbstrStack)
1373{
1374 ReturnComNotImplemented();
1375}
1376
1377/**
1378 * Resets VM statistics.
1379 *
1380 * @returns COM status code.
1381 * @param aPattern The selection pattern. A bit similar to filename globbing.
1382 */
1383STDMETHODIMP MachineDebugger::ResetStats(IN_BSTR aPattern)
1384{
1385 Console::SafeVMPtrQuiet pVM (mParent);
1386
1387 if (!pVM.isOk())
1388 return setError(VBOX_E_INVALID_VM_STATE, "Machine is not running");
1389
1390 STAMR3Reset(pVM, Utf8Str(aPattern).c_str());
1391
1392 return S_OK;
1393}
1394
1395/**
1396 * Dumps VM statistics to the log.
1397 *
1398 * @returns COM status code.
1399 * @param aPattern The selection pattern. A bit similar to filename globbing.
1400 */
1401STDMETHODIMP MachineDebugger::DumpStats (IN_BSTR aPattern)
1402{
1403 Console::SafeVMPtrQuiet pVM (mParent);
1404
1405 if (!pVM.isOk())
1406 return setError(VBOX_E_INVALID_VM_STATE, "Machine is not running");
1407
1408 STAMR3Dump(pVM, Utf8Str(aPattern).c_str());
1409
1410 return S_OK;
1411}
1412
1413/**
1414 * Get the VM statistics in an XML format.
1415 *
1416 * @returns COM status code.
1417 * @param aPattern The selection pattern. A bit similar to filename globbing.
1418 * @param aWithDescriptions Whether to include the descriptions.
1419 * @param aStats The XML document containing the statistics.
1420 */
1421STDMETHODIMP MachineDebugger::GetStats (IN_BSTR aPattern, BOOL aWithDescriptions, BSTR *aStats)
1422{
1423 Console::SafeVMPtrQuiet pVM (mParent);
1424
1425 if (!pVM.isOk())
1426 return setError(VBOX_E_INVALID_VM_STATE, "Machine is not running");
1427
1428 char *pszSnapshot;
1429 int vrc = STAMR3Snapshot(pVM, Utf8Str(aPattern).c_str(), &pszSnapshot, NULL,
1430 !!aWithDescriptions);
1431 if (RT_FAILURE(vrc))
1432 return vrc == VERR_NO_MEMORY ? E_OUTOFMEMORY : E_FAIL;
1433
1434 /** @todo this is horribly inefficient! And it's kinda difficult to tell whether it failed...
1435 * Must use UTF-8 or ASCII here and completely avoid these two extra copy operations.
1436 * Until that's done, this method is kind of useless for debugger statistics GUI because
1437 * of the amount statistics in a debug build. */
1438 Bstr(pszSnapshot).detachTo(aStats);
1439
1440 return S_OK;
1441}
1442
1443
1444// public methods only for internal purposes
1445/////////////////////////////////////////////////////////////////////////////
1446
1447void MachineDebugger::flushQueuedSettings()
1448{
1449 mFlushMode = true;
1450 if (mSinglestepQueued != ~0)
1451 {
1452 COMSETTER(Singlestep) (mSinglestepQueued);
1453 mSinglestepQueued = ~0;
1454 }
1455 if (mRecompileUserQueued != ~0)
1456 {
1457 COMSETTER(RecompileUser) (mRecompileUserQueued);
1458 mRecompileUserQueued = ~0;
1459 }
1460 if (mRecompileSupervisorQueued != ~0)
1461 {
1462 COMSETTER(RecompileSupervisor) (mRecompileSupervisorQueued);
1463 mRecompileSupervisorQueued = ~0;
1464 }
1465 if (mPatmEnabledQueued != ~0)
1466 {
1467 COMSETTER(PATMEnabled) (mPatmEnabledQueued);
1468 mPatmEnabledQueued = ~0;
1469 }
1470 if (mCsamEnabledQueued != ~0)
1471 {
1472 COMSETTER(CSAMEnabled) (mCsamEnabledQueued);
1473 mCsamEnabledQueued = ~0;
1474 }
1475 if (mLogEnabledQueued != ~0)
1476 {
1477 COMSETTER(LogEnabled) (mLogEnabledQueued);
1478 mLogEnabledQueued = ~0;
1479 }
1480 if (mVirtualTimeRateQueued != ~(uint32_t)0)
1481 {
1482 COMSETTER(VirtualTimeRate) (mVirtualTimeRateQueued);
1483 mVirtualTimeRateQueued = ~0;
1484 }
1485 mFlushMode = false;
1486}
1487
1488// private methods
1489/////////////////////////////////////////////////////////////////////////////
1490
1491bool MachineDebugger::queueSettings() const
1492{
1493 if (!mFlushMode)
1494 {
1495 // check if the machine is running
1496 MachineState_T machineState;
1497 mParent->COMGETTER(State) (&machineState);
1498 switch (machineState)
1499 {
1500 // queue the request
1501 default:
1502 return true;
1503
1504 case MachineState_Running:
1505 case MachineState_Paused:
1506 case MachineState_Stuck:
1507 case MachineState_LiveSnapshotting:
1508 case MachineState_Teleporting:
1509 break;
1510 }
1511 }
1512 return false;
1513}
1514/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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