VirtualBox

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

Last change on this file since 53401 was 51092, checked in by vboxsync, 11 years ago

6813 src-client/MachineDebuggerImpl.cpp + various formatting changes

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