VirtualBox

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

Last change on this file since 45029 was 44399, checked in by vboxsync, 12 years ago

DBGF,DBGC,++: PVM -> PUVM. Some refactoring and cleanup as well.

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