VirtualBox

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

Last change on this file since 73768 was 73505, checked in by vboxsync, 6 years ago

Main,Config.kmk: GCC 8.2.0 fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.4 KB
RevLine 
[14627]1/* $Id: MachineDebuggerImpl.cpp 73505 2018-08-05 13:58:10Z vboxsync $ */
[1]2/** @file
[44373]3 * VBox IMachineDebugger COM class implementation (VBoxC).
[1]4 */
5
6/*
[69500]7 * Copyright (C) 2006-2017 Oracle Corporation
[1]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
[5999]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.
[1]16 */
17
[57358]18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
[67914]22#define LOG_GROUP LOG_GROUP_MAIN_MACHINEDEBUGGER
23#include "LoggingNew.h"
24
[1]25#include "MachineDebuggerImpl.h"
[15762]26
27#include "Global.h"
[1]28#include "ConsoleImpl.h"
[25860]29
30#include "AutoCaller.h"
[1]31
[35346]32#include <VBox/vmm/em.h>
33#include <VBox/vmm/patm.h>
34#include <VBox/vmm/csam.h>
[44340]35#include <VBox/vmm/uvm.h>
[35346]36#include <VBox/vmm/tm.h>
[43387]37#include <VBox/vmm/hm.h>
[1]38#include <VBox/err.h>
[30681]39#include <iprt/cpp/utils.h>
[1]40
41
42// constructor / destructor
[14627]43/////////////////////////////////////////////////////////////////////////////
[1]44
[27607]45MachineDebugger::MachineDebugger()
46 : mParent(NULL)
47{
48}
[14627]49
[27607]50MachineDebugger::~MachineDebugger()
51{
52}
53
[1]54HRESULT MachineDebugger::FinalConstruct()
55{
[21878]56 unconst(mParent) = NULL;
[35638]57 return BaseFinalConstruct();
[1]58}
59
60void MachineDebugger::FinalRelease()
61{
[14627]62 uninit();
[35638]63 BaseFinalRelease();
[1]64}
65
[14627]66// public initializer/uninitializer for internal purposes only
67/////////////////////////////////////////////////////////////////////////////
[1]68
69/**
70 * Initializes the machine debugger object.
71 *
72 * @returns COM result indicator
[14627]73 * @param aParent handle of our parent object
[1]74 */
[62598]75HRESULT MachineDebugger::init(Console *aParent)
[1]76{
[21878]77 LogFlowThisFunc(("aParent=%p\n", aParent));
[1]78
[26235]79 ComAssertRet(aParent, E_INVALIDARG);
[1]80
[14627]81 /* Enclose the state transition NotReady->InInit->Ready */
[21878]82 AutoInitSpan autoInitSpan(this);
83 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]84
[21878]85 unconst(mParent) = aParent;
[14627]86
[46423]87 for (unsigned i = 0; i < RT_ELEMENTS(maiQueuedEmExecPolicyParams); i++)
88 maiQueuedEmExecPolicyParams[i] = UINT8_MAX;
[63147]89 mSingleStepQueued = -1;
90 mRecompileUserQueued = -1;
91 mRecompileSupervisorQueued = -1;
92 mPatmEnabledQueued = -1;
93 mCsamEnabledQueued = -1;
94 mLogEnabledQueued = -1;
95 mVirtualTimeRateQueued = UINT32_MAX;
[14627]96 mFlushMode = false;
97
98 /* Confirm a successful initialization */
99 autoInitSpan.setSucceeded();
100
[1]101 return S_OK;
102}
103
104/**
105 * Uninitializes the instance and sets the ready flag to FALSE.
106 * Called either from FinalRelease() or by the parent when it gets destroyed.
107 */
108void MachineDebugger::uninit()
109{
[21878]110 LogFlowThisFunc(("\n"));
[1]111
[14627]112 /* Enclose the state transition Ready->InUninit->NotReady */
[21878]113 AutoUninitSpan autoUninitSpan(this);
[14627]114 if (autoUninitSpan.uninitDone())
115 return;
[1]116
[27607]117 unconst(mParent) = NULL;
[14627]118 mFlushMode = false;
[1]119}
120
[14627]121// IMachineDebugger properties
122/////////////////////////////////////////////////////////////////////////////
123
[1]124/**
125 * Returns the current singlestepping flag.
126 *
127 * @returns COM status code
[65120]128 * @param aSingleStep Where to store the result.
[1]129 */
[51092]130HRESULT MachineDebugger::getSingleStep(BOOL *aSingleStep)
[1]131{
[51092]132 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
133 Console::SafeVMPtr ptrVM(mParent);
134 HRESULT hrc = ptrVM.rc();
[39712]135 if (SUCCEEDED(hrc))
136 {
[63244]137 RT_NOREF(aSingleStep); /** @todo */
[51092]138 ReturnComNotImplemented();
[39712]139 }
140 return hrc;
[1]141}
142
143/**
144 * Sets the singlestepping flag.
145 *
146 * @returns COM status code
[65103]147 * @param aSingleStep The new state.
[1]148 */
[51092]149HRESULT MachineDebugger::setSingleStep(BOOL aSingleStep)
[1]150{
[51092]151 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
152 Console::SafeVMPtr ptrVM(mParent);
153 HRESULT hrc = ptrVM.rc();
[39712]154 if (SUCCEEDED(hrc))
155 {
[63244]156 NOREF(aSingleStep); /** @todo */
[51092]157 ReturnComNotImplemented();
[39712]158 }
159 return hrc;
[1]160}
161
162/**
[46423]163 * Internal worker for getting an EM executable policy setting.
[1]164 *
[46423]165 * @returns COM status code.
166 * @param enmPolicy Which EM policy.
167 * @param pfEnforced Where to return the policy setting.
[1]168 */
[51092]169HRESULT MachineDebugger::i_getEmExecPolicyProperty(EMEXECPOLICY enmPolicy, BOOL *pfEnforced)
[1]170{
[46423]171 CheckComArgOutPointerValid(pfEnforced);
[1]172
[21878]173 AutoCaller autoCaller(this);
[46423]174 HRESULT hrc = autoCaller.rc();
175 if (SUCCEEDED(hrc))
176 {
177 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[51092]178 if (i_queueSettings())
[46423]179 *pfEnforced = maiQueuedEmExecPolicyParams[enmPolicy] == 1;
180 else
181 {
182 bool fEnforced = false;
183 Console::SafeVMPtrQuiet ptrVM(mParent);
184 hrc = ptrVM.rc();
185 if (SUCCEEDED(hrc))
186 EMR3QueryExecutionPolicy(ptrVM.rawUVM(), enmPolicy, &fEnforced);
187 *pfEnforced = fEnforced;
188 }
189 }
190 return hrc;
[1]191}
192
193/**
[46423]194 * Internal worker for setting an EM executable policy.
[1]195 *
[46423]196 * @returns COM status code.
197 * @param enmPolicy Which policy to change.
198 * @param fEnforce Whether to enforce the policy or not.
[1]199 */
[51092]200HRESULT MachineDebugger::i_setEmExecPolicyProperty(EMEXECPOLICY enmPolicy, BOOL fEnforce)
[1]201{
[21878]202 AutoCaller autoCaller(this);
[38324]203 HRESULT hrc = autoCaller.rc();
204 if (SUCCEEDED(hrc))
[1]205 {
[46423]206 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[51092]207 if (i_queueSettings())
[46423]208 maiQueuedEmExecPolicyParams[enmPolicy] = fEnforce ? 1 : 0;
[38324]209 else
210 {
[46423]211 Console::SafeVMPtrQuiet ptrVM(mParent);
[38324]212 hrc = ptrVM.rc();
213 if (SUCCEEDED(hrc))
214 {
[46423]215 int vrc = EMR3SetExecutionPolicy(ptrVM.rawUVM(), enmPolicy, fEnforce != FALSE);
[38324]216 if (RT_FAILURE(vrc))
[73003]217 hrc = setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("EMR3SetExecutionPolicy failed with %Rrc"), vrc);
[38324]218 }
219 }
[1]220 }
[38324]221 return hrc;
[1]222}
223
224/**
[46423]225 * Returns the current recompile user mode code flag.
226 *
227 * @returns COM status code
[65103]228 * @param aRecompileUser address of result variable
[46423]229 */
[51092]230HRESULT MachineDebugger::getRecompileUser(BOOL *aRecompileUser)
[46423]231{
[51092]232 return i_getEmExecPolicyProperty(EMEXECPOLICY_RECOMPILE_RING3, aRecompileUser);
[46423]233}
234
235/**
236 * Sets the recompile user mode code flag.
237 *
238 * @returns COM status
[65103]239 * @param aRecompileUser new user mode code recompile flag.
[46423]240 */
[51092]241HRESULT MachineDebugger::setRecompileUser(BOOL aRecompileUser)
[46423]242{
[51092]243 LogFlowThisFunc(("enable=%d\n", aRecompileUser));
244 return i_setEmExecPolicyProperty(EMEXECPOLICY_RECOMPILE_RING3, aRecompileUser);
[46423]245}
246
247/**
[1]248 * Returns the current recompile supervisor code flag.
249 *
250 * @returns COM status code
[65103]251 * @param aRecompileSupervisor address of result variable
[1]252 */
[51092]253HRESULT MachineDebugger::getRecompileSupervisor(BOOL *aRecompileSupervisor)
[1]254{
[51092]255 return i_getEmExecPolicyProperty(EMEXECPOLICY_RECOMPILE_RING0, aRecompileSupervisor);
[1]256}
257
258/**
259 * Sets the new recompile supervisor code flag.
260 *
261 * @returns COM status code
[65103]262 * @param aRecompileSupervisor new recompile supervisor code flag
[1]263 */
[51092]264HRESULT MachineDebugger::setRecompileSupervisor(BOOL aRecompileSupervisor)
[1]265{
[51092]266 LogFlowThisFunc(("enable=%d\n", aRecompileSupervisor));
267 return i_setEmExecPolicyProperty(EMEXECPOLICY_RECOMPILE_RING0, aRecompileSupervisor);
[46423]268}
[1]269
[46423]270/**
271 * Returns the current execute-all-in-IEM setting.
272 *
273 * @returns COM status code
[65103]274 * @param aExecuteAllInIEM Address of result variable.
[46423]275 */
[51092]276HRESULT MachineDebugger::getExecuteAllInIEM(BOOL *aExecuteAllInIEM)
[46423]277{
[51092]278 return i_getEmExecPolicyProperty(EMEXECPOLICY_IEM_ALL, aExecuteAllInIEM);
[1]279}
280
281/**
[46423]282 * Changes the execute-all-in-IEM setting.
283 *
284 * @returns COM status code
[65103]285 * @param aExecuteAllInIEM New setting.
[46423]286 */
[51092]287HRESULT MachineDebugger::setExecuteAllInIEM(BOOL aExecuteAllInIEM)
[46423]288{
[51092]289 LogFlowThisFunc(("enable=%d\n", aExecuteAllInIEM));
290 return i_setEmExecPolicyProperty(EMEXECPOLICY_IEM_ALL, aExecuteAllInIEM);
[46423]291}
292
293/**
[1]294 * Returns the current patch manager enabled flag.
295 *
296 * @returns COM status code
[65103]297 * @param aPATMEnabled address of result variable
[1]298 */
[51092]299HRESULT MachineDebugger::getPATMEnabled(BOOL *aPATMEnabled)
[1]300{
[45528]301#ifdef VBOX_WITH_RAW_MODE
[25310]302 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[14627]303
[44362]304 Console::SafeVMPtrQuiet ptrVM(mParent);
305 if (ptrVM.isOk())
[62598]306 *aPATMEnabled = PATMR3IsEnabled(ptrVM.rawUVM());
[1]307 else
[45528]308#endif
[51092]309 *aPATMEnabled = false;
[14627]310
[1]311 return S_OK;
312}
313
314/**
315 * Set the new patch manager enabled flag.
316 *
317 * @returns COM status code
[65103]318 * @param aPATMEnabled new patch manager enabled flag
[1]319 */
[51092]320HRESULT MachineDebugger::setPATMEnabled(BOOL aPATMEnabled)
[1]321{
[51092]322 LogFlowThisFunc(("enable=%d\n", aPATMEnabled));
[14627]323
[45528]324#ifdef VBOX_WITH_RAW_MODE
[25310]325 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]326
[51092]327 if (i_queueSettings())
[1]328 {
[14627]329 // queue the request
[51092]330 mPatmEnabledQueued = aPATMEnabled;
[14627]331 return S_OK;
[1]332 }
333
[44362]334 Console::SafeVMPtr ptrVM(mParent);
335 if (FAILED(ptrVM.rc()))
336 return ptrVM.rc();
[1]337
[51092]338 int vrc = PATMR3AllowPatching(ptrVM.rawUVM(), RT_BOOL(aPATMEnabled));
[44362]339 if (RT_FAILURE(vrc))
[73003]340 return setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("PATMR3AllowPatching returned %Rrc"), vrc);
[14627]341
[45528]342#else /* !VBOX_WITH_RAW_MODE */
[51092]343 if (aPATMEnabled)
[73003]344 return setErrorBoth(VBOX_E_VM_ERROR, VERR_RAW_MODE_NOT_SUPPORTED, tr("PATM not present"), VERR_NOT_SUPPORTED);
[45528]345#endif /* !VBOX_WITH_RAW_MODE */
[14107]346 return S_OK;
[1]347}
348
349/**
350 * Returns the current code scanner enabled flag.
351 *
352 * @returns COM status code
[65103]353 * @param aCSAMEnabled address of result variable
[1]354 */
[51092]355HRESULT MachineDebugger::getCSAMEnabled(BOOL *aCSAMEnabled)
[1]356{
[45528]357#ifdef VBOX_WITH_RAW_MODE
[25310]358 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[14627]359
[44373]360 Console::SafeVMPtrQuiet ptrVM(mParent);
[14627]361
[44373]362 if (ptrVM.isOk())
[51092]363 *aCSAMEnabled = CSAMR3IsEnabled(ptrVM.rawUVM());
[1]364 else
[45528]365#endif /* VBOX_WITH_RAW_MODE */
[51092]366 *aCSAMEnabled = false;
[14627]367
[1]368 return S_OK;
369}
370
371/**
372 * Sets the new code scanner enabled flag.
373 *
374 * @returns COM status code
[65103]375 * @param aCSAMEnabled new code scanner enabled flag
[1]376 */
[51092]377HRESULT MachineDebugger::setCSAMEnabled(BOOL aCSAMEnabled)
[1]378{
[51092]379 LogFlowThisFunc(("enable=%d\n", aCSAMEnabled));
[14627]380
[45528]381#ifdef VBOX_WITH_RAW_MODE
[25310]382 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]383
[51092]384 if (i_queueSettings())
[1]385 {
[14627]386 // queue the request
[51092]387 mCsamEnabledQueued = aCSAMEnabled;
[14627]388 return S_OK;
[1]389 }
390
[44373]391 Console::SafeVMPtr ptrVM(mParent);
[44385]392 if (FAILED(ptrVM.rc()))
393 return ptrVM.rc();
[1]394
[51092]395 int vrc = CSAMR3SetScanningEnabled(ptrVM.rawUVM(), aCSAMEnabled != FALSE);
[21878]396 if (RT_FAILURE(vrc))
[73003]397 return setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("CSAMR3SetScanningEnabled returned %Rrc"), vrc);
[14627]398
[45528]399#else /* !VBOX_WITH_RAW_MODE */
[51092]400 if (aCSAMEnabled)
[73003]401 return setErrorBoth(VBOX_E_VM_ERROR, VERR_RAW_MODE_NOT_SUPPORTED, tr("CASM not present"));
[45528]402#endif /* !VBOX_WITH_RAW_MODE */
[1]403 return S_OK;
404}
405
406/**
407 * Returns the log enabled / disabled status.
408 *
409 * @returns COM status code
[58132]410 * @param aLogEnabled address of result variable
[1]411 */
[51092]412HRESULT MachineDebugger::getLogEnabled(BOOL *aLogEnabled)
[1]413{
[9242]414#ifdef LOG_ENABLED
[25310]415 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[14627]416
417 const PRTLOGGER pLogInstance = RTLogDefaultInstance();
[51092]418 *aLogEnabled = pLogInstance && !(pLogInstance->fFlags & RTLOGFLAGS_DISABLED);
[9242]419#else
[51092]420 *aLogEnabled = false;
[9242]421#endif
[14627]422
[1]423 return S_OK;
424}
425
426/**
427 * Enables or disables logging.
428 *
429 * @returns COM status code
[58132]430 * @param aLogEnabled The new code log state.
[1]431 */
[51092]432HRESULT MachineDebugger::setLogEnabled(BOOL aLogEnabled)
[1]433{
[51092]434 LogFlowThisFunc(("aLogEnabled=%d\n", aLogEnabled));
[1]435
[25310]436 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[14627]437
[51092]438 if (i_queueSettings())
[1]439 {
[14627]440 // queue the request
[51092]441 mLogEnabledQueued = aLogEnabled;
[14627]442 return S_OK;
[1]443 }
444
[44373]445 Console::SafeVMPtr ptrVM(mParent);
446 if (FAILED(ptrVM.rc())) return ptrVM.rc();
[1]447
[9242]448#ifdef LOG_ENABLED
[51092]449 int vrc = DBGFR3LogModifyFlags(ptrVM.rawUVM(), aLogEnabled ? "enabled" : "disabled");
[21878]450 if (RT_FAILURE(vrc))
[1]451 {
452 /** @todo handle error code. */
453 }
[9242]454#endif
[14627]455
[1]456 return S_OK;
457}
458
[51092]459HRESULT MachineDebugger::i_logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr,
[56567]460 const char *pszLogGetStr, Utf8Str *pstrSettings)
[35250]461{
[39668]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 {
[56567]472 *pstrSettings = "";
[39668]473 return S_OK;
474 }
475
476 /* Do the job. */
477 size_t cbBuf = _1K;
478 for (;;)
479 {
480 char *pszBuf = (char *)RTMemTmpAlloc(cbBuf);
481 AssertReturn(pszBuf, E_OUTOFMEMORY);
[56567]482 int vrc = pstrSettings->reserveNoThrow(cbBuf);
483 if (RT_SUCCESS(vrc))
[39668]484 {
[56567]485 vrc = pfnLogGetStr(pLogger, pstrSettings->mutableRaw(), cbBuf);
486 if (RT_SUCCESS(vrc))
[39668]487 {
[56567]488 pstrSettings->jolt();
489 return S_OK;
[39668]490 }
[56567]491 *pstrSettings = "";
[73003]492 AssertReturn(vrc == VERR_BUFFER_OVERFLOW,
493 setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("%s returned %Rrc"), pszLogGetStr, vrc));
[39668]494 }
[56567]495 else
496 return E_OUTOFMEMORY;
[39668]497
498 /* try again with a bigger buffer. */
499 cbBuf *= 2;
500 AssertReturn(cbBuf <= _256K, setError(E_FAIL, tr("%s returns too much data"), pszLogGetStr));
501 }
[35250]502}
503
[51092]504HRESULT MachineDebugger::getLogDbgFlags(com::Utf8Str &aLogDbgFlags)
[35250]505{
[56567]506 return i_logStringProps(RTLogGetDefaultInstance(), RTLogGetFlags, "RTGetFlags", &aLogDbgFlags);
[35250]507}
508
[51092]509HRESULT MachineDebugger::getLogDbgGroups(com::Utf8Str &aLogDbgGroups)
[35250]510{
[56567]511 return i_logStringProps(RTLogGetDefaultInstance(), RTLogGetGroupSettings, "RTLogGetGroupSettings", &aLogDbgGroups);
[35250]512}
513
[51092]514HRESULT MachineDebugger::getLogDbgDestinations(com::Utf8Str &aLogDbgDestinations)
[39668]515{
[56567]516 return i_logStringProps(RTLogGetDefaultInstance(), RTLogGetDestinations, "RTLogGetDestinations", &aLogDbgDestinations);
[39668]517}
518
[51092]519HRESULT MachineDebugger::getLogRelFlags(com::Utf8Str &aLogRelFlags)
[39668]520{
[56567]521 return i_logStringProps(RTLogRelGetDefaultInstance(), RTLogGetFlags, "RTGetFlags", &aLogRelFlags);
[39668]522}
523
[51092]524HRESULT MachineDebugger::getLogRelGroups(com::Utf8Str &aLogRelGroups)
[39668]525{
[56567]526 return i_logStringProps(RTLogRelGetDefaultInstance(), RTLogGetGroupSettings, "RTLogGetGroupSettings", &aLogRelGroups);
[39668]527}
528
[51092]529HRESULT MachineDebugger::getLogRelDestinations(com::Utf8Str &aLogRelDestinations)
[39668]530{
[56567]531 return i_logStringProps(RTLogRelGetDefaultInstance(), RTLogGetDestinations, "RTLogGetDestinations", &aLogRelDestinations);
[39668]532}
533
[1]534/**
[72328]535 * Return the main execution engine of the VM.
536 *
537 * @returns COM status code
538 * @param apenmEngine Address of the result variable.
539 */
540HRESULT MachineDebugger::getExecutionEngine(VMExecutionEngine_T *apenmEngine)
541{
542 *apenmEngine = VMExecutionEngine_NotSet;
543
544 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
545 Console::SafeVMPtrQuiet ptrVM(mParent);
546 if (ptrVM.isOk())
547 {
548 uint8_t bEngine = UINT8_MAX;
549 int rc = EMR3QueryMainExecutionEngine(ptrVM.rawUVM(), &bEngine);
550 if (RT_SUCCESS(rc))
551 switch (bEngine)
552 {
553 case VM_EXEC_ENGINE_NOT_SET: *apenmEngine = VMExecutionEngine_NotSet; break;
554 case VM_EXEC_ENGINE_RAW_MODE: *apenmEngine = VMExecutionEngine_RawMode; break;
555 case VM_EXEC_ENGINE_HW_VIRT: *apenmEngine = VMExecutionEngine_HwVirt; break;
556 case VM_EXEC_ENGINE_NATIVE_API: *apenmEngine = VMExecutionEngine_NativeApi; break;
557 default: AssertMsgFailed(("bEngine=%d\n", bEngine));
558 }
559 }
560
561 return S_OK;
562}
563
564/**
[1]565 * Returns the current hardware virtualization flag.
566 *
567 * @returns COM status code
[65120]568 * @param aHWVirtExEnabled address of result variable
[1]569 */
[51092]570HRESULT MachineDebugger::getHWVirtExEnabled(BOOL *aHWVirtExEnabled)
[1]571{
[72328]572 *aHWVirtExEnabled = false;
573
[25310]574 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[44373]575 Console::SafeVMPtrQuiet ptrVM(mParent);
576 if (ptrVM.isOk())
[72328]577 {
578 uint8_t bEngine = UINT8_MAX;
579 int rc = EMR3QueryMainExecutionEngine(ptrVM.rawUVM(), &bEngine);
580 *aHWVirtExEnabled = RT_SUCCESS(rc) && bEngine == VM_EXEC_ENGINE_HW_VIRT;
581 }
[14627]582
[1]583 return S_OK;
584}
585
586/**
[10695]587 * Returns the current nested paging flag.
588 *
589 * @returns COM status code
[65120]590 * @param aHWVirtExNestedPagingEnabled address of result variable
[10695]591 */
[51092]592HRESULT MachineDebugger::getHWVirtExNestedPagingEnabled(BOOL *aHWVirtExNestedPagingEnabled)
[10695]593{
[25310]594 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[14627]595
[44373]596 Console::SafeVMPtrQuiet ptrVM(mParent);
[14627]597
[44373]598 if (ptrVM.isOk())
[51092]599 *aHWVirtExNestedPagingEnabled = HMR3IsNestedPagingActive(ptrVM.rawUVM());
[10695]600 else
[51092]601 *aHWVirtExNestedPagingEnabled = false;
[14627]602
[10695]603 return S_OK;
604}
605
606/**
[13221]607 * Returns the current VPID flag.
608 *
609 * @returns COM status code
[65120]610 * @param aHWVirtExVPIDEnabled address of result variable
[13221]611 */
[51092]612HRESULT MachineDebugger::getHWVirtExVPIDEnabled(BOOL *aHWVirtExVPIDEnabled)
[13221]613{
[25310]614 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[14627]615
[44373]616 Console::SafeVMPtrQuiet ptrVM(mParent);
[14627]617
[44373]618 if (ptrVM.isOk())
[51092]619 *aHWVirtExVPIDEnabled = HMR3IsVpidActive(ptrVM.rawUVM());
[13221]620 else
[51092]621 *aHWVirtExVPIDEnabled = false;
[14627]622
[13221]623 return S_OK;
624}
625
[45971]626/**
627 * Returns the current unrestricted execution setting.
628 *
629 * @returns COM status code
[65103]630 * @param aHWVirtExUXEnabled address of result variable
[45971]631 */
[51092]632HRESULT MachineDebugger::getHWVirtExUXEnabled(BOOL *aHWVirtExUXEnabled)
[45971]633{
634 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
635
636 Console::SafeVMPtrQuiet ptrVM(mParent);
637
638 if (ptrVM.isOk())
[51092]639 *aHWVirtExUXEnabled = HMR3IsUXActive(ptrVM.rawUVM());
[45971]640 else
[51092]641 *aHWVirtExUXEnabled = false;
[45971]642
643 return S_OK;
644}
645
[51092]646HRESULT MachineDebugger::getOSName(com::Utf8Str &aOSName)
[35250]647{
[35306]648 LogFlowThisFunc(("\n"));
[51092]649 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
650 Console::SafeVMPtr ptrVM(mParent);
651 HRESULT hrc = ptrVM.rc();
[35306]652 if (SUCCEEDED(hrc))
653 {
[51092]654 /*
655 * Do the job and try convert the name.
656 */
657 char szName[64];
658 int vrc = DBGFR3OSQueryNameAndVersion(ptrVM.rawUVM(), szName, sizeof(szName), NULL, 0);
659 if (RT_SUCCESS(vrc))
[35306]660 {
[51092]661 try
[35306]662 {
[51092]663 Bstr bstrName(szName);
664 aOSName = Utf8Str(bstrName);
[35306]665 }
[73505]666 catch (std::bad_alloc &)
[51092]667 {
668 hrc = E_OUTOFMEMORY;
669 }
[35306]670 }
[51092]671 else
[73003]672 hrc = setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("DBGFR3OSQueryNameAndVersion failed with %Rrc"), vrc);
[35306]673 }
674 return hrc;
[35250]675}
676
[51092]677HRESULT MachineDebugger::getOSVersion(com::Utf8Str &aOSVersion)
[35250]678{
[35306]679 LogFlowThisFunc(("\n"));
[51092]680 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
681 Console::SafeVMPtr ptrVM(mParent);
682 HRESULT hrc = ptrVM.rc();
[35306]683 if (SUCCEEDED(hrc))
684 {
[51092]685 /*
686 * Do the job and try convert the name.
687 */
688 char szVersion[256];
689 int vrc = DBGFR3OSQueryNameAndVersion(ptrVM.rawUVM(), NULL, 0, szVersion, sizeof(szVersion));
690 if (RT_SUCCESS(vrc))
[35306]691 {
[51092]692 try
[35306]693 {
[51092]694 Bstr bstrVersion(szVersion);
695 aOSVersion = Utf8Str(bstrVersion);
[35306]696 }
[73505]697 catch (std::bad_alloc &)
[51092]698 {
699 hrc = E_OUTOFMEMORY;
700 }
[35306]701 }
[51092]702 else
[73003]703 hrc = setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("DBGFR3OSQueryNameAndVersion failed with %Rrc"), vrc);
[35306]704 }
705 return hrc;
[35250]706}
707
[13221]708/**
[7990]709 * Returns the current PAE flag.
710 *
711 * @returns COM status code
[65103]712 * @param aPAEEnabled address of result variable.
[7990]713 */
[51092]714HRESULT MachineDebugger::getPAEEnabled(BOOL *aPAEEnabled)
[7990]715{
[25310]716 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[14627]717
[44347]718 Console::SafeVMPtrQuiet ptrVM(mParent);
[14627]719
[44347]720 if (ptrVM.isOk())
[7990]721 {
[44347]722 uint32_t cr4;
[44399]723 int rc = DBGFR3RegCpuQueryU32(ptrVM.rawUVM(), 0 /*idCpu*/, DBGFREG_CR4, &cr4); AssertRC(rc);
[51092]724 *aPAEEnabled = RT_BOOL(cr4 & X86_CR4_PAE);
[7990]725 }
726 else
[51092]727 *aPAEEnabled = false;
[14627]728
[7990]729 return S_OK;
730}
731
732/**
[444]733 * Returns the current virtual time rate.
[5190]734 *
[444]735 * @returns COM status code.
[65103]736 * @param aVirtualTimeRate Where to store the rate.
[444]737 */
[51092]738HRESULT MachineDebugger::getVirtualTimeRate(ULONG *aVirtualTimeRate)
[444]739{
[51092]740 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[444]741
[51092]742 Console::SafeVMPtr ptrVM(mParent);
743 HRESULT hrc = ptrVM.rc();
[39712]744 if (SUCCEEDED(hrc))
[51092]745 *aVirtualTimeRate = TMR3GetWarpDrive(ptrVM.rawUVM());
[444]746
[39712]747 return hrc;
[444]748}
749
750/**
[65103]751 * Set the virtual time rate.
[5190]752 *
[444]753 * @returns COM status code.
[65103]754 * @param aVirtualTimeRate The new rate.
[444]755 */
[51092]756HRESULT MachineDebugger::setVirtualTimeRate(ULONG aVirtualTimeRate)
[444]757{
[51092]758 HRESULT hrc = S_OK;
[444]759
[51092]760 if (aVirtualTimeRate < 2 || aVirtualTimeRate > 20000)
761 return setError(E_INVALIDARG, tr("%u is out of range [2..20000]"), aVirtualTimeRate);
762
763 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
764 if (i_queueSettings())
765 mVirtualTimeRateQueued = aVirtualTimeRate;
766 else
[444]767 {
[51092]768 Console::SafeVMPtr ptrVM(mParent);
769 hrc = ptrVM.rc();
770 if (SUCCEEDED(hrc))
[39712]771 {
[51092]772 int vrc = TMR3SetWarpDrive(ptrVM.rawUVM(), aVirtualTimeRate);
773 if (RT_FAILURE(vrc))
[73003]774 hrc = setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("TMR3SetWarpDrive(, %u) failed with rc=%Rrc"), aVirtualTimeRate, vrc);
[39712]775 }
[444]776 }
777
[39712]778 return hrc;
[444]779}
780
781/**
[44340]782 * Hack for getting the user mode VM handle (UVM).
[39712]783 *
[1]784 * This is only temporary (promise) while prototyping the debugger.
785 *
786 * @returns COM status code
[62598]787 * @param aVM Where to store the vm handle. Since there is no
[39712]788 * uintptr_t in COM, we're using the max integer.
789 * (No, ULONG is not pointer sized!)
[44340]790 * @remarks The returned handle must be passed to VMR3ReleaseUVM()!
791 * @remarks Prior to 4.3 this returned PVM.
[1]792 */
[51092]793HRESULT MachineDebugger::getVM(LONG64 *aVM)
[1]794{
[51092]795 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]796
[51092]797 Console::SafeVMPtr ptrVM(mParent);
798 HRESULT hrc = ptrVM.rc();
[39712]799 if (SUCCEEDED(hrc))
800 {
[51092]801 VMR3RetainUVM(ptrVM.rawUVM());
802 *aVM = (intptr_t)ptrVM.rawUVM();
[39712]803 }
[1]804
[51092]805 /*
806 * Note! ptrVM protection provided by SafeVMPtr is no long effective
807 * after we return from this method.
808 */
[39712]809 return hrc;
[1]810}
811
[62598]812/**
813 * Get the VM uptime in milliseconds.
814 *
815 * @returns COM status code
816 * @param aUptime Where to store the uptime.
817 */
818HRESULT MachineDebugger::getUptime(LONG64 *aUptime)
819{
820 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
821
822 Console::SafeVMPtr ptrVM(mParent);
823 HRESULT hrc = ptrVM.rc();
824 if (SUCCEEDED(hrc))
825 *aUptime = (int64_t)TMR3TimeVirtGetMilli(ptrVM.rawUVM());
826
827 return hrc;
828}
829
[14627]830// IMachineDebugger methods
831/////////////////////////////////////////////////////////////////////////////
832
[51092]833HRESULT MachineDebugger::dumpGuestCore(const com::Utf8Str &aFilename, const com::Utf8Str &aCompression)
[35242]834{
[51092]835 if (aCompression.length())
[35242]836 return setError(E_INVALIDARG, tr("The compression parameter must be empty"));
837
[51092]838 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
839 Console::SafeVMPtr ptrVM(mParent);
840 HRESULT hrc = ptrVM.rc();
[35242]841 if (SUCCEEDED(hrc))
842 {
[51092]843 int vrc = DBGFR3CoreWrite(ptrVM.rawUVM(), aFilename.c_str(), false /*fReplaceFile*/);
844 if (RT_SUCCESS(vrc))
845 hrc = S_OK;
846 else
[73003]847 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3CoreWrite failed with %Rrc"), vrc);
[35242]848 }
849
850 return hrc;
851}
852
[51092]853HRESULT MachineDebugger::dumpHostProcessCore(const com::Utf8Str &aFilename, const com::Utf8Str &aCompression)
[35242]854{
[63244]855 RT_NOREF(aFilename, aCompression);
[35242]856 ReturnComNotImplemented();
857}
858
[35306]859/**
860 * Debug info string buffer formatter.
861 */
862typedef struct MACHINEDEBUGGERINOFHLP
863{
864 /** The core info helper structure. */
865 DBGFINFOHLP Core;
866 /** Pointer to the buffer. */
867 char *pszBuf;
868 /** The size of the buffer. */
869 size_t cbBuf;
870 /** The offset into the buffer */
871 size_t offBuf;
872 /** Indicates an out-of-memory condition. */
873 bool fOutOfMemory;
874} MACHINEDEBUGGERINOFHLP;
875/** Pointer to a Debug info string buffer formatter. */
876typedef MACHINEDEBUGGERINOFHLP *PMACHINEDEBUGGERINOFHLP;
877
878
879/**
880 * @callback_method_impl{FNRTSTROUTPUT}
881 */
882static DECLCALLBACK(size_t) MachineDebuggerInfoOutput(void *pvArg, const char *pachChars, size_t cbChars)
883{
884 PMACHINEDEBUGGERINOFHLP pHlp = (PMACHINEDEBUGGERINOFHLP)pvArg;
885
886 /*
887 * Grow the buffer if required.
888 */
889 size_t const cbRequired = cbChars + pHlp->offBuf + 1;
890 if (cbRequired > pHlp->cbBuf)
891 {
892 if (RT_UNLIKELY(pHlp->fOutOfMemory))
893 return 0;
894
895 size_t cbBufNew = pHlp->cbBuf * 2;
896 if (cbRequired > cbBufNew)
897 cbBufNew = RT_ALIGN_Z(cbRequired, 256);
898 void *pvBufNew = RTMemRealloc(pHlp->pszBuf, cbBufNew);
899 if (RT_UNLIKELY(!pvBufNew))
900 {
901 pHlp->fOutOfMemory = true;
902 RTMemFree(pHlp->pszBuf);
903 pHlp->pszBuf = NULL;
904 pHlp->cbBuf = 0;
905 pHlp->offBuf = 0;
906 return 0;
907 }
908
909 pHlp->pszBuf = (char *)pvBufNew;
910 pHlp->cbBuf = cbBufNew;
911 }
912
913 /*
914 * Copy the bytes into the buffer and terminate it.
915 */
[65550]916 if (cbChars)
917 {
918 memcpy(&pHlp->pszBuf[pHlp->offBuf], pachChars, cbChars);
919 pHlp->offBuf += cbChars;
920 }
[35306]921 pHlp->pszBuf[pHlp->offBuf] = '\0';
922 Assert(pHlp->offBuf < pHlp->cbBuf);
923 return cbChars;
924}
925
926/**
[58132]927 * @interface_method_impl{DBGFINFOHLP,pfnPrintfV}
[35306]928 */
[65088]929static DECLCALLBACK(void) MachineDebuggerInfoPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
[35306]930{
[65088]931 RTStrFormatV(MachineDebuggerInfoOutput, (void *)pHlp, NULL, NULL, pszFormat, args);
[35306]932}
933
934/**
[58132]935 * @interface_method_impl{DBGFINFOHLP,pfnPrintf}
[35306]936 */
937static DECLCALLBACK(void) MachineDebuggerInfoPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
938{
939 va_list va;
940 va_start(va, pszFormat);
941 MachineDebuggerInfoPrintfV(pHlp, pszFormat, va);
942 va_end(va);
943}
944
945/**
946 * Initializes the debug info string buffer formatter
947 *
948 * @param pHlp The help structure to init.
949 */
950static void MachineDebuggerInfoInit(PMACHINEDEBUGGERINOFHLP pHlp)
951{
952 pHlp->Core.pfnPrintf = MachineDebuggerInfoPrintf;
953 pHlp->Core.pfnPrintfV = MachineDebuggerInfoPrintfV;
954 pHlp->pszBuf = NULL;
955 pHlp->cbBuf = 0;
956 pHlp->offBuf = 0;
957 pHlp->fOutOfMemory = false;
958}
959
960/**
961 * Deletes the debug info string buffer formatter.
962 * @param pHlp The helper structure to delete.
963 */
964static void MachineDebuggerInfoDelete(PMACHINEDEBUGGERINOFHLP pHlp)
965{
966 RTMemFree(pHlp->pszBuf);
967 pHlp->pszBuf = NULL;
968}
969
[51092]970HRESULT MachineDebugger::info(const com::Utf8Str &aName, const com::Utf8Str &aArgs, com::Utf8Str &aInfo)
[35242]971{
[35306]972 LogFlowThisFunc(("\n"));
973
974 /*
975 * Do the autocaller and lock bits.
976 */
977 AutoCaller autoCaller(this);
978 HRESULT hrc = autoCaller.rc();
979 if (SUCCEEDED(hrc))
980 {
981 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
982 Console::SafeVMPtr ptrVM(mParent);
983 hrc = ptrVM.rc();
984 if (SUCCEEDED(hrc))
985 {
986 /*
987 * Create a helper and call DBGFR3Info.
988 */
989 MACHINEDEBUGGERINOFHLP Hlp;
990 MachineDebuggerInfoInit(&Hlp);
[51092]991 int vrc = DBGFR3Info(ptrVM.rawUVM(), aName.c_str(), aArgs.c_str(), &Hlp.Core);
[35306]992 if (RT_SUCCESS(vrc))
993 {
994 if (!Hlp.fOutOfMemory)
995 {
996 /*
997 * Convert the info string, watching out for allocation errors.
998 */
999 try
1000 {
1001 Bstr bstrInfo(Hlp.pszBuf);
[51092]1002 aInfo = bstrInfo;
[35306]1003 }
[73505]1004 catch (std::bad_alloc &)
[35306]1005 {
1006 hrc = E_OUTOFMEMORY;
1007 }
1008 }
1009 else
1010 hrc = E_OUTOFMEMORY;
1011 }
1012 else
[73003]1013 hrc = setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("DBGFR3Info failed with %Rrc"), vrc);
[35306]1014 MachineDebuggerInfoDelete(&Hlp);
1015 }
1016 }
1017 return hrc;
[35242]1018}
1019
[51092]1020HRESULT MachineDebugger::injectNMI()
[35242]1021{
1022 LogFlowThisFunc(("\n"));
1023
[51092]1024 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1025 Console::SafeVMPtr ptrVM(mParent);
1026 HRESULT hrc = ptrVM.rc();
[35242]1027 if (SUCCEEDED(hrc))
1028 {
[51092]1029 int vrc = DBGFR3InjectNMI(ptrVM.rawUVM(), 0);
1030 if (RT_SUCCESS(vrc))
1031 hrc = S_OK;
1032 else
[73003]1033 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3InjectNMI failed with %Rrc"), vrc);
[35242]1034 }
1035 return hrc;
1036}
1037
[51092]1038HRESULT MachineDebugger::modifyLogFlags(const com::Utf8Str &aSettings)
[35250]1039{
[51092]1040 LogFlowThisFunc(("aSettings=%s\n", aSettings.c_str()));
1041 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1042 Console::SafeVMPtr ptrVM(mParent);
1043 HRESULT hrc = ptrVM.rc();
[39650]1044 if (SUCCEEDED(hrc))
1045 {
[51092]1046 int vrc = DBGFR3LogModifyFlags(ptrVM.rawUVM(), aSettings.c_str());
1047 if (RT_SUCCESS(vrc))
1048 hrc = S_OK;
1049 else
[73003]1050 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3LogModifyFlags failed with %Rrc"), vrc);
[39650]1051 }
1052 return hrc;
[35250]1053}
1054
[51092]1055HRESULT MachineDebugger::modifyLogGroups(const com::Utf8Str &aSettings)
[35250]1056{
[51092]1057 LogFlowThisFunc(("aSettings=%s\n", aSettings.c_str()));
1058 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1059 Console::SafeVMPtr ptrVM(mParent);
1060 HRESULT hrc = ptrVM.rc();
[39650]1061 if (SUCCEEDED(hrc))
1062 {
[51092]1063 int vrc = DBGFR3LogModifyGroups(ptrVM.rawUVM(), aSettings.c_str());
1064 if (RT_SUCCESS(vrc))
1065 hrc = S_OK;
1066 else
[73003]1067 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3LogModifyGroups failed with %Rrc"), vrc);
[39650]1068 }
1069 return hrc;
[35250]1070}
1071
[51092]1072HRESULT MachineDebugger::modifyLogDestinations(const com::Utf8Str &aSettings)
[35250]1073{
[51092]1074 LogFlowThisFunc(("aSettings=%s\n", aSettings.c_str()));
1075 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1076 Console::SafeVMPtr ptrVM(mParent);
1077 HRESULT hrc = ptrVM.rc();
[39650]1078 if (SUCCEEDED(hrc))
1079 {
[51092]1080 int vrc = DBGFR3LogModifyDestinations(ptrVM.rawUVM(), aSettings.c_str());
1081 if (RT_SUCCESS(vrc))
1082 hrc = S_OK;
1083 else
[73003]1084 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3LogModifyDestinations failed with %Rrc"), vrc);
[39650]1085 }
1086 return hrc;
[35250]1087}
1088
[51092]1089HRESULT MachineDebugger::readPhysicalMemory(LONG64 aAddress, ULONG aSize, std::vector<BYTE> &aBytes)
[35242]1090{
[63244]1091 RT_NOREF(aAddress, aSize, aBytes);
[35242]1092 ReturnComNotImplemented();
1093}
1094
[51092]1095HRESULT MachineDebugger::writePhysicalMemory(LONG64 aAddress, ULONG aSize, const std::vector<BYTE> &aBytes)
[35242]1096{
[63244]1097 RT_NOREF(aAddress, aSize, aBytes);
[35242]1098 ReturnComNotImplemented();
1099}
1100
[51092]1101HRESULT MachineDebugger::readVirtualMemory(ULONG aCpuId, LONG64 aAddress, ULONG aSize, std::vector<BYTE> &aBytes)
[35242]1102{
[63244]1103 RT_NOREF(aCpuId, aAddress, aSize, aBytes);
[35242]1104 ReturnComNotImplemented();
1105}
1106
[51092]1107HRESULT MachineDebugger::writeVirtualMemory(ULONG aCpuId, LONG64 aAddress, ULONG aSize, const std::vector<BYTE> &aBytes)
[35242]1108{
[63244]1109 RT_NOREF(aCpuId, aAddress, aSize, aBytes);
[35242]1110 ReturnComNotImplemented();
1111}
1112
[55883]1113HRESULT MachineDebugger::loadPlugIn(const com::Utf8Str &aName, com::Utf8Str &aPlugInName)
1114{
1115 /*
1116 * Lock the debugger and get the VM pointer
1117 */
1118 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1119 Console::SafeVMPtr ptrVM(mParent);
1120 HRESULT hrc = ptrVM.rc();
1121 if (SUCCEEDED(hrc))
1122 {
1123 /*
1124 * Do the job and try convert the name.
1125 */
1126 if (aName.equals("all"))
1127 {
1128 DBGFR3PlugInLoadAll(ptrVM.rawUVM());
1129 try
1130 {
1131 aPlugInName = "all";
1132 hrc = S_OK;
1133 }
[73505]1134 catch (std::bad_alloc &)
[55883]1135 {
1136 hrc = E_OUTOFMEMORY;
1137 }
1138 }
1139 else
1140 {
1141 RTERRINFOSTATIC ErrInfo;
1142 char szName[80];
1143 int vrc = DBGFR3PlugInLoad(ptrVM.rawUVM(), aName.c_str(), szName, sizeof(szName), RTErrInfoInitStatic(&ErrInfo));
1144 if (RT_SUCCESS(vrc))
1145 {
1146 try
1147 {
[61349]1148 aPlugInName = szName;
[55883]1149 hrc = S_OK;
1150 }
[73505]1151 catch (std::bad_alloc &)
[55883]1152 {
1153 hrc = E_OUTOFMEMORY;
1154 }
1155 }
1156 else
1157 hrc = setErrorVrc(vrc, "%s", ErrInfo.szMsg);
1158 }
1159 }
1160 return hrc;
1161
1162}
1163
1164HRESULT MachineDebugger::unloadPlugIn(const com::Utf8Str &aName)
1165{
1166 /*
1167 * Lock the debugger and get the VM pointer
1168 */
1169 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1170 Console::SafeVMPtr ptrVM(mParent);
1171 HRESULT hrc = ptrVM.rc();
1172 if (SUCCEEDED(hrc))
1173 {
1174 /*
1175 * Do the job and try convert the name.
1176 */
1177 if (aName.equals("all"))
1178 {
1179 DBGFR3PlugInUnloadAll(ptrVM.rawUVM());
1180 hrc = S_OK;
1181 }
1182 else
1183 {
1184 int vrc = DBGFR3PlugInUnload(ptrVM.rawUVM(), aName.c_str());
1185 if (RT_SUCCESS(vrc))
1186 hrc = S_OK;
1187 else if (vrc == VERR_NOT_FOUND)
1188 hrc = setErrorBoth(E_FAIL, vrc, "Plug-in '%s' was not found", aName.c_str());
1189 else
1190 hrc = setErrorVrc(vrc, "Error unloading '%s': %Rrc", aName.c_str(), vrc);
1191 }
1192 }
1193 return hrc;
1194
1195}
1196
[51092]1197HRESULT MachineDebugger::detectOS(com::Utf8Str &aOs)
[35250]1198{
[35306]1199 LogFlowThisFunc(("\n"));
1200
1201 /*
[55883]1202 * Lock the debugger and get the VM pointer
[35306]1203 */
[51092]1204 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1205 Console::SafeVMPtr ptrVM(mParent);
1206 HRESULT hrc = ptrVM.rc();
[35306]1207 if (SUCCEEDED(hrc))
1208 {
[51092]1209 /*
[55883]1210 * Do the job.
[51092]1211 */
1212 char szName[64];
1213 int vrc = DBGFR3OSDetect(ptrVM.rawUVM(), szName, sizeof(szName));
1214 if (RT_SUCCESS(vrc) && vrc != VINF_DBGF_OS_NOT_DETCTED)
[35306]1215 {
[51092]1216 try
[35306]1217 {
[55883]1218 aOs = szName;
[35306]1219 }
[73505]1220 catch (std::bad_alloc &)
[51092]1221 {
1222 hrc = E_OUTOFMEMORY;
1223 }
[35306]1224 }
[51092]1225 else
[73003]1226 hrc = setErrorBoth(VBOX_E_VM_ERROR, vrc, tr("DBGFR3OSDetect failed with %Rrc"), vrc);
[35306]1227 }
1228 return hrc;
[35250]1229}
1230
[55885]1231HRESULT MachineDebugger::queryOSKernelLog(ULONG aMaxMessages, com::Utf8Str &aDmesg)
1232{
1233 /*
1234 * Lock the debugger and get the VM pointer
1235 */
1236 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1237 Console::SafeVMPtr ptrVM(mParent);
1238 HRESULT hrc = ptrVM.rc();
1239 if (SUCCEEDED(hrc))
1240 {
1241 PDBGFOSIDMESG pDmesg = (PDBGFOSIDMESG)DBGFR3OSQueryInterface(ptrVM.rawUVM(), DBGFOSINTERFACE_DMESG);
1242 if (pDmesg)
1243 {
1244 size_t cbActual;
1245 size_t cbBuf = _512K;
1246 int vrc = aDmesg.reserveNoThrow(cbBuf);
1247 if (RT_SUCCESS(vrc))
1248 {
1249 uint32_t cMessages = aMaxMessages == 0 ? UINT32_MAX : aMaxMessages;
1250 vrc = pDmesg->pfnQueryKernelLog(pDmesg, ptrVM.rawUVM(), 0 /*fFlags*/, cMessages,
1251 aDmesg.mutableRaw(), cbBuf, &cbActual);
1252
1253 uint32_t cTries = 10;
1254 while (vrc == VERR_BUFFER_OVERFLOW && cbBuf < 16*_1M && cTries-- > 0)
1255 {
1256 cbBuf = RT_ALIGN_Z(cbActual + _4K, _4K);
[55996]1257 vrc = aDmesg.reserveNoThrow(cbBuf);
[55885]1258 if (RT_SUCCESS(vrc))
1259 vrc = pDmesg->pfnQueryKernelLog(pDmesg, ptrVM.rawUVM(), 0 /*fFlags*/, cMessages,
1260 aDmesg.mutableRaw(), cbBuf, &cbActual);
1261 }
1262 if (RT_SUCCESS(vrc))
1263 aDmesg.jolt();
1264 else if (vrc == VERR_BUFFER_OVERFLOW)
1265 hrc = setError(E_FAIL, "Too much log available, must use the maxMessages parameter to restrict.");
1266 else
1267 hrc = setErrorVrc(vrc);
1268 }
1269 else
1270 hrc = setErrorBoth(E_OUTOFMEMORY, vrc);
1271 }
1272 else
1273 hrc = setError(E_FAIL, "The dmesg interface isn't implemented by guest OS digger, or detectOS() has not been called.");
1274 }
1275 return hrc;
1276}
1277
[35502]1278/**
1279 * Formats a register value.
1280 *
1281 * This is used by both register getter methods.
1282 *
1283 * @returns
1284 * @param a_pbstr The output Bstr variable.
1285 * @param a_pValue The value to format.
1286 * @param a_enmType The type of the value.
1287 */
[35586]1288DECLINLINE(HRESULT) formatRegisterValue(Bstr *a_pbstr, PCDBGFREGVAL a_pValue, DBGFREGVALTYPE a_enmType)
[35502]1289{
[35586]1290 char szHex[160];
1291 ssize_t cch = DBGFR3RegFormatValue(szHex, sizeof(szHex), a_pValue, a_enmType, true /*fSpecial*/);
1292 if (RT_UNLIKELY(cch <= 0))
1293 return E_UNEXPECTED;
1294 *a_pbstr = szHex;
1295 return S_OK;
[35502]1296}
1297
[51092]1298HRESULT MachineDebugger::getRegister(ULONG aCpuId, const com::Utf8Str &aName, com::Utf8Str &aValue)
[35242]1299{
[35502]1300 /*
1301 * The prologue.
1302 */
1303 LogFlowThisFunc(("\n"));
[51092]1304 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1305 Console::SafeVMPtr ptrVM(mParent);
1306 HRESULT hrc = ptrVM.rc();
[35502]1307 if (SUCCEEDED(hrc))
1308 {
[51092]1309 /*
1310 * Real work.
1311 */
1312 DBGFREGVAL Value;
1313 DBGFREGVALTYPE enmType;
1314 int vrc = DBGFR3RegNmQuery(ptrVM.rawUVM(), aCpuId, aName.c_str(), &Value, &enmType);
1315 if (RT_SUCCESS(vrc))
[35502]1316 {
[51092]1317 try
[35502]1318 {
[51092]1319 Bstr bstrValue;
1320 hrc = formatRegisterValue(&bstrValue, &Value, enmType);
1321 if (SUCCEEDED(hrc))
1322 aValue = Utf8Str(bstrValue);
[35502]1323 }
[73505]1324 catch (std::bad_alloc &)
[51092]1325 {
1326 hrc = E_OUTOFMEMORY;
1327 }
[35502]1328 }
[51092]1329 else if (vrc == VERR_DBGF_REGISTER_NOT_FOUND)
[73003]1330 hrc = setErrorBoth(E_FAIL, vrc, tr("Register '%s' was not found"), aName.c_str());
[51092]1331 else if (vrc == VERR_INVALID_CPU_ID)
[73003]1332 hrc = setErrorBoth(E_FAIL, vrc, tr("Invalid CPU ID: %u"), aCpuId);
[51092]1333 else
[73003]1334 hrc = setErrorBoth(VBOX_E_VM_ERROR, vrc,
1335 tr("DBGFR3RegNmQuery failed with rc=%Rrc querying register '%s' with default cpu set to %u"),
1336 vrc, aName.c_str(), aCpuId);
[35502]1337 }
1338
1339 return hrc;
[35242]1340}
1341
[51092]1342HRESULT MachineDebugger::getRegisters(ULONG aCpuId, std::vector<com::Utf8Str> &aNames, std::vector<com::Utf8Str> &aValues)
[35242]1343{
[63244]1344 RT_NOREF(aCpuId); /** @todo fix missing aCpuId usage! */
1345
[35312]1346 /*
1347 * The prologue.
1348 */
1349 LogFlowThisFunc(("\n"));
[51092]1350 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1351 Console::SafeVMPtr ptrVM(mParent);
1352 HRESULT hrc = ptrVM.rc();
[35312]1353 if (SUCCEEDED(hrc))
1354 {
[51092]1355 /*
1356 * Real work.
1357 */
1358 size_t cRegs;
1359 int vrc = DBGFR3RegNmQueryAllCount(ptrVM.rawUVM(), &cRegs);
1360 if (RT_SUCCESS(vrc))
[35312]1361 {
[51092]1362 PDBGFREGENTRYNM paRegs = (PDBGFREGENTRYNM)RTMemAllocZ(sizeof(paRegs[0]) * cRegs);
1363 if (paRegs)
[35312]1364 {
[51092]1365 vrc = DBGFR3RegNmQueryAll(ptrVM.rawUVM(), paRegs, cRegs);
1366 if (RT_SUCCESS(vrc))
[35312]1367 {
[51092]1368 try
[35312]1369 {
[55702]1370 aValues.resize(cRegs);
1371 aNames.resize(cRegs);
[51092]1372 for (uint32_t iReg = 0; iReg < cRegs; iReg++)
[35550]1373 {
[55702]1374 char szHex[160];
1375 szHex[159] = szHex[0] = '\0';
1376 ssize_t cch = DBGFR3RegFormatValue(szHex, sizeof(szHex), &paRegs[iReg].Val,
1377 paRegs[iReg].enmType, true /*fSpecial*/);
[62379]1378 Assert(cch > 0); NOREF(cch);
[51092]1379 aNames[iReg] = Utf8Str(paRegs[iReg].pszName);
[55702]1380 aValues[iReg] = Utf8Str(szHex);
[35550]1381 }
[35312]1382 }
[73505]1383 catch (std::bad_alloc &)
[51092]1384 {
1385 hrc = E_OUTOFMEMORY;
1386 }
[35312]1387 }
[35550]1388 else
[73003]1389 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3RegNmQueryAll failed with %Rrc"), vrc);
[51092]1390
1391 RTMemFree(paRegs);
[35312]1392 }
1393 else
[51092]1394 hrc = E_OUTOFMEMORY;
[35312]1395 }
[51092]1396 else
[73003]1397 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3RegNmQueryAllCount failed with %Rrc"), vrc);
[35312]1398 }
1399 return hrc;
[35242]1400}
1401
[51092]1402HRESULT MachineDebugger::setRegister(ULONG aCpuId, const com::Utf8Str &aName, const com::Utf8Str &aValue)
[35242]1403{
[63244]1404 RT_NOREF(aCpuId, aName, aValue);
[35242]1405 ReturnComNotImplemented();
1406}
1407
[51092]1408HRESULT MachineDebugger::setRegisters(ULONG aCpuId, const std::vector<com::Utf8Str> &aNames,
1409 const std::vector<com::Utf8Str> &aValues)
[35242]1410{
[63244]1411 RT_NOREF(aCpuId, aNames, aValues);
[35242]1412 ReturnComNotImplemented();
1413}
1414
[51092]1415HRESULT MachineDebugger::dumpGuestStack(ULONG aCpuId, com::Utf8Str &aStack)
[35250]1416{
[61561]1417 /*
1418 * The prologue.
1419 */
1420 LogFlowThisFunc(("\n"));
1421 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1422 Console::SafeVMPtr ptrVM(mParent);
1423 HRESULT hrc = ptrVM.rc();
1424 if (SUCCEEDED(hrc))
1425 {
[61935]1426 /*
1427 * There is currently a problem with the windows diggers and SMP, where
1428 * guest driver memory is being read from CPU zero in order to ensure that
1429 * we've got a consisten virtual memory view. If one of the other CPUs
1430 * initiates a rendezvous while we're unwinding the stack and trying to
1431 * read guest driver memory, we will deadlock.
1432 *
1433 * So, check the VM state and maybe suspend the VM before we continue.
1434 */
1435 int vrc = VINF_SUCCESS;
1436 bool fPaused = false;
1437 if (aCpuId != 0)
1438 {
1439 VMSTATE enmVmState = VMR3GetStateU(ptrVM.rawUVM());
1440 if ( enmVmState == VMSTATE_RUNNING
1441 || enmVmState == VMSTATE_RUNNING_LS
1442 || enmVmState == VMSTATE_RUNNING_FT)
1443 {
1444 alock.release();
1445 vrc = VMR3Suspend(ptrVM.rawUVM(), VMSUSPENDREASON_USER);
1446 alock.acquire();
1447 fPaused = RT_SUCCESS(vrc);
1448 }
1449 }
[61561]1450 if (RT_SUCCESS(vrc))
1451 {
[61786]1452 PCDBGFSTACKFRAME pFirstFrame;
1453 vrc = DBGFR3StackWalkBegin(ptrVM.rawUVM(), aCpuId, DBGFCODETYPE_GUEST, &pFirstFrame);
1454 if (RT_SUCCESS(vrc))
[61561]1455 {
[61786]1456 /*
1457 * Print header.
1458 */
1459 try
[61561]1460 {
[61786]1461 uint32_t fBitFlags = 0;
1462 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
1463 pFrame;
1464 pFrame = DBGFR3StackWalkNext(pFrame))
[61561]1465 {
[61786]1466 uint32_t const fCurBitFlags = pFrame->fFlags & (DBGFSTACKFRAME_FLAGS_16BIT | DBGFSTACKFRAME_FLAGS_32BIT | DBGFSTACKFRAME_FLAGS_64BIT);
1467 if (fCurBitFlags & DBGFSTACKFRAME_FLAGS_16BIT)
1468 {
1469 if (fCurBitFlags != fBitFlags)
1470 aStack.append("SS:BP Ret SS:BP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP / Symbol [line]\n");
1471 aStack.append(Utf8StrFmt("%04RX16:%04RX16 %04RX16:%04RX16 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
1472 pFrame->AddrFrame.Sel,
1473 (uint16_t)pFrame->AddrFrame.off,
1474 pFrame->AddrReturnFrame.Sel,
1475 (uint16_t)pFrame->AddrReturnFrame.off,
1476 (uint32_t)pFrame->AddrReturnPC.Sel,
1477 (uint32_t)pFrame->AddrReturnPC.off,
1478 pFrame->Args.au32[0],
1479 pFrame->Args.au32[1],
1480 pFrame->Args.au32[2],
1481 pFrame->Args.au32[3]));
1482 }
1483 else if (fCurBitFlags & DBGFSTACKFRAME_FLAGS_32BIT)
1484 {
1485 if (fCurBitFlags != fBitFlags)
1486 aStack.append("EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP / Symbol [line]\n");
1487 aStack.append(Utf8StrFmt("%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
1488 (uint32_t)pFrame->AddrFrame.off,
1489 (uint32_t)pFrame->AddrReturnFrame.off,
1490 (uint32_t)pFrame->AddrReturnPC.Sel,
1491 (uint32_t)pFrame->AddrReturnPC.off,
1492 pFrame->Args.au32[0],
1493 pFrame->Args.au32[1],
1494 pFrame->Args.au32[2],
1495 pFrame->Args.au32[3]));
1496 }
1497 else if (fCurBitFlags & DBGFSTACKFRAME_FLAGS_64BIT)
1498 {
1499 if (fCurBitFlags != fBitFlags)
1500 aStack.append("RBP Ret SS:RBP Ret RIP CS:RIP / Symbol [line]\n");
1501 aStack.append(Utf8StrFmt("%016RX64 %04RX16:%016RX64 %016RX64",
1502 (uint64_t)pFrame->AddrFrame.off,
1503 pFrame->AddrReturnFrame.Sel,
1504 (uint64_t)pFrame->AddrReturnFrame.off,
1505 (uint64_t)pFrame->AddrReturnPC.off));
1506 }
[61561]1507
[61786]1508 if (!pFrame->pSymPC)
1509 aStack.append(Utf8StrFmt(fCurBitFlags & DBGFSTACKFRAME_FLAGS_64BIT
1510 ? " %RTsel:%016RGv"
1511 : fCurBitFlags & DBGFSTACKFRAME_FLAGS_32BIT
1512 ? " %RTsel:%08RGv"
1513 : " %RTsel:%04RGv"
1514 , pFrame->AddrPC.Sel, pFrame->AddrPC.off));
[61561]1515 else
[61786]1516 {
1517 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value; /** @todo this isn't 100% correct for segmented stuff. */
1518 if (offDisp > 0)
1519 aStack.append(Utf8StrFmt(" %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp));
1520 else if (offDisp < 0)
1521 aStack.append(Utf8StrFmt(" %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp));
1522 else
1523 aStack.append(Utf8StrFmt(" %s", pFrame->pSymPC->szName));
1524 }
1525 if (pFrame->pLinePC)
1526 aStack.append(Utf8StrFmt(" [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo));
1527 aStack.append(Utf8StrFmt("\n"));
1528
1529 fBitFlags = fCurBitFlags;
[61561]1530 }
[61786]1531 }
[73505]1532 catch (std::bad_alloc &)
[61786]1533 {
1534 hrc = E_OUTOFMEMORY;
1535 }
[61561]1536
[61786]1537 DBGFR3StackWalkEnd(pFirstFrame);
[61561]1538 }
[61786]1539 else
[73003]1540 hrc = setErrorBoth(E_FAIL, vrc, tr("DBGFR3StackWalkBegin failed with %Rrc"), vrc);
[61561]1541
[61935]1542 /*
1543 * Resume the VM if we suspended it.
1544 */
1545 if (fPaused)
1546 {
1547 alock.release();
1548 VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_USER);
1549 }
[61561]1550 }
1551 else
[73003]1552 hrc = setErrorBoth(E_FAIL, vrc, tr("Suspending the VM failed with %Rrc\n"), vrc);
[61561]1553 }
1554
1555 return hrc;
[35250]1556}
1557
[14627]1558/**
1559 * Resets VM statistics.
1560 *
1561 * @returns COM status code.
1562 * @param aPattern The selection pattern. A bit similar to filename globbing.
1563 */
[51092]1564HRESULT MachineDebugger::resetStats(const com::Utf8Str &aPattern)
[14627]1565{
[44347]1566 Console::SafeVMPtrQuiet ptrVM(mParent);
[14627]1567
[44347]1568 if (!ptrVM.isOk())
[26154]1569 return setError(VBOX_E_INVALID_VM_STATE, "Machine is not running");
[14627]1570
[51092]1571 STAMR3Reset(ptrVM.rawUVM(), aPattern.c_str());
[15827]1572
[14627]1573 return S_OK;
1574}
1575
1576/**
1577 * Dumps VM statistics to the log.
1578 *
1579 * @returns COM status code.
1580 * @param aPattern The selection pattern. A bit similar to filename globbing.
1581 */
[51092]1582HRESULT MachineDebugger::dumpStats(const com::Utf8Str &aPattern)
[14627]1583{
[44347]1584 Console::SafeVMPtrQuiet ptrVM(mParent);
[14627]1585
[44347]1586 if (!ptrVM.isOk())
[26154]1587 return setError(VBOX_E_INVALID_VM_STATE, "Machine is not running");
[14627]1588
[51092]1589 STAMR3Dump(ptrVM.rawUVM(), aPattern.c_str());
[15827]1590
[14627]1591 return S_OK;
1592}
1593
1594/**
1595 * Get the VM statistics in an XML format.
1596 *
1597 * @returns COM status code.
1598 * @param aPattern The selection pattern. A bit similar to filename globbing.
1599 * @param aWithDescriptions Whether to include the descriptions.
1600 * @param aStats The XML document containing the statistics.
1601 */
[51092]1602HRESULT MachineDebugger::getStats(const com::Utf8Str &aPattern, BOOL aWithDescriptions, com::Utf8Str &aStats)
[14627]1603{
[62598]1604 Console::SafeVMPtrQuiet ptrVM(mParent);
[14627]1605
[44347]1606 if (!ptrVM.isOk())
[26154]1607 return setError(VBOX_E_INVALID_VM_STATE, "Machine is not running");
[14627]1608
1609 char *pszSnapshot;
[51092]1610 int vrc = STAMR3Snapshot(ptrVM.rawUVM(), aPattern.c_str(), &pszSnapshot, NULL,
[31539]1611 !!aWithDescriptions);
[21878]1612 if (RT_FAILURE(vrc))
[14627]1613 return vrc == VERR_NO_MEMORY ? E_OUTOFMEMORY : E_FAIL;
1614
1615 /** @todo this is horribly inefficient! And it's kinda difficult to tell whether it failed...
1616 * Must use UTF-8 or ASCII here and completely avoid these two extra copy operations.
1617 * Until that's done, this method is kind of useless for debugger statistics GUI because
1618 * of the amount statistics in a debug build. */
[51092]1619 aStats = Utf8Str(pszSnapshot);
[44347]1620 STAMR3SnapshotFree(ptrVM.rawUVM(), pszSnapshot);
[14627]1621
1622 return S_OK;
1623}
1624
1625
1626// public methods only for internal purposes
1627/////////////////////////////////////////////////////////////////////////////
1628
[51092]1629void MachineDebugger::i_flushQueuedSettings()
[1]1630{
[14627]1631 mFlushMode = true;
[63147]1632 if (mSingleStepQueued != -1)
[1]1633 {
[39712]1634 COMSETTER(SingleStep)(mSingleStepQueued);
[63147]1635 mSingleStepQueued = -1;
[1]1636 }
[46423]1637 for (unsigned i = 0; i < EMEXECPOLICY_END; i++)
1638 if (maiQueuedEmExecPolicyParams[i] != UINT8_MAX)
1639 {
[51092]1640 i_setEmExecPolicyProperty((EMEXECPOLICY)i, RT_BOOL(maiQueuedEmExecPolicyParams[i]));
[46423]1641 maiQueuedEmExecPolicyParams[i] = UINT8_MAX;
1642 }
[63147]1643 if (mPatmEnabledQueued != -1)
[1]1644 {
[39712]1645 COMSETTER(PATMEnabled)(mPatmEnabledQueued);
[63147]1646 mPatmEnabledQueued = -1;
[1]1647 }
[63147]1648 if (mCsamEnabledQueued != -1)
[1]1649 {
[39712]1650 COMSETTER(CSAMEnabled)(mCsamEnabledQueued);
[63147]1651 mCsamEnabledQueued = -1;
[1]1652 }
[63147]1653 if (mLogEnabledQueued != -1)
[1]1654 {
[39712]1655 COMSETTER(LogEnabled)(mLogEnabledQueued);
[63147]1656 mLogEnabledQueued = -1;
[1]1657 }
[63147]1658 if (mVirtualTimeRateQueued != UINT32_MAX)
[444]1659 {
[39712]1660 COMSETTER(VirtualTimeRate)(mVirtualTimeRateQueued);
[63147]1661 mVirtualTimeRateQueued = UINT32_MAX;
[444]1662 }
[14627]1663 mFlushMode = false;
[1]1664}
1665
1666// private methods
[14627]1667/////////////////////////////////////////////////////////////////////////////
1668
[51092]1669bool MachineDebugger::i_queueSettings() const
[14627]1670{
1671 if (!mFlushMode)
1672 {
1673 // check if the machine is running
1674 MachineState_T machineState;
[39712]1675 mParent->COMGETTER(State)(&machineState);
[24301]1676 switch (machineState)
1677 {
[14627]1678 // queue the request
[24301]1679 default:
1680 return true;
1681
1682 case MachineState_Running:
1683 case MachineState_Paused:
1684 case MachineState_Stuck:
1685 case MachineState_LiveSnapshotting:
1686 case MachineState_Teleporting:
1687 break;
1688 }
[14627]1689 }
1690 return false;
1691}
[14772]1692/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use