VirtualBox

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

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

EM: pVM -> pUVM for main, mark as many as possible interfaces module internal.

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

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